00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <ifaddrs.h>
00026
00027
00028 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'G')
00029
00030 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
00031
00032 #ifdef __linux
00033 static isc_boolean_t seenv6 = ISC_FALSE;
00034 #endif
00035
00036
00037 struct isc_interfaceiter {
00038 unsigned int magic;
00039 isc_mem_t *mctx;
00040 void *buf;
00041 unsigned int bufsize;
00042 struct ifaddrs *ifaddrs;
00043 struct ifaddrs *pos;
00044 isc_interface_t current;
00045 isc_result_t result;
00046 #ifdef __linux
00047 FILE * proc;
00048 char entry[ISC_IF_INET6_SZ];
00049 isc_result_t valid;
00050 #endif
00051 };
00052
00053 isc_result_t
00054 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
00055 isc_interfaceiter_t *iter;
00056 isc_result_t result;
00057 char strbuf[ISC_STRERRORSIZE];
00058
00059 REQUIRE(mctx != NULL);
00060 REQUIRE(iterp != NULL);
00061 REQUIRE(*iterp == NULL);
00062
00063 iter = isc_mem_get(mctx, sizeof(*iter));
00064 if (iter == NULL)
00065 return (ISC_R_NOMEMORY);
00066
00067 iter->mctx = mctx;
00068 iter->buf = NULL;
00069 iter->bufsize = 0;
00070 iter->ifaddrs = NULL;
00071 #ifdef __linux
00072
00073
00074
00075
00076 if (!seenv6)
00077 iter->proc = fopen("/proc/net/if_inet6", "r");
00078 else
00079 iter->proc = NULL;
00080 iter->valid = ISC_R_FAILURE;
00081 #endif
00082
00083 if (getifaddrs(&iter->ifaddrs) < 0) {
00084 isc__strerror(errno, strbuf, sizeof(strbuf));
00085 UNEXPECTED_ERROR(__FILE__, __LINE__,
00086 isc_msgcat_get(isc_msgcat,
00087 ISC_MSGSET_IFITERGETIFADDRS,
00088 ISC_MSG_GETIFADDRS,
00089 "getting interface "
00090 "addresses: getifaddrs: %s"),
00091 strbuf);
00092 result = ISC_R_UNEXPECTED;
00093 goto failure;
00094 }
00095
00096
00097
00098
00099
00100 iter->pos = NULL;
00101 iter->result = ISC_R_FAILURE;
00102
00103 iter->magic = IFITER_MAGIC;
00104 *iterp = iter;
00105 return (ISC_R_SUCCESS);
00106
00107 failure:
00108 #ifdef __linux
00109 if (iter->proc != NULL)
00110 fclose(iter->proc);
00111 #endif
00112 if (iter->ifaddrs != NULL)
00113 freeifaddrs(iter->ifaddrs);
00114 isc_mem_put(mctx, iter, sizeof(*iter));
00115 return (result);
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125 static isc_result_t
00126 internal_current(isc_interfaceiter_t *iter) {
00127 struct ifaddrs *ifa;
00128 int family;
00129 unsigned int namelen;
00130
00131 REQUIRE(VALID_IFITER(iter));
00132
00133 ifa = iter->pos;
00134
00135 #ifdef __linux
00136 if (iter->pos == NULL)
00137 return (linux_if_inet6_current(iter));
00138 #endif
00139
00140 INSIST(ifa != NULL);
00141 INSIST(ifa->ifa_name != NULL);
00142
00143 if (ifa->ifa_addr == NULL)
00144 return (ISC_R_IGNORE);
00145
00146 family = ifa->ifa_addr->sa_family;
00147 if (family != AF_INET && family != AF_INET6)
00148 return (ISC_R_IGNORE);
00149
00150 #ifdef __linux
00151 if (family == AF_INET6)
00152 seenv6 = ISC_TRUE;
00153 #endif
00154
00155 memset(&iter->current, 0, sizeof(iter->current));
00156
00157 namelen = strlen(ifa->ifa_name);
00158 if (namelen > sizeof(iter->current.name) - 1)
00159 namelen = sizeof(iter->current.name) - 1;
00160
00161 memset(iter->current.name, 0, sizeof(iter->current.name));
00162 memmove(iter->current.name, ifa->ifa_name, namelen);
00163
00164 iter->current.flags = 0;
00165
00166 if ((ifa->ifa_flags & IFF_UP) != 0)
00167 iter->current.flags |= INTERFACE_F_UP;
00168
00169 if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0)
00170 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
00171
00172 if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
00173 iter->current.flags |= INTERFACE_F_LOOPBACK;
00174
00175 iter->current.af = family;
00176
00177 get_addr(family, &iter->current.address, ifa->ifa_addr, ifa->ifa_name);
00178
00179 if (ifa->ifa_netmask != NULL)
00180 get_addr(family, &iter->current.netmask, ifa->ifa_netmask,
00181 ifa->ifa_name);
00182
00183 if (ifa->ifa_dstaddr != NULL &&
00184 (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
00185 get_addr(family, &iter->current.dstaddress, ifa->ifa_dstaddr,
00186 ifa->ifa_name);
00187
00188 return (ISC_R_SUCCESS);
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198 static isc_result_t
00199 internal_next(isc_interfaceiter_t *iter) {
00200
00201 if (iter->pos != NULL)
00202 iter->pos = iter->pos->ifa_next;
00203 if (iter->pos == NULL) {
00204 #ifdef __linux
00205 if (!seenv6)
00206 return (linux_if_inet6_next(iter));
00207 #endif
00208 return (ISC_R_NOMORE);
00209 }
00210
00211 return (ISC_R_SUCCESS);
00212 }
00213
00214 static void
00215 internal_destroy(isc_interfaceiter_t *iter) {
00216
00217 #ifdef __linux
00218 if (iter->proc != NULL)
00219 fclose(iter->proc);
00220 iter->proc = NULL;
00221 #endif
00222 if (iter->ifaddrs)
00223 freeifaddrs(iter->ifaddrs);
00224 iter->ifaddrs = NULL;
00225 }
00226
00227 static
00228 void internal_first(isc_interfaceiter_t *iter) {
00229
00230 #ifdef __linux
00231 linux_if_inet6_first(iter);
00232 #endif
00233 iter->pos = iter->ifaddrs;
00234 }