]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c
This commit was generated by cvs2svn to compensate for changes in r170242,
[FreeBSD/FreeBSD.git] / contrib / bind9 / lib / isc / unix / ifiter_getifaddrs.c
1 /*
2  * Copyright (C) 2004, 2005  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: ifiter_getifaddrs.c,v 1.4.18.2 2005/04/29 00:17:08 marka Exp $ */
19
20 /*! \file
21  * \brief
22  * Obtain the list of network interfaces using the getifaddrs(3) library.
23  */
24
25 #include <ifaddrs.h>
26
27 /*% Iterator Magic */
28 #define IFITER_MAGIC            ISC_MAGIC('I', 'F', 'I', 'G')
29 /*% Valid Iterator */
30 #define VALID_IFITER(t)         ISC_MAGIC_VALID(t, IFITER_MAGIC)
31
32 /*% Iterator structure */
33 struct isc_interfaceiter {
34         unsigned int            magic;          /*%< Magic number. */
35         isc_mem_t               *mctx;
36         void                    *buf;           /*%< (unused) */
37         unsigned int            bufsize;        /*%< (always 0) */
38         struct ifaddrs          *ifaddrs;       /*%< List of ifaddrs */
39         struct ifaddrs          *pos;           /*%< Ptr to current ifaddr */
40         isc_interface_t         current;        /*%< Current interface data. */
41         isc_result_t            result;         /*%< Last result code. */
42 };
43
44
45 isc_result_t
46 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
47         isc_interfaceiter_t *iter;
48         isc_result_t result;
49         char strbuf[ISC_STRERRORSIZE];
50
51         REQUIRE(mctx != NULL);
52         REQUIRE(iterp != NULL);
53         REQUIRE(*iterp == NULL);
54
55         iter = isc_mem_get(mctx, sizeof(*iter));
56         if (iter == NULL)
57                 return (ISC_R_NOMEMORY);
58
59         iter->mctx = mctx;
60         iter->buf = NULL;
61         iter->bufsize = 0;
62         iter->ifaddrs = NULL;
63
64         if (getifaddrs(&iter->ifaddrs) < 0) {
65                 isc__strerror(errno, strbuf, sizeof(strbuf));
66                 UNEXPECTED_ERROR(__FILE__, __LINE__,
67                                  isc_msgcat_get(isc_msgcat,
68                                                 ISC_MSGSET_IFITERGETIFADDRS,
69                                                 ISC_MSG_GETIFADDRS,
70                                                 "getting interface "
71                                                 "addresses: getifaddrs: %s"),
72                                  strbuf);
73                 result = ISC_R_UNEXPECTED;
74                 goto failure;
75         }
76
77         /*
78          * A newly created iterator has an undefined position
79          * until isc_interfaceiter_first() is called.
80          */
81         iter->pos = NULL;
82         iter->result = ISC_R_FAILURE;
83
84         iter->magic = IFITER_MAGIC;
85         *iterp = iter;
86         return (ISC_R_SUCCESS);
87
88  failure:
89         if (iter->ifaddrs != NULL) /* just in case */
90                 freeifaddrs(iter->ifaddrs);
91         isc_mem_put(mctx, iter, sizeof(*iter));
92         return (result);
93 }
94
95 /*
96  * Get information about the current interface to iter->current.
97  * If successful, return ISC_R_SUCCESS.
98  * If the interface has an unsupported address family,
99  * return ISC_R_IGNORE.
100  */
101
102 static isc_result_t
103 internal_current(isc_interfaceiter_t *iter) {
104         struct ifaddrs *ifa;
105         int family;
106         unsigned int namelen;
107
108         REQUIRE(VALID_IFITER(iter));
109
110         ifa = iter->pos;
111
112         INSIST(ifa != NULL);
113         INSIST(ifa->ifa_name != NULL);
114         INSIST(ifa->ifa_addr != NULL);
115
116         family = ifa->ifa_addr->sa_family;
117         if (family != AF_INET && family != AF_INET6)
118                 return (ISC_R_IGNORE);
119
120         memset(&iter->current, 0, sizeof(iter->current));
121
122         namelen = strlen(ifa->ifa_name);
123         if (namelen > sizeof(iter->current.name) - 1)
124                 namelen = sizeof(iter->current.name) - 1;
125
126         memset(iter->current.name, 0, sizeof(iter->current.name));
127         memcpy(iter->current.name, ifa->ifa_name, namelen);
128
129         iter->current.flags = 0;
130
131         if ((ifa->ifa_flags & IFF_UP) != 0)
132                 iter->current.flags |= INTERFACE_F_UP;
133
134         if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0)
135                 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
136
137         if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
138                 iter->current.flags |= INTERFACE_F_LOOPBACK;
139
140         iter->current.af = family;
141
142         get_addr(family, &iter->current.address, ifa->ifa_addr, ifa->ifa_name);
143
144         if (ifa->ifa_netmask != NULL)
145                 get_addr(family, &iter->current.netmask, ifa->ifa_netmask,
146                          ifa->ifa_name);
147
148         if (ifa->ifa_dstaddr != NULL &&
149             (iter->current.flags & IFF_POINTOPOINT) != 0)
150                 get_addr(family, &iter->current.dstaddress, ifa->ifa_dstaddr,
151                          ifa->ifa_name);
152
153         return (ISC_R_SUCCESS);
154 }
155
156 /*
157  * Step the iterator to the next interface.  Unlike
158  * isc_interfaceiter_next(), this may leave the iterator
159  * positioned on an interface that will ultimately
160  * be ignored.  Return ISC_R_NOMORE if there are no more
161  * interfaces, otherwise ISC_R_SUCCESS.
162  */
163 static isc_result_t
164 internal_next(isc_interfaceiter_t *iter) {
165         iter->pos = iter->pos->ifa_next;
166
167         if (iter->pos == NULL)
168                 return (ISC_R_NOMORE);
169
170         return (ISC_R_SUCCESS);
171 }
172
173 static void
174 internal_destroy(isc_interfaceiter_t *iter) {
175         if (iter->ifaddrs)
176                 freeifaddrs(iter->ifaddrs);
177         iter->ifaddrs = NULL;
178 }
179
180 static
181 void internal_first(isc_interfaceiter_t *iter) {
182         iter->pos = iter->ifaddrs;
183 }