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
00026
00027 #include <sys/param.h>
00028 #include <sys/sysctl.h>
00029
00030 #include <net/route.h>
00031 #include <net/if_dl.h>
00032
00033
00034 #ifdef sgi
00035 #define ROUNDUP(a) ((a) > 0 ? \
00036 (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) : \
00037 sizeof(__uint64_t))
00038 #else
00039 #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
00040 : sizeof(long))
00041 #endif
00042
00043 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'S')
00044 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
00045
00046 struct isc_interfaceiter {
00047 unsigned int magic;
00048 isc_mem_t *mctx;
00049 void *buf;
00050 unsigned int bufsize;
00051 unsigned int bufused;
00052 unsigned int pos;
00053
00054 isc_interface_t current;
00055 isc_result_t result;
00056 };
00057
00058 static int mib[6] = {
00059 CTL_NET,
00060 PF_ROUTE,
00061 0,
00062 0,
00063 NET_RT_IFLIST,
00064 0
00065 };
00066
00067 isc_result_t
00068 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
00069 isc_interfaceiter_t *iter;
00070 isc_result_t result;
00071 size_t bufsize;
00072 size_t bufused;
00073 char strbuf[ISC_STRERRORSIZE];
00074
00075 REQUIRE(mctx != NULL);
00076 REQUIRE(iterp != NULL);
00077 REQUIRE(*iterp == NULL);
00078
00079 iter = isc_mem_get(mctx, sizeof(*iter));
00080 if (iter == NULL)
00081 return (ISC_R_NOMEMORY);
00082
00083 iter->mctx = mctx;
00084 iter->buf = 0;
00085
00086
00087
00088
00089 bufsize = 0;
00090 if (sysctl(mib, 6, NULL, &bufsize, NULL, (size_t) 0) < 0) {
00091 isc__strerror(errno, strbuf, sizeof(strbuf));
00092 UNEXPECTED_ERROR(__FILE__, __LINE__,
00093 isc_msgcat_get(isc_msgcat,
00094 ISC_MSGSET_IFITERSYSCTL,
00095 ISC_MSG_GETIFLISTSIZE,
00096 "getting interface "
00097 "list size: sysctl: %s"),
00098 strbuf);
00099 result = ISC_R_UNEXPECTED;
00100 goto failure;
00101 }
00102 iter->bufsize = bufsize;
00103
00104 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
00105 if (iter->buf == NULL) {
00106 result = ISC_R_NOMEMORY;
00107 goto failure;
00108 }
00109
00110 bufused = bufsize;
00111 if (sysctl(mib, 6, iter->buf, &bufused, NULL, (size_t) 0) < 0) {
00112 isc__strerror(errno, strbuf, sizeof(strbuf));
00113 UNEXPECTED_ERROR(__FILE__, __LINE__,
00114 isc_msgcat_get(isc_msgcat,
00115 ISC_MSGSET_IFITERSYSCTL,
00116 ISC_MSG_GETIFLIST,
00117 "getting interface list: "
00118 "sysctl: %s"),
00119 strbuf);
00120 result = ISC_R_UNEXPECTED;
00121 goto failure;
00122 }
00123 iter->bufused = bufused;
00124 INSIST(iter->bufused <= iter->bufsize);
00125
00126
00127
00128
00129
00130 iter->pos = (unsigned int) -1;
00131 iter->result = ISC_R_FAILURE;
00132
00133 iter->magic = IFITER_MAGIC;
00134 *iterp = iter;
00135 return (ISC_R_SUCCESS);
00136
00137 failure:
00138 if (iter->buf != NULL)
00139 isc_mem_put(mctx, iter->buf, iter->bufsize);
00140 isc_mem_put(mctx, iter, sizeof(*iter));
00141 return (result);
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 static isc_result_t
00153 internal_current(isc_interfaceiter_t *iter) {
00154 struct ifa_msghdr *ifam, *ifam_end;
00155
00156 REQUIRE(VALID_IFITER(iter));
00157 REQUIRE (iter->pos < (unsigned int) iter->bufused);
00158
00159 ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
00160 ifam_end = (struct ifa_msghdr *) ((char *) iter->buf + iter->bufused);
00161
00162 if (ifam->ifam_type == RTM_IFINFO) {
00163 struct if_msghdr *ifm = (struct if_msghdr *) ifam;
00164 struct sockaddr_dl *sdl = (struct sockaddr_dl *) (ifm + 1);
00165 unsigned int namelen;
00166
00167 memset(&iter->current, 0, sizeof(iter->current));
00168
00169 namelen = sdl->sdl_nlen;
00170 if (namelen > sizeof(iter->current.name) - 1)
00171 namelen = sizeof(iter->current.name) - 1;
00172
00173 memset(iter->current.name, 0, sizeof(iter->current.name));
00174 memmove(iter->current.name, sdl->sdl_data, namelen);
00175
00176 iter->current.flags = 0;
00177
00178 if ((ifam->ifam_flags & IFF_UP) != 0)
00179 iter->current.flags |= INTERFACE_F_UP;
00180
00181 if ((ifam->ifam_flags & IFF_POINTOPOINT) != 0)
00182 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
00183
00184 if ((ifam->ifam_flags & IFF_LOOPBACK) != 0)
00185 iter->current.flags |= INTERFACE_F_LOOPBACK;
00186
00187
00188
00189
00190
00191 return (ISC_R_IGNORE);
00192 } else if (ifam->ifam_type == RTM_NEWADDR) {
00193 int i;
00194 int family;
00195 struct sockaddr *mask_sa = NULL;
00196 struct sockaddr *addr_sa = NULL;
00197 struct sockaddr *dst_sa = NULL;
00198
00199 struct sockaddr *sa = (struct sockaddr *)(ifam + 1);
00200 family = sa->sa_family;
00201
00202 for (i = 0; i < RTAX_MAX; i++)
00203 {
00204 if ((ifam->ifam_addrs & (1 << i)) == 0)
00205 continue;
00206
00207 INSIST(sa < (struct sockaddr *) ifam_end);
00208
00209 switch (i) {
00210 case RTAX_NETMASK:
00211 mask_sa = sa;
00212 break;
00213 case RTAX_IFA:
00214 addr_sa = sa;
00215 break;
00216 case RTAX_BRD:
00217 dst_sa = sa;
00218 break;
00219 }
00220 #ifdef ISC_PLATFORM_HAVESALEN
00221 sa = (struct sockaddr *)((char*)(sa)
00222 + ROUNDUP(sa->sa_len));
00223 #else
00224 #ifdef sgi
00225
00226
00227
00228 sa = (struct sockaddr *)((char*)(sa)
00229 + ROUNDUP(_FAKE_SA_LEN_DST(sa)));
00230 #else
00231
00232 sa = (struct sockaddr *)((char*)(sa)
00233 + ROUNDUP(sizeof(struct sockaddr)));
00234 #endif
00235 #endif
00236 }
00237
00238 if (addr_sa == NULL)
00239 return (ISC_R_IGNORE);
00240
00241 family = addr_sa->sa_family;
00242 if (family != AF_INET && family != AF_INET6)
00243 return (ISC_R_IGNORE);
00244
00245 iter->current.af = family;
00246
00247 get_addr(family, &iter->current.address, addr_sa,
00248 iter->current.name);
00249
00250 if (mask_sa != NULL)
00251 get_addr(family, &iter->current.netmask, mask_sa,
00252 iter->current.name);
00253
00254 if (dst_sa != NULL &&
00255 (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
00256 get_addr(family, &iter->current.dstaddress, dst_sa,
00257 iter->current.name);
00258
00259 return (ISC_R_SUCCESS);
00260 } else {
00261 printf("%s",
00262 isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERSYSCTL,
00263 ISC_MSG_UNEXPECTEDTYPE,
00264 "warning: unexpected interface list "
00265 "message type\n"));
00266 return (ISC_R_IGNORE);
00267 }
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 static isc_result_t
00278 internal_next(isc_interfaceiter_t *iter) {
00279 struct ifa_msghdr *ifam;
00280 REQUIRE (iter->pos < (unsigned int) iter->bufused);
00281
00282 ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
00283
00284 iter->pos += ifam->ifam_msglen;
00285
00286 if (iter->pos >= iter->bufused)
00287 return (ISC_R_NOMORE);
00288
00289 return (ISC_R_SUCCESS);
00290 }
00291
00292 static void
00293 internal_destroy(isc_interfaceiter_t *iter) {
00294 UNUSED(iter);
00295
00296
00297
00298 }
00299
00300 static
00301 void internal_first(isc_interfaceiter_t *iter) {
00302 iter->pos = 0;
00303 }