]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c
Clone Kip's Xen on stable/6 tree so that I can work on improving FreeBSD/amd64
[FreeBSD/FreeBSD.git] / 6 / contrib / bind9 / lib / isc / unix / ifiter_getifaddrs.c
1 /*
2  * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or 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.2.68.6 2007/08/28 07:19:17 tbox Exp $ */
19
20 /*
21  * Obtain the list of network interfaces using the getifaddrs(3) library.
22  */
23
24 #include <ifaddrs.h>
25
26 #define IFITER_MAGIC            ISC_MAGIC('I', 'F', 'I', 'G')
27 #define VALID_IFITER(t)         ISC_MAGIC_VALID(t, IFITER_MAGIC)
28
29 struct isc_interfaceiter {
30         unsigned int            magic;          /* Magic number. */
31         isc_mem_t               *mctx;
32         void                    *buf;           /* (unused) */
33         unsigned int            bufsize;        /* (always 0) */
34         struct ifaddrs          *ifaddrs;       /* List of ifaddrs */
35         struct ifaddrs          *pos;           /* Ptr to current ifaddr */
36         isc_interface_t         current;        /* Current interface data. */
37         isc_result_t            result;         /* Last result code. */
38 };
39
40 isc_result_t
41 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
42         isc_interfaceiter_t *iter;
43         isc_result_t result;
44         char strbuf[ISC_STRERRORSIZE];
45
46         REQUIRE(mctx != NULL);
47         REQUIRE(iterp != NULL);
48         REQUIRE(*iterp == NULL);
49
50         iter = isc_mem_get(mctx, sizeof(*iter));
51         if (iter == NULL)
52                 return (ISC_R_NOMEMORY);
53
54         iter->mctx = mctx;
55         iter->buf = NULL;
56         iter->bufsize = 0;
57         iter->ifaddrs = NULL;
58
59         if (getifaddrs(&iter->ifaddrs) < 0) {
60                 isc__strerror(errno, strbuf, sizeof(strbuf));
61                 UNEXPECTED_ERROR(__FILE__, __LINE__,
62                                  isc_msgcat_get(isc_msgcat,
63                                                 ISC_MSGSET_IFITERGETIFADDRS,
64                                                 ISC_MSG_GETIFADDRS,
65                                                 "getting interface "
66                                                 "addresses: getifaddrs: %s"),
67                                  strbuf);
68                 result = ISC_R_UNEXPECTED;
69                 goto failure;
70         }
71
72         /*
73          * A newly created iterator has an undefined position
74          * until isc_interfaceiter_first() is called.
75          */
76         iter->pos = NULL;
77         iter->result = ISC_R_FAILURE;
78
79         iter->magic = IFITER_MAGIC;
80         *iterp = iter;
81         return (ISC_R_SUCCESS);
82
83  failure:
84         if (iter->ifaddrs != NULL) /* just in case */
85                 freeifaddrs(iter->ifaddrs);
86         isc_mem_put(mctx, iter, sizeof(*iter));
87         return (result);
88 }
89
90 /*
91  * Get information about the current interface to iter->current.
92  * If successful, return ISC_R_SUCCESS.
93  * If the interface has an unsupported address family,
94  * return ISC_R_IGNORE.
95  */
96
97 static isc_result_t
98 internal_current(isc_interfaceiter_t *iter) {
99         struct ifaddrs *ifa;
100         int family;
101         unsigned int namelen;
102
103         REQUIRE(VALID_IFITER(iter));
104
105         ifa = iter->pos;
106
107         INSIST(ifa != NULL);
108         INSIST(ifa->ifa_name != NULL);
109
110         if (ifa->ifa_addr == NULL)
111                 return (ISC_R_IGNORE);
112
113         family = ifa->ifa_addr->sa_family;
114         if (family != AF_INET && family != AF_INET6)
115                 return (ISC_R_IGNORE);
116
117         memset(&iter->current, 0, sizeof(iter->current));
118
119         namelen = strlen(ifa->ifa_name);
120         if (namelen > sizeof(iter->current.name) - 1)
121                 namelen = sizeof(iter->current.name) - 1;
122
123         memset(iter->current.name, 0, sizeof(iter->current.name));
124         memcpy(iter->current.name, ifa->ifa_name, namelen);
125
126         iter->current.flags = 0;
127
128         if ((ifa->ifa_flags & IFF_UP) != 0)
129                 iter->current.flags |= INTERFACE_F_UP;
130
131         if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0)
132                 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
133
134         if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
135                 iter->current.flags |= INTERFACE_F_LOOPBACK;
136
137         iter->current.af = family;
138
139         get_addr(family, &iter->current.address, ifa->ifa_addr, ifa->ifa_name);
140
141         if (ifa->ifa_netmask != NULL)
142                 get_addr(family, &iter->current.netmask, ifa->ifa_netmask,
143                          ifa->ifa_name);
144
145         if (ifa->ifa_dstaddr != NULL &&
146             (iter->current.flags & IFF_POINTOPOINT) != 0)
147                 get_addr(family, &iter->current.dstaddress, ifa->ifa_dstaddr,
148                          ifa->ifa_name);
149
150         return (ISC_R_SUCCESS);
151 }
152
153 /*
154  * Step the iterator to the next interface.  Unlike
155  * isc_interfaceiter_next(), this may leave the iterator
156  * positioned on an interface that will ultimately
157  * be ignored.  Return ISC_R_NOMORE if there are no more
158  * interfaces, otherwise ISC_R_SUCCESS.
159  */
160 static isc_result_t
161 internal_next(isc_interfaceiter_t *iter) {
162         iter->pos = iter->pos->ifa_next;
163
164         if (iter->pos == NULL)
165                 return (ISC_R_NOMORE);
166
167         return (ISC_R_SUCCESS);
168 }
169
170 static void
171 internal_destroy(isc_interfaceiter_t *iter) {
172         if (iter->ifaddrs)
173                 freeifaddrs(iter->ifaddrs);
174         iter->ifaddrs = NULL;
175 }
176
177 static
178 void internal_first(isc_interfaceiter_t *iter) {
179         iter->pos = iter->ifaddrs;
180 }