]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/libisc/ifiter_ioctl.c
This commit was generated by cvs2svn to compensate for changes in r170754,
[FreeBSD/FreeBSD.git] / contrib / ntp / libisc / ifiter_ioctl.c
1 /*
2  * Copyright (C) 1999-2001  Internet Software Consortium.
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
9  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
10  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
11  * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
13  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
14  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: ifiter_ioctl.c,v 1.34 2002/08/16 00:05:57 marka Exp $ */
19
20 /*
21  * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
22  * See netintro(4).
23  */
24
25 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
26 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
27 #define lifc_len iflc_len
28 #define lifc_buf iflc_buf
29 #define lifc_req iflc_req
30 #define LIFCONF if_laddrconf
31 #else
32 #define ISC_HAVE_LIFC_FAMILY 1
33 #define ISC_HAVE_LIFC_FLAGS 1
34 #define LIFCONF lifconf
35 #endif
36
37 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
38 #define lifr_addr iflr_addr
39 #define lifr_name iflr_name
40 #define lifr_dstaddr iflr_dstaddr
41 #define lifr_broadaddr iflr_broadaddr
42 #define lifr_flags iflr_flags
43 #define ss_family sa_family
44 #define LIFREQ if_laddrreq
45 #else
46 #define LIFREQ lifreq
47 #endif
48 #endif
49
50 #define IFITER_MAGIC            ISC_MAGIC('I', 'F', 'I', 'T')
51 #define VALID_IFITER(t)         ISC_MAGIC_VALID(t, IFITER_MAGIC)
52
53 struct isc_interfaceiter {
54         unsigned int            magic;          /* Magic number. */
55         isc_mem_t               *mctx;
56         int                     socket;
57         int                     mode;
58         struct ifconf           ifc;
59 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
60         struct LIFCONF          lifc;
61 #endif
62         void                    *buf;           /* Buffer for sysctl data. */
63         unsigned int            bufsize;        /* Bytes allocated. */
64 #ifdef HAVE_TRUCLUSTER
65         int                     clua_context;   /* Cluster alias context */
66 #endif
67         unsigned int            pos;            /* Current offset in
68                                                    SIOCGLIFCONF data */
69         isc_interface_t         current;        /* Current interface data. */
70         isc_result_t            result;         /* Last result code. */
71 };
72
73 #ifdef HAVE_TRUCLUSTER
74 #include <clua/clua.h>
75 #include <sys/socket.h>
76 #endif
77
78
79 /*
80  * Size of buffer for SIOCGLIFCONF, in bytes.  We assume no sane system
81  * will have more than a megabyte of interface configuration data.
82  */
83 #define IFCONF_BUFSIZE_INITIAL  4096
84 #define IFCONF_BUFSIZE_MAX      1048576
85
86 static isc_result_t
87 getbuf4(isc_interfaceiter_t *iter) {
88         char strbuf[ISC_STRERRORSIZE];
89
90         iter->bufsize = IFCONF_BUFSIZE_INITIAL;
91
92         for (;;) {
93                 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
94                 if (iter->buf == NULL)
95                         return (ISC_R_NOMEMORY);
96
97                 memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
98                 iter->ifc.ifc_len = iter->bufsize;
99                 iter->ifc.ifc_buf = iter->buf;
100                 /*
101                  * Ignore the HP/UX warning about "integer overflow during
102                  * conversion".  It comes from its own macro definition,
103                  * and is really hard to shut up.
104                  */
105                 if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
106                     == -1) {
107                         if (errno != EINVAL) {
108                                 isc__strerror(errno, strbuf, sizeof(strbuf));
109                                 UNEXPECTED_ERROR(__FILE__, __LINE__,
110                                                  isc_msgcat_get(isc_msgcat,
111                                                         ISC_MSGSET_IFITERIOCTL,
112                                                         ISC_MSG_GETIFCONFIG,
113                                                         "get interface "
114                                                         "configuration: %s"),
115                                                  strbuf);
116                                 goto unexpected;
117                         }
118                         /*
119                          * EINVAL.  Retry with a bigger buffer.
120                          */
121                 } else {
122                         /*
123                          * The ioctl succeeded.
124                          * Some OS's just return what will fit rather
125                          * than set EINVAL if the buffer is too small
126                          * to fit all the interfaces in.  If
127                          * ifc.lifc_len is too near to the end of the
128                          * buffer we will grow it just in case and
129                          * retry.
130                          */
131                         if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
132                             < iter->bufsize)
133                                 break;
134                 }
135                 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
136                         UNEXPECTED_ERROR(__FILE__, __LINE__,
137                                          isc_msgcat_get(isc_msgcat,
138                                                         ISC_MSGSET_IFITERIOCTL,
139                                                         ISC_MSG_BUFFERMAX,
140                                                         "get interface "
141                                                         "configuration: "
142                                                         "maximum buffer "
143                                                         "size exceeded"));
144                         goto unexpected;
145                 }
146                 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
147
148                 iter->bufsize *= 2;
149         }
150         iter->mode = 4;
151         return (ISC_R_SUCCESS);
152
153  unexpected:
154         isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
155         iter->buf = NULL;
156         return (ISC_R_UNEXPECTED);
157 }
158
159 static isc_result_t
160 getbuf6(isc_interfaceiter_t *iter) {
161 #if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
162         UNUSED(iter);
163         return (ISC_R_NOTIMPLEMENTED);
164 #else
165         char strbuf[ISC_STRERRORSIZE];
166         isc_result_t result;
167
168         iter->bufsize = IFCONF_BUFSIZE_INITIAL;
169
170         for (;;) {
171                 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
172                 if (iter->buf == NULL)
173                         return (ISC_R_NOMEMORY);
174
175                 memset(&iter->lifc.lifc_len, 0, sizeof(iter->lifc.lifc_len));
176 #ifdef ISC_HAVE_LIFC_FAMILY
177                 iter->lifc.lifc_family = AF_UNSPEC;
178 #endif
179 #ifdef ISC_HAVE_LIFC_FLAGS
180                 iter->lifc.lifc_flags = 0;
181 #endif
182                 iter->lifc.lifc_len = iter->bufsize;
183                 iter->lifc.lifc_buf = iter->buf;
184                 /*
185                  * Ignore the HP/UX warning about "integer overflow during
186                  * conversion".  It comes from its own macro definition,
187                  * and is really hard to shut up.
188                  */
189                 if (ioctl(iter->socket, SIOCGLIFCONF, (char *)&iter->lifc)
190                     == -1) {
191 #ifdef __hpux
192                         /*
193                          * IPv6 interface scanning is not available on all
194                          * kernels w/ IPv6 sockets.
195                          */
196                         if (errno == ENOENT) {
197                                 isc__strerror(errno, strbuf, sizeof(strbuf));
198                                 UNEXPECTED_ERROR(__FILE__, __LINE__,
199                                                  isc_msgcat_get(isc_msgcat,
200                                                         ISC_MSGSET_IFITERIOCTL,
201                                                         ISC_MSG_GETIFCONFIG,
202                                                         "get interface "
203                                                         "configuration: %s"),
204                                                  strbuf);
205                                 result = ISC_R_FAILURE;
206                                 goto cleanup;
207                         }
208 #endif
209                         if (errno != EINVAL) {
210                                 isc__strerror(errno, strbuf, sizeof(strbuf));
211                                 UNEXPECTED_ERROR(__FILE__, __LINE__,
212                                                  isc_msgcat_get(isc_msgcat,
213                                                         ISC_MSGSET_IFITERIOCTL,
214                                                         ISC_MSG_GETIFCONFIG,
215                                                         "get interface "
216                                                         "configuration: %s"),
217                                                  strbuf);
218                                 result = ISC_R_UNEXPECTED;
219                                 goto cleanup;
220                         }
221                         /*
222                          * EINVAL.  Retry with a bigger buffer.
223                          */
224                 } else {
225                         /*
226                          * The ioctl succeeded.
227                          * Some OS's just return what will fit rather
228                          * than set EINVAL if the buffer is too small
229                          * to fit all the interfaces in.  If
230                          * ifc.ifc_len is too near to the end of the
231                          * buffer we will grow it just in case and
232                          * retry.
233                          */
234                         if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
235                             < iter->bufsize)
236                                 break;
237                 }
238                 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
239                         UNEXPECTED_ERROR(__FILE__, __LINE__,
240                                          isc_msgcat_get(isc_msgcat,
241                                                         ISC_MSGSET_IFITERIOCTL,
242                                                         ISC_MSG_BUFFERMAX,
243                                                         "get interface "
244                                                         "configuration: "
245                                                         "maximum buffer "
246                                                         "size exceeded"));
247                         result = ISC_R_UNEXPECTED;
248                         goto cleanup;
249                 }
250                 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
251
252                 iter->bufsize *= 2;
253         }
254
255         iter->mode = 6;
256         return (ISC_R_SUCCESS);
257
258  cleanup:
259         isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
260         iter->buf = NULL;
261         return (result);
262 #endif
263 }
264
265 isc_result_t
266 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
267         isc_interfaceiter_t *iter;
268         isc_result_t result;
269         char strbuf[ISC_STRERRORSIZE];
270
271         REQUIRE(iterp != NULL);
272         REQUIRE(*iterp == NULL);
273
274         iter = isc_mem_get(mctx, sizeof(*iter));
275         if (iter == NULL)
276                 return (ISC_R_NOMEMORY);
277
278         iter->mctx = mctx;
279         iter->buf = NULL;
280         iter->mode = 0;
281
282         /*
283          * Create an unbound datagram socket to do the SIOCGLIFADDR ioctl on.
284          */
285         if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
286                 isc__strerror(errno, strbuf, sizeof(strbuf));
287                 UNEXPECTED_ERROR(__FILE__, __LINE__,
288                                  isc_msgcat_get(isc_msgcat,
289                                                 ISC_MSGSET_IFITERIOCTL,
290                                                 ISC_MSG_MAKESCANSOCKET,
291                                                 "making interface "
292                                                 "scan socket: %s"),
293                                  strbuf);
294                 result = ISC_R_UNEXPECTED;
295                 goto socket_failure;
296         }
297
298         /*
299          * Get the interface configuration, allocating more memory if
300          * necessary.
301          */
302
303         result = isc_net_probeipv6();
304         if (result == ISC_R_SUCCESS)
305                 result = getbuf6(iter);
306         if (result != ISC_R_SUCCESS)
307                 result = getbuf4(iter);
308         if (result != ISC_R_SUCCESS)
309                 goto ioctl_failure;
310
311         /*
312          * A newly created iterator has an undefined position
313          * until isc_interfaceiter_first() is called.
314          */
315 #ifdef HAVE_TRUCLUSTER
316         iter->clua_context = -1;
317 #endif
318         iter->pos = (unsigned int) -1;
319         iter->result = ISC_R_FAILURE;
320
321         iter->magic = IFITER_MAGIC;
322         *iterp = iter;
323         return (ISC_R_SUCCESS);
324
325  ioctl_failure:
326         if (iter->buf != NULL)
327                 isc_mem_put(mctx, iter->buf, iter->bufsize);
328         (void) close(iter->socket);
329
330  socket_failure:
331         isc_mem_put(mctx, iter, sizeof(*iter));
332         return (result);
333 }
334
335 #ifdef HAVE_TRUCLUSTER
336 static void
337 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
338         dst->family = AF_INET;
339         memcpy(&dst->type.in, src, sizeof(struct in_addr));
340 }
341
342 static isc_result_t
343 internal_current_clusteralias(isc_interfaceiter_t *iter) {
344         struct sockaddr sa;
345         struct clua_info ci;
346         while (clua_getaliasaddress(&sa, &iter->clua_context) == CLUA_SUCCESS) {
347                 if (clua_getaliasinfo(&sa, &ci) != CLUA_SUCCESS)
348                         continue;
349                 memset(&iter->current, 0, sizeof(iter->current));
350                 iter->current.af = sa.sa_family;
351                 memset(iter->current.name, 0, sizeof(iter->current.name));
352                 sprintf(iter->current.name, "clua%d", ci.aliasid);
353                 iter->current.flags = INTERFACE_F_UP;
354                 get_inaddr(&iter->current.address, &ci.addr);
355                 get_inaddr(&iter->current.netmask, &ci.netmask);
356                 return (ISC_R_SUCCESS);
357         }
358         return (ISC_R_NOMORE);
359 }
360 #endif
361
362 /*
363  * Get information about the current interface to iter->current.
364  * If successful, return ISC_R_SUCCESS.
365  * If the interface has an unsupported address family, or if
366  * some operation on it fails, return ISC_R_IGNORE to make
367  * the higher-level iterator code ignore it.
368  */
369
370 static isc_result_t
371 internal_current4(isc_interfaceiter_t *iter) {
372         struct ifreq *ifrp;
373         struct ifreq ifreq;
374         int family;
375         char strbuf[ISC_STRERRORSIZE];
376 #if !defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
377         struct if_laddrreq if_laddrreq;
378         int i, bits;
379 #endif
380
381         REQUIRE(VALID_IFITER(iter));
382         REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
383
384         ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
385
386         memset(&ifreq, 0, sizeof(ifreq));
387         memcpy(&ifreq, ifrp, sizeof(ifreq));
388
389         family = ifreq.ifr_addr.sa_family;
390 #if !defined (SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
391     defined(ISC_PLATFORM_HAVEIPV6)
392         if (family != AF_INET && family != AF_INET6)
393 #else
394         if (family != AF_INET)
395 #endif
396                 return (ISC_R_IGNORE);
397
398         memset(&iter->current, 0, sizeof(iter->current));
399         iter->current.af = family;
400
401         INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
402         memset(iter->current.name, 0, sizeof(iter->current.name));
403         memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
404
405         get_addr(family, &iter->current.address,
406                  (struct sockaddr *)&ifrp->ifr_addr);
407
408         /*
409          * If the interface does not have a address ignore it.
410          */
411         switch (family) {
412         case AF_INET:
413                 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
414                         return (ISC_R_IGNORE);
415                 break;
416         case AF_INET6:
417                 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
418                            sizeof(in6addr_any)) == 0)
419                         return (ISC_R_IGNORE);
420                 break;
421         }
422
423         /*
424          * Get interface flags.
425          */
426
427         iter->current.flags = 0;
428
429         /*
430          * Ignore the HP/UX warning about "integer overflow during
431          * conversion.  It comes from its own macro definition,
432          * and is really hard to shut up.
433          */
434         if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
435                 isc__strerror(errno, strbuf, sizeof(strbuf));
436                 UNEXPECTED_ERROR(__FILE__, __LINE__,
437                                  "%s: getting interface flags: %s",
438                                  ifreq.ifr_name, strbuf);
439                 return (ISC_R_IGNORE);
440         }
441
442         if ((ifreq.ifr_flags & IFF_UP) != 0)
443                 iter->current.flags |= INTERFACE_F_UP;
444
445         if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
446                 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
447
448         if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
449                 iter->current.flags |= INTERFACE_F_LOOPBACK;
450
451         if ((ifreq.ifr_flags & IFF_BROADCAST) != 0) {
452                 iter->current.flags |= INTERFACE_F_BROADCAST;
453         }
454
455 #ifdef IFF_MULTICAST
456         if ((ifreq.ifr_flags & IFF_MULTICAST) != 0) {
457                 iter->current.flags |= INTERFACE_F_MULTICAST;
458         }
459 #endif
460
461 #if !defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
462         if (family == AF_INET) 
463                 goto inet;
464
465         memset(&if_laddrreq, 0, sizeof(if_laddrreq));
466         memcpy(if_laddrreq.iflr_name, iter->current.name,
467                sizeof(if_laddrreq.iflr_name));
468         memcpy(&if_laddrreq.addr, &iter->current.address.type.in6,
469                sizeof(iter->current.address.type.in6));
470
471         if (ioctl(iter->socket, SIOCGLIFADDR, &if_laddrreq) < 0) {
472                 isc__strerror(errno, strbuf, sizeof(strbuf));
473                 UNEXPECTED_ERROR(__FILE__, __LINE__,
474                                  "%s: getting interface address: %s",
475                                  ifreq.ifr_name, strbuf);
476                 return (ISC_R_IGNORE);
477         }
478
479         /*
480          * Netmask already zeroed.
481          */
482         iter->current.netmask.family = family;
483         for (i = 0; i < 16; i++) {
484                 if (if_laddrreq.prefixlen > 8) {
485                         bits = 0;
486                         if_laddrreq.prefixlen -= 8;
487                 } else {
488                         bits = 8 - if_laddrreq.prefixlen;
489                         if_laddrreq.prefixlen = 0;
490                 }
491                 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
492         }
493         return (ISC_R_SUCCESS);
494
495  inet:
496 #endif
497         if (family != AF_INET)
498                 return (ISC_R_IGNORE);
499         /*
500          * If the interface is point-to-point, get the destination address.
501          */
502         if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
503                 /*
504                  * Ignore the HP/UX warning about "integer overflow during
505                  * conversion.  It comes from its own macro definition,
506                  * and is really hard to shut up.
507                  */
508                 if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
509                     < 0) {
510                         isc__strerror(errno, strbuf, sizeof(strbuf));
511                         UNEXPECTED_ERROR(__FILE__, __LINE__,
512                                 isc_msgcat_get(isc_msgcat,
513                                                ISC_MSGSET_IFITERIOCTL,
514                                                ISC_MSG_GETDESTADDR,
515                                                "%s: getting "
516                                                "destination address: %s"),
517                                          ifreq.ifr_name, strbuf);
518                         return (ISC_R_IGNORE);
519                 }
520                 get_addr(family, &iter->current.dstaddress,
521                          (struct sockaddr *)&ifreq.ifr_dstaddr);
522         }
523
524         if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) {
525                 /*
526                  * Ignore the HP/UX warning about "integer overflow during
527                  * conversion.  It comes from its own macro definition,
528                  * and is really hard to shut up.
529                  */
530                 if (ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq)
531                     < 0) {
532                         isc__strerror(errno, strbuf, sizeof(strbuf));
533                         UNEXPECTED_ERROR(__FILE__, __LINE__,
534                                 isc_msgcat_get(isc_msgcat,
535                                                ISC_MSGSET_IFITERIOCTL,
536                                                ISC_MSG_GETDESTADDR,
537                                                "%s: getting "
538                                                "broadcast address: %s"),
539                                          ifreq.ifr_name, strbuf);
540                         return (ISC_R_IGNORE);
541                 }
542                 get_addr(family, &iter->current.broadcast,
543                          (struct sockaddr *)&ifreq.ifr_broadaddr);
544         }
545         /*
546          * Get the network mask.
547          */
548         memset(&ifreq, 0, sizeof(ifreq));
549         memcpy(&ifreq, ifrp, sizeof(ifreq));
550         /*
551          * Ignore the HP/UX warning about "integer overflow during
552          * conversion.  It comes from its own macro definition,
553          * and is really hard to shut up.
554          */
555         if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq)
556             < 0) {
557                 isc__strerror(errno, strbuf, sizeof(strbuf));
558                 UNEXPECTED_ERROR(__FILE__, __LINE__,
559                         isc_msgcat_get(isc_msgcat,
560                                        ISC_MSGSET_IFITERIOCTL,
561                                        ISC_MSG_GETNETMASK,
562                                        "%s: getting netmask: %s"),
563                                        ifreq.ifr_name, strbuf);
564                 return (ISC_R_IGNORE);
565         }
566         get_addr(family, &iter->current.netmask,
567                  (struct sockaddr *)&ifreq.ifr_addr);
568         return (ISC_R_SUCCESS);
569 }
570
571 static isc_result_t
572 internal_current6(isc_interfaceiter_t *iter) {
573 #if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
574         UNUSED(iter);
575         return (ISC_R_NOTIMPLEMENTED);
576 #else
577         struct LIFREQ *ifrp;
578         struct LIFREQ lifreq;
579         int family;
580         char strbuf[ISC_STRERRORSIZE];
581
582         REQUIRE(VALID_IFITER(iter));
583         REQUIRE (iter->pos < (unsigned int) iter->lifc.lifc_len);
584
585         ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos);
586
587         memset(&lifreq, 0, sizeof(lifreq));
588         memcpy(&lifreq, ifrp, sizeof(lifreq));
589
590         family = lifreq.lifr_addr.ss_family;
591 #ifdef ISC_PLATFORM_HAVEIPV6
592         if (family != AF_INET && family != AF_INET6)
593 #else
594         if (family != AF_INET)
595 #endif
596                 return (ISC_R_IGNORE);
597
598         memset(&iter->current, 0, sizeof(iter->current));
599         iter->current.af = family;
600
601         INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
602         memset(iter->current.name, 0, sizeof(iter->current.name));
603         memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
604
605         get_addr(family, &iter->current.address,
606                  (struct sockaddr *)&lifreq.lifr_addr);
607
608         /*
609          * If the interface does not have a address ignore it.
610          */
611         switch (family) {
612         case AF_INET:
613                 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
614                         return (ISC_R_IGNORE);
615                 break;
616         case AF_INET6:
617                 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
618                            sizeof(in6addr_any)) == 0)
619                         return (ISC_R_IGNORE);
620                 break;
621         }
622
623         /*
624          * Get interface flags.
625          */
626
627         iter->current.flags = 0;
628
629         /*
630          * Ignore the HP/UX warning about "integer overflow during
631          * conversion.  It comes from its own macro definition,
632          * and is really hard to shut up.
633          */
634         if (ioctl(iter->socket, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
635
636                 /*
637                  * XXX This should be looked at further since it looks strange.
638                  * If we get an ENXIO then we ignore the error and not worry
639                  * about the flags.
640                  */
641                 if (errno != ENXIO) {
642                         isc__strerror(errno, strbuf, sizeof(strbuf));
643                         UNEXPECTED_ERROR(__FILE__, __LINE__,
644                                  "%s: getting interface flags: %s",
645                                  lifreq.lifr_name, strbuf);
646                         return (ISC_R_IGNORE);
647                 }
648         }
649
650         if ((lifreq.lifr_flags & IFF_UP) != 0)
651                 iter->current.flags |= INTERFACE_F_UP;
652
653         if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
654                 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
655
656         if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
657                 iter->current.flags |= INTERFACE_F_LOOPBACK;
658
659         /* 
660          * Note that IPv6 broadcast does not exist
661          * so don't check for IPv6 broadcast flag
662          */
663
664 #ifdef IFF_MULTICAST
665         if ((lifreq.lifr_flags & IFF_MULTICAST) != 0) {
666                 iter->current.flags |= INTERFACE_F_MULTICAST;
667         }
668 #endif
669
670         /*
671          * If the interface is point-to-point, get the destination address.
672          */
673         if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
674                 /*
675                  * Ignore the HP/UX warning about "interger overflow during
676                  * conversion.  It comes from its own macro definition,
677                  * and is really hard to shut up.
678                  */
679                 if (ioctl(iter->socket, SIOCGLIFDSTADDR, (char *)&lifreq)
680                     < 0) {
681                         isc__strerror(errno, strbuf, sizeof(strbuf));
682                         UNEXPECTED_ERROR(__FILE__, __LINE__,
683                                 isc_msgcat_get(isc_msgcat,
684                                                ISC_MSGSET_IFITERIOCTL,
685                                                ISC_MSG_GETDESTADDR,
686                                                "%s: getting "
687                                                "destination address: %s"),
688                                          lifreq.lifr_name, strbuf);
689                         return (ISC_R_IGNORE);
690                 }
691                 get_addr(family, &iter->current.dstaddress,
692                          (struct sockaddr *)&lifreq.lifr_dstaddr);
693         }
694
695
696         /*
697          * Get the network mask.
698          */
699         memset(&lifreq, 0, sizeof(lifreq));
700         memcpy(&lifreq, ifrp, sizeof(lifreq));
701         switch (family) {
702         case AF_INET:
703                 /*
704                  * Ignore the HP/UX warning about "integer overflow during
705                  * conversion.  It comes from its own macro definition,
706                  * and is really hard to shut up.
707                  */
708                 if (ioctl(iter->socket, SIOCGLIFNETMASK, (char *)&lifreq)
709                     < 0) {
710                         isc__strerror(errno, strbuf, sizeof(strbuf));
711                         UNEXPECTED_ERROR(__FILE__, __LINE__,
712                                 isc_msgcat_get(isc_msgcat,
713                                                ISC_MSGSET_IFITERIOCTL,
714                                                ISC_MSG_GETNETMASK,
715                                                "%s: getting netmask: %s"),
716                                          lifreq.lifr_name, strbuf);
717                         return (ISC_R_IGNORE);
718                 }
719                 get_addr(family, &iter->current.netmask,
720                          (struct sockaddr *)&lifreq.lifr_addr);
721                 break;
722         case AF_INET6: {
723 #ifdef lifr_addrlen
724                 int i, bits;
725
726                 /*
727                  * Netmask already zeroed.
728                  */
729                 iter->current.netmask.family = family;
730                 for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
731                         bits = lifreq.lifr_addrlen - i;
732                         bits = (bits < 8) ? (8 - bits) : 0;
733                         iter->current.netmask.type.in6.s6_addr[i / 8] =
734                                 (~0 << bits) & 0xff;
735                 }
736 #endif
737                 break;
738         }
739         }
740
741         return (ISC_R_SUCCESS);
742 #endif
743 }
744
745 static isc_result_t
746 internal_current(isc_interfaceiter_t *iter) {
747         if (iter->mode == 6)
748                 return (internal_current6(iter));
749         return (internal_current4(iter));
750 }
751
752 /*
753  * Step the iterator to the next interface.  Unlike
754  * isc_interfaceiter_next(), this may leave the iterator
755  * positioned on an interface that will ultimately
756  * be ignored.  Return ISC_R_NOMORE if there are no more
757  * interfaces, otherwise ISC_R_SUCCESS.
758  */
759 static isc_result_t
760 internal_next4(isc_interfaceiter_t *iter) {
761         struct ifreq *ifrp;
762
763         REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
764
765 #ifdef HAVE_TRUCLUSTER
766         if (internal_current_clusteralias(iter) == ISC_R_SUCCESS)
767                 return (ISC_R_SUCCESS);
768 #endif
769         ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
770
771 #ifdef ISC_PLATFORM_HAVESALEN
772         if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
773                 iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len;
774         else
775 #endif
776                 iter->pos += sizeof(*ifrp);
777
778         if (iter->pos >= (unsigned int) iter->ifc.ifc_len)
779                 return (ISC_R_NOMORE);
780
781         return (ISC_R_SUCCESS);
782 }
783
784 static isc_result_t
785 internal_next6(isc_interfaceiter_t *iter) {
786 #if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR)
787         UNUSED(iter);
788         return (ISC_R_NOTIMPLEMENTED);
789 #else
790         struct LIFREQ *ifrp;
791
792         REQUIRE (iter->pos < (unsigned int) iter->lifc.lifc_len);
793
794         ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos);
795
796 #ifdef ISC_PLATFORM_HAVESALEN
797         if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
798                 iter->pos += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
799         else
800 #endif
801                 iter->pos += sizeof(*ifrp);
802
803         if (iter->pos >= (unsigned int) iter->lifc.lifc_len)
804                 return (ISC_R_NOMORE);
805
806         return (ISC_R_SUCCESS);
807 #endif
808 }
809
810 static isc_result_t
811 internal_next(isc_interfaceiter_t *iter) {
812         if (iter->mode == 6)
813                 return (internal_next6(iter));
814         return (internal_next4(iter));
815 }
816
817 static void
818 internal_destroy(isc_interfaceiter_t *iter) {
819         (void) close(iter->socket);
820 }