Merge from vendor branch SENDMAIL:
[dragonfly.git] / contrib / bind-9.3 / lib / isc / unix / ifiter_ioctl.c
1 /*
2  * Copyright (C) 2004-2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-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_ioctl.c,v 1.19.2.5.2.19 2006/02/03 23:51:37 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_flags iflr_flags
42 #define ss_family sa_family
43 #define LIFREQ if_laddrreq
44 #else
45 #define LIFREQ lifreq
46 #endif
47 #endif
48
49 #define IFITER_MAGIC            ISC_MAGIC('I', 'F', 'I', 'T')
50 #define VALID_IFITER(t)         ISC_MAGIC_VALID(t, IFITER_MAGIC)
51
52 #define ISC_IF_INET6_SZ \
53     sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
54
55 struct isc_interfaceiter {
56         unsigned int            magic;          /* Magic number. */
57         isc_mem_t               *mctx;
58         int                     mode;
59         int                     socket;
60         struct ifconf           ifc;
61         void                    *buf;           /* Buffer for sysctl data. */
62         unsigned int            bufsize;        /* Bytes allocated. */
63         unsigned int            pos;            /* Current offset in
64                                                    SIOCGIFCONF data */
65 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
66         int                     socket6;
67         struct LIFCONF          lifc;
68         void                    *buf6;          /* Buffer for sysctl data. */
69         unsigned int            bufsize6;       /* Bytes allocated. */
70         unsigned int            pos6;           /* Current offset in
71                                                    SIOCGLIFCONF data */
72         isc_result_t            result6;        /* Last result code. */
73         isc_boolean_t           first6;
74 #endif
75 #ifdef HAVE_TRUCLUSTER
76         int                     clua_context;   /* Cluster alias context */
77         isc_boolean_t           clua_done;
78         struct sockaddr         clua_sa;
79 #endif
80 #ifdef  __linux
81         FILE *                  proc;
82         char                    entry[ISC_IF_INET6_SZ];
83         isc_result_t            valid;
84         isc_boolean_t           first;
85 #endif
86         isc_interface_t         current;        /* Current interface data. */
87         isc_result_t            result;         /* Last result code. */
88 };
89
90 #ifdef HAVE_TRUCLUSTER
91 #include <clua/clua.h>
92 #include <sys/socket.h>
93 #endif
94
95
96 /*
97  * Size of buffer for SIOCGLIFCONF, in bytes.  We assume no sane system
98  * will have more than a megabyte of interface configuration data.
99  */
100 #define IFCONF_BUFSIZE_INITIAL  4096
101 #define IFCONF_BUFSIZE_MAX      1048576
102
103 #ifdef __linux
104 #ifndef IF_NAMESIZE
105 # ifdef IFNAMSIZ
106 #  define IF_NAMESIZE  IFNAMSIZ  
107 # else
108 #  define IF_NAMESIZE 16
109 # endif
110 #endif
111 #endif
112
113 static isc_result_t
114 getbuf4(isc_interfaceiter_t *iter) {
115         char strbuf[ISC_STRERRORSIZE];
116
117         iter->bufsize = IFCONF_BUFSIZE_INITIAL;
118
119         for (;;) {
120                 iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
121                 if (iter->buf == NULL)
122                         return (ISC_R_NOMEMORY);
123
124                 memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
125                 iter->ifc.ifc_len = iter->bufsize;
126                 iter->ifc.ifc_buf = iter->buf;
127                 /*
128                  * Ignore the HP/UX warning about "interger overflow during
129                  * conversion".  It comes from its own macro definition,
130                  * and is really hard to shut up.
131                  */
132                 if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
133                     == -1) {
134                         if (errno != EINVAL) {
135                                 isc__strerror(errno, strbuf, sizeof(strbuf));
136                                 UNEXPECTED_ERROR(__FILE__, __LINE__,
137                                                  isc_msgcat_get(isc_msgcat,
138                                                         ISC_MSGSET_IFITERIOCTL,
139                                                         ISC_MSG_GETIFCONFIG,
140                                                         "get interface "
141                                                         "configuration: %s"),
142                                                  strbuf);
143                                 goto unexpected;
144                         }
145                         /*
146                          * EINVAL.  Retry with a bigger buffer.
147                          */
148                 } else {
149                         /*
150                          * The ioctl succeeded.
151                          * Some OS's just return what will fit rather
152                          * than set EINVAL if the buffer is too small
153                          * to fit all the interfaces in.  If
154                          * ifc.lifc_len is too near to the end of the
155                          * buffer we will grow it just in case and
156                          * retry.
157                          */
158                         if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
159                             < iter->bufsize)
160                                 break;
161                 }
162                 if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
163                         UNEXPECTED_ERROR(__FILE__, __LINE__,
164                                          isc_msgcat_get(isc_msgcat,
165                                                         ISC_MSGSET_IFITERIOCTL,
166                                                         ISC_MSG_BUFFERMAX,
167                                                         "get interface "
168                                                         "configuration: "
169                                                         "maximum buffer "
170                                                         "size exceeded"));
171                         goto unexpected;
172                 }
173                 isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
174
175                 iter->bufsize *= 2;
176         }
177         return (ISC_R_SUCCESS);
178
179  unexpected:
180         isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
181         iter->buf = NULL;
182         return (ISC_R_UNEXPECTED);
183 }
184
185 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
186 static isc_result_t
187 getbuf6(isc_interfaceiter_t *iter) {
188         char strbuf[ISC_STRERRORSIZE];
189         isc_result_t result;
190
191         iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
192
193         for (;;) {
194                 iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
195                 if (iter->buf6 == NULL)
196                         return (ISC_R_NOMEMORY);
197
198                 memset(&iter->lifc, 0, sizeof(iter->lifc));
199 #ifdef ISC_HAVE_LIFC_FAMILY
200                 iter->lifc.lifc_family = AF_INET6;
201 #endif
202 #ifdef ISC_HAVE_LIFC_FLAGS
203                 iter->lifc.lifc_flags = 0;
204 #endif
205                 iter->lifc.lifc_len = iter->bufsize6;
206                 iter->lifc.lifc_buf = iter->buf6;
207                 /*
208                  * Ignore the HP/UX warning about "interger overflow during
209                  * conversion".  It comes from its own macro definition,
210                  * and is really hard to shut up.
211                  */
212                 if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
213                     == -1) {
214 #ifdef __hpux
215                         /*
216                          * IPv6 interface scanning is not available on all
217                          * kernels w/ IPv6 sockets.
218                          */
219                         if (errno == ENOENT) {
220                                 isc__strerror(errno, strbuf, sizeof(strbuf));
221                                 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
222                                               ISC_LOGMODULE_INTERFACE,
223                                               ISC_LOG_DEBUG(1),
224                                               isc_msgcat_get(isc_msgcat,
225                                                         ISC_MSGSET_IFITERIOCTL,
226                                                         ISC_MSG_GETIFCONFIG,
227                                                         "get interface "
228                                                         "configuration: %s"),
229                                                strbuf);
230                                 result = ISC_R_FAILURE;
231                                 goto cleanup;
232                         }
233 #endif
234                         if (errno != EINVAL) {
235                                 isc__strerror(errno, strbuf, sizeof(strbuf));
236                                 UNEXPECTED_ERROR(__FILE__, __LINE__,
237                                                  isc_msgcat_get(isc_msgcat,
238                                                         ISC_MSGSET_IFITERIOCTL,
239                                                         ISC_MSG_GETIFCONFIG,
240                                                         "get interface "
241                                                         "configuration: %s"),
242                                                  strbuf);
243                                 result = ISC_R_UNEXPECTED;
244                                 goto cleanup;
245                         }
246                         /*
247                          * EINVAL.  Retry with a bigger buffer.
248                          */
249                 } else {
250                         /*
251                          * The ioctl succeeded.
252                          * Some OS's just return what will fit rather
253                          * than set EINVAL if the buffer is too small
254                          * to fit all the interfaces in.  If
255                          * ifc.ifc_len is too near to the end of the
256                          * buffer we will grow it just in case and
257                          * retry.
258                          */
259                         if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
260                             < iter->bufsize6)
261                                 break;
262                 }
263                 if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
264                         UNEXPECTED_ERROR(__FILE__, __LINE__,
265                                          isc_msgcat_get(isc_msgcat,
266                                                         ISC_MSGSET_IFITERIOCTL,
267                                                         ISC_MSG_BUFFERMAX,
268                                                         "get interface "
269                                                         "configuration: "
270                                                         "maximum buffer "
271                                                         "size exceeded"));
272                         result = ISC_R_UNEXPECTED;
273                         goto cleanup;
274                 }
275                 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
276
277                 iter->bufsize6 *= 2;
278         }
279
280         if (iter->lifc.lifc_len != 0)
281                 iter->mode = 6;
282         return (ISC_R_SUCCESS);
283
284  cleanup:
285         isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
286         iter->buf6 = NULL;
287         return (result);
288 }
289 #endif
290
291 isc_result_t
292 isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
293         isc_interfaceiter_t *iter;
294         isc_result_t result;
295         char strbuf[ISC_STRERRORSIZE];
296
297         REQUIRE(mctx != NULL);
298         REQUIRE(iterp != NULL);
299         REQUIRE(*iterp == NULL);
300
301         iter = isc_mem_get(mctx, sizeof(*iter));
302         if (iter == NULL)
303                 return (ISC_R_NOMEMORY);
304
305         iter->mctx = mctx;
306         iter->mode = 4;
307         iter->buf = NULL;
308         iter->pos = (unsigned int) -1;
309 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
310         iter->buf6 = NULL;
311         iter->pos6 = (unsigned int) -1;
312         iter->result6 = ISC_R_NOMORE;
313         iter->socket6 = -1;
314         iter->first6 = ISC_FALSE;
315 #endif
316
317         /*
318          * Get the interface configuration, allocating more memory if
319          * necessary.
320          */
321
322 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
323         result = isc_net_probeipv6();
324         if (result == ISC_R_SUCCESS) {
325                 /*
326                  * Create an unbound datagram socket to do the SIOCGLIFCONF
327                  * ioctl on.  HP/UX requires an AF_INET6 socket for
328                  * SIOCGLIFCONF to get IPv6 addresses.
329                  */
330                 if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
331                         isc__strerror(errno, strbuf, sizeof(strbuf));
332                         UNEXPECTED_ERROR(__FILE__, __LINE__,
333                                          isc_msgcat_get(isc_msgcat,
334                                                         ISC_MSGSET_IFITERIOCTL,
335                                                         ISC_MSG_MAKESCANSOCKET,
336                                                         "making interface "
337                                                         "scan socket: %s"),
338                                          strbuf);
339                         result = ISC_R_UNEXPECTED;
340                         goto socket6_failure;
341                 }
342                 result = iter->result6 = getbuf6(iter);
343                 if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
344                         goto ioctl6_failure;
345         }
346 #endif
347         if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
348                 isc__strerror(errno, strbuf, sizeof(strbuf));
349                 UNEXPECTED_ERROR(__FILE__, __LINE__,
350                                  isc_msgcat_get(isc_msgcat,
351                                                 ISC_MSGSET_IFITERIOCTL,
352                                                 ISC_MSG_MAKESCANSOCKET,
353                                                 "making interface "
354                                                 "scan socket: %s"),
355                                  strbuf);
356                 result = ISC_R_UNEXPECTED;
357                 goto socket_failure;
358         }
359         result = getbuf4(iter);
360         if (result != ISC_R_SUCCESS)
361                 goto ioctl_failure;
362
363         /*
364          * A newly created iterator has an undefined position
365          * until isc_interfaceiter_first() is called.
366          */
367 #ifdef HAVE_TRUCLUSTER
368         iter->clua_context = -1;
369         iter->clua_done = ISC_TRUE;
370 #endif
371 #ifdef __linux
372         iter->proc = fopen("/proc/net/if_inet6", "r");
373         iter->valid = ISC_R_FAILURE;
374         iter->first = ISC_FALSE;
375 #endif
376         iter->result = ISC_R_FAILURE;
377
378         iter->magic = IFITER_MAGIC;
379         *iterp = iter;
380         return (ISC_R_SUCCESS);
381
382  ioctl_failure:
383         if (iter->buf != NULL)
384                 isc_mem_put(mctx, iter->buf, iter->bufsize);
385         (void) close(iter->socket);
386
387  socket_failure:
388 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
389         if (iter->buf6 != NULL)
390                 isc_mem_put(mctx, iter->buf6, iter->bufsize6);
391   ioctl6_failure:
392         if (iter->socket6 != -1)
393                 (void) close(iter->socket6);
394   socket6_failure:
395 #endif
396  
397         isc_mem_put(mctx, iter, sizeof(*iter));
398         return (result);
399 }
400
401 #ifdef HAVE_TRUCLUSTER
402 static void
403 get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
404         dst->family = AF_INET;
405         memcpy(&dst->type.in, src, sizeof(struct in_addr));
406 }
407
408 static isc_result_t
409 internal_current_clusteralias(isc_interfaceiter_t *iter) {
410         struct clua_info ci;
411         if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
412                 return (ISC_R_IGNORE);
413         memset(&iter->current, 0, sizeof(iter->current));
414         iter->current.af = iter->clua_sa.sa_family;
415         memset(iter->current.name, 0, sizeof(iter->current.name));
416         sprintf(iter->current.name, "clua%d", ci.aliasid);
417         iter->current.flags = INTERFACE_F_UP;
418         get_inaddr(&iter->current.address, &ci.addr);
419         get_inaddr(&iter->current.netmask, &ci.netmask);
420         return (ISC_R_SUCCESS);
421 }
422 #endif
423
424 #ifdef __linux
425 static isc_result_t
426 linux_if_inet6_next(isc_interfaceiter_t *iter) {
427         if (iter->proc != NULL &&
428             fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL)
429                 iter->valid = ISC_R_SUCCESS;
430         else
431                 iter->valid = ISC_R_NOMORE;
432         return (iter->valid);
433 }
434
435 static void
436 linux_if_inet6_first(isc_interfaceiter_t *iter) {
437         if (iter->proc != NULL) {
438                 rewind(iter->proc);
439                 (void)linux_if_inet6_next(iter);
440         } else
441                 iter->valid = ISC_R_NOMORE;
442         iter->first = ISC_FALSE;
443 }
444
445 static isc_result_t
446 linux_if_inet6_current(isc_interfaceiter_t *iter) {
447         char address[33];
448         char name[IF_NAMESIZE+1];
449         struct in6_addr addr6;
450         int ifindex, prefix, flag3, flag4;
451         int res;
452         unsigned int i;
453
454         if (iter->valid != ISC_R_SUCCESS)
455                 return (iter->valid);
456         if (iter->proc == NULL) {
457                 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
458                               ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
459                               "/proc/net/if_inet6:iter->proc == NULL");
460                 return (ISC_R_FAILURE);
461         }
462
463         res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n",
464                      address, &ifindex, &prefix, &flag3, &flag4, name);
465         if (res != 6) {
466                 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
467                               ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
468                               "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
469                               res);
470                 return (ISC_R_FAILURE);
471         }
472         if (strlen(address) != 32) {
473                 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
474                               ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
475                               "/proc/net/if_inet6:strlen(%s) != 32", address);
476                 return (ISC_R_FAILURE);
477         }
478         for (i = 0; i < 16; i++) {
479                 unsigned char byte;
480                 static const char hex[] = "0123456789abcdef";
481                 byte = ((index(hex, address[i * 2]) - hex) << 4) |
482                        (index(hex, address[i * 2 + 1]) - hex);
483                 addr6.s6_addr[i] = byte;
484         }
485         iter->current.af = AF_INET6;
486         iter->current.flags = INTERFACE_F_UP;
487         isc_netaddr_fromin6(&iter->current.address, &addr6);
488         if (isc_netaddr_islinklocal(&iter->current.address)) {
489                 isc_netaddr_setzone(&iter->current.address,
490                                     (isc_uint32_t)ifindex);
491         }
492         for (i = 0; i < 16; i++) {
493                 if (prefix > 8) {
494                         addr6.s6_addr[i] = 0xff;
495                         prefix -= 8;
496                 } else {
497                         addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff;
498                         prefix = 0;
499                 }
500         }
501         isc_netaddr_fromin6(&iter->current.netmask, &addr6);
502         strncpy(iter->current.name, name, sizeof(iter->current.name));
503         return (ISC_R_SUCCESS);
504 }
505 #endif
506
507 /*
508  * Get information about the current interface to iter->current.
509  * If successful, return ISC_R_SUCCESS.
510  * If the interface has an unsupported address family, or if
511  * some operation on it fails, return ISC_R_IGNORE to make
512  * the higher-level iterator code ignore it.
513  */
514
515 static isc_result_t
516 internal_current4(isc_interfaceiter_t *iter) {
517         struct ifreq *ifrp;
518         struct ifreq ifreq;
519         int family;
520         char strbuf[ISC_STRERRORSIZE];
521 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
522         struct lifreq lifreq;
523 #else
524         char sabuf[256];
525 #endif
526         int i, bits, prefixlen;
527 #ifdef __linux
528         isc_result_t result;
529 #endif
530
531         REQUIRE(VALID_IFITER(iter));
532         REQUIRE(iter->ifc.ifc_len == 0 ||
533                 iter->pos < (unsigned int) iter->ifc.ifc_len);
534
535 #ifdef __linux
536         result = linux_if_inet6_current(iter);
537         if (result != ISC_R_NOMORE)
538                 return (result);
539         iter->first = ISC_TRUE;
540 #endif
541
542         if (iter->ifc.ifc_len == 0)
543                 return (ISC_R_NOMORE);
544
545         ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
546
547         memset(&ifreq, 0, sizeof(ifreq));
548         memcpy(&ifreq, ifrp, sizeof(ifreq));
549
550         family = ifreq.ifr_addr.sa_family;
551 #if defined(ISC_PLATFORM_HAVEIPV6)
552         if (family != AF_INET && family != AF_INET6)
553 #else
554         if (family != AF_INET)
555 #endif
556                 return (ISC_R_IGNORE);
557
558         memset(&iter->current, 0, sizeof(iter->current));
559         iter->current.af = family;
560
561         INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
562         memset(iter->current.name, 0, sizeof(iter->current.name));
563         memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
564
565         get_addr(family, &iter->current.address,
566                  (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
567
568         /*
569          * If the interface does not have a address ignore it.
570          */
571         switch (family) {
572         case AF_INET:
573                 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
574                         return (ISC_R_IGNORE);
575                 break;
576         case AF_INET6:
577                 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
578                            sizeof(in6addr_any)) == 0)
579                         return (ISC_R_IGNORE);
580                 break;
581         }
582
583         /*
584          * Get interface flags.
585          */
586
587         iter->current.flags = 0;
588
589         /*
590          * Ignore the HP/UX warning about "interger overflow during
591          * conversion.  It comes from its own macro definition,
592          * and is really hard to shut up.
593          */
594         if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
595                 isc__strerror(errno, strbuf, sizeof(strbuf));
596                 UNEXPECTED_ERROR(__FILE__, __LINE__,
597                                  "%s: getting interface flags: %s",
598                                  ifreq.ifr_name, strbuf);
599                 return (ISC_R_IGNORE);
600         }
601
602         if ((ifreq.ifr_flags & IFF_UP) != 0)
603                 iter->current.flags |= INTERFACE_F_UP;
604
605 #ifdef IFF_POINTOPOINT
606         if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
607                 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
608 #endif
609
610         if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
611                 iter->current.flags |= INTERFACE_F_LOOPBACK;
612
613         if (family == AF_INET)
614                 goto inet;
615
616 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
617         memset(&lifreq, 0, sizeof(lifreq));
618         memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
619         memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
620                sizeof(iter->current.address.type.in6));
621
622         if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
623                 isc__strerror(errno, strbuf, sizeof(strbuf));
624                 UNEXPECTED_ERROR(__FILE__, __LINE__,
625                                  "%s: getting interface address: %s",
626                                  ifreq.ifr_name, strbuf);
627                 return (ISC_R_IGNORE);
628         }
629         prefixlen = lifreq.lifr_addrlen;
630 #else
631         isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
632         isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
633                       ISC_LOGMODULE_INTERFACE,
634                       ISC_LOG_INFO,
635                       isc_msgcat_get(isc_msgcat,
636                                      ISC_MSGSET_IFITERIOCTL,
637                                      ISC_MSG_GETIFCONFIG,
638                                      "prefix length for %s is unknown "
639                                      "(assume 128)"), sabuf);
640         prefixlen = 128;
641 #endif
642
643         /*
644          * Netmask already zeroed.
645          */
646         iter->current.netmask.family = family;
647         for (i = 0; i < 16; i++) {
648                 if (prefixlen > 8) {
649                         bits = 0;
650                         prefixlen -= 8;
651                 } else {
652                         bits = 8 - prefixlen;
653                         prefixlen = 0;
654                 }
655                 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
656         }
657         return (ISC_R_SUCCESS);
658
659  inet:
660         if (family != AF_INET)
661                 return (ISC_R_IGNORE);
662 #ifdef IFF_POINTOPOINT
663         /*
664          * If the interface is point-to-point, get the destination address.
665          */
666         if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
667                 /*
668                  * Ignore the HP/UX warning about "interger overflow during
669                  * conversion.  It comes from its own macro definition,
670                  * and is really hard to shut up.
671                  */
672                 if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
673                     < 0) {
674                         isc__strerror(errno, strbuf, sizeof(strbuf));
675                         UNEXPECTED_ERROR(__FILE__, __LINE__,
676                                 isc_msgcat_get(isc_msgcat,
677                                                ISC_MSGSET_IFITERIOCTL,
678                                                ISC_MSG_GETDESTADDR,
679                                                "%s: getting "
680                                                "destination address: %s"),
681                                          ifreq.ifr_name, strbuf);
682                         return (ISC_R_IGNORE);
683                 }
684                 get_addr(family, &iter->current.dstaddress,
685                          (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
686         }
687 #endif
688
689         /*
690          * Get the network mask.
691          */
692         memset(&ifreq, 0, sizeof(ifreq));
693         memcpy(&ifreq, ifrp, sizeof(ifreq));
694         /*
695          * Ignore the HP/UX warning about "interger overflow during
696          * conversion.  It comes from its own macro definition,
697          * and is really hard to shut up.
698          */
699         if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
700                 isc__strerror(errno, strbuf, sizeof(strbuf));
701                 UNEXPECTED_ERROR(__FILE__, __LINE__,
702                         isc_msgcat_get(isc_msgcat,
703                                        ISC_MSGSET_IFITERIOCTL,
704                                        ISC_MSG_GETNETMASK,
705                                        "%s: getting netmask: %s"),
706                                        ifreq.ifr_name, strbuf);
707                 return (ISC_R_IGNORE);
708         }
709         get_addr(family, &iter->current.netmask,
710                  (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
711         return (ISC_R_SUCCESS);
712 }
713
714 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
715 static isc_result_t
716 internal_current6(isc_interfaceiter_t *iter) {
717         struct LIFREQ *ifrp;
718         struct LIFREQ lifreq;
719         int family;
720         char strbuf[ISC_STRERRORSIZE];
721         int fd;
722
723         REQUIRE(VALID_IFITER(iter));
724         if (iter->result6 != ISC_R_SUCCESS)
725                 return (iter->result6);
726         REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
727
728         ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
729
730         memset(&lifreq, 0, sizeof(lifreq));
731         memcpy(&lifreq, ifrp, sizeof(lifreq));
732
733         family = lifreq.lifr_addr.ss_family;
734 #ifdef ISC_PLATFORM_HAVEIPV6
735         if (family != AF_INET && family != AF_INET6)
736 #else
737         if (family != AF_INET)
738 #endif
739                 return (ISC_R_IGNORE);
740
741         memset(&iter->current, 0, sizeof(iter->current));
742         iter->current.af = family;
743
744         INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
745         memset(iter->current.name, 0, sizeof(iter->current.name));
746         memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
747
748         get_addr(family, &iter->current.address,
749                  (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
750
751         /*
752          * If the interface does not have a address ignore it.
753          */
754         switch (family) {
755         case AF_INET:
756                 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
757                         return (ISC_R_IGNORE);
758                 break;
759         case AF_INET6:
760                 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
761                            sizeof(in6addr_any)) == 0)
762                         return (ISC_R_IGNORE);
763                 break;
764         }
765
766         /*
767          * Get interface flags.
768          */
769
770         iter->current.flags = 0;
771
772         if (family == AF_INET6)
773                 fd = iter->socket6;
774         else
775                 fd = iter->socket;
776
777         /*
778          * Ignore the HP/UX warning about "interger overflow during
779          * conversion.  It comes from its own macro definition,
780          * and is really hard to shut up.
781          */
782         if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
783                 isc__strerror(errno, strbuf, sizeof(strbuf));
784                 UNEXPECTED_ERROR(__FILE__, __LINE__,
785                                  "%s: getting interface flags: %s",
786                                  lifreq.lifr_name, strbuf);
787                 return (ISC_R_IGNORE);
788         }
789
790         if ((lifreq.lifr_flags & IFF_UP) != 0)
791                 iter->current.flags |= INTERFACE_F_UP;
792
793 #ifdef IFF_POINTOPOINT
794         if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
795                 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
796 #endif
797
798         if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
799                 iter->current.flags |= INTERFACE_F_LOOPBACK;
800
801 #ifdef IFF_POINTOPOINT
802         /*
803          * If the interface is point-to-point, get the destination address.
804          */
805         if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
806                 /*
807                  * Ignore the HP/UX warning about "interger overflow during
808                  * conversion.  It comes from its own macro definition,
809                  * and is really hard to shut up.
810                  */
811                 if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
812                     < 0) {
813                         isc__strerror(errno, strbuf, sizeof(strbuf));
814                         UNEXPECTED_ERROR(__FILE__, __LINE__,
815                                 isc_msgcat_get(isc_msgcat,
816                                                ISC_MSGSET_IFITERIOCTL,
817                                                ISC_MSG_GETDESTADDR,
818                                                "%s: getting "
819                                                "destination address: %s"),
820                                          lifreq.lifr_name, strbuf);
821                         return (ISC_R_IGNORE);
822                 }
823                 get_addr(family, &iter->current.dstaddress,
824                          (struct sockaddr *)&lifreq.lifr_dstaddr,
825                          lifreq.lifr_name);
826         }
827 #endif
828
829         /*
830          * Get the network mask.  Netmask already zeroed.
831          */
832         memset(&lifreq, 0, sizeof(lifreq));
833         memcpy(&lifreq, ifrp, sizeof(lifreq));
834
835 #ifdef lifr_addrlen
836         /*
837          * Special case: if the system provides lifr_addrlen member, the
838          * netmask of an IPv6 address can be derived from the length, since
839          * an IPv6 address always has a contiguous mask.
840          */
841         if (family == AF_INET6) {
842                 int i, bits;
843
844                 iter->current.netmask.family = family;
845                 for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
846                         bits = lifreq.lifr_addrlen - i;
847                         bits = (bits < 8) ? (8 - bits) : 0;
848                         iter->current.netmask.type.in6.s6_addr[i / 8] =
849                                 (~0 << bits) & 0xff;
850                 }
851
852                 return (ISC_R_SUCCESS);
853         }
854 #endif
855
856         /*
857          * Ignore the HP/UX warning about "interger overflow during
858          * conversion.  It comes from its own macro definition,
859          * and is really hard to shut up.
860          */
861         if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
862                 isc__strerror(errno, strbuf, sizeof(strbuf));
863                 UNEXPECTED_ERROR(__FILE__, __LINE__,
864                                  isc_msgcat_get(isc_msgcat,
865                                                 ISC_MSGSET_IFITERIOCTL,
866                                                 ISC_MSG_GETNETMASK,
867                                                 "%s: getting netmask: %s"),
868                                  lifreq.lifr_name, strbuf);
869                 return (ISC_R_IGNORE);
870         }
871         get_addr(family, &iter->current.netmask,
872                  (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
873
874         return (ISC_R_SUCCESS);
875 }
876 #endif
877
878 static isc_result_t
879 internal_current(isc_interfaceiter_t *iter) {
880 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
881         if (iter->mode == 6) {
882                 iter->result6 = internal_current6(iter);
883                 if (iter->result6 != ISC_R_NOMORE)
884                         return (iter->result6);
885         }
886 #endif
887 #ifdef HAVE_TRUCLUSTER
888         if (!iter->clua_done)
889                 return(internal_current_clusteralias(iter));
890 #endif
891         return (internal_current4(iter));
892 }
893
894 /*
895  * Step the iterator to the next interface.  Unlike
896  * isc_interfaceiter_next(), this may leave the iterator
897  * positioned on an interface that will ultimately
898  * be ignored.  Return ISC_R_NOMORE if there are no more
899  * interfaces, otherwise ISC_R_SUCCESS.
900  */
901 static isc_result_t
902 internal_next4(isc_interfaceiter_t *iter) {
903 #ifdef ISC_PLATFORM_HAVESALEN
904         struct ifreq *ifrp;
905 #endif
906
907         REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
908
909 #ifdef __linux
910         if (linux_if_inet6_next(iter) == ISC_R_SUCCESS)
911                 return (ISC_R_SUCCESS);
912         if (!iter->first)
913                 return (ISC_R_SUCCESS);
914 #endif
915 #ifdef ISC_PLATFORM_HAVESALEN
916         ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
917
918         if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
919                 iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len;
920         else
921 #endif
922                 iter->pos += sizeof(struct ifreq);
923
924         if (iter->pos >= (unsigned int) iter->ifc.ifc_len)
925                 return (ISC_R_NOMORE);
926
927         return (ISC_R_SUCCESS);
928 }
929
930 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
931 static isc_result_t
932 internal_next6(isc_interfaceiter_t *iter) {
933 #ifdef ISC_PLATFORM_HAVESALEN
934         struct LIFREQ *ifrp;
935 #endif
936         
937         if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
938                 return (iter->result6);
939
940         REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
941
942 #ifdef ISC_PLATFORM_HAVESALEN
943         ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
944
945         if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
946                 iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
947         else
948 #endif
949                 iter->pos6 += sizeof(struct LIFREQ);
950
951         if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
952                 return (ISC_R_NOMORE);
953
954         return (ISC_R_SUCCESS);
955 }
956 #endif
957
958 static isc_result_t
959 internal_next(isc_interfaceiter_t *iter) {
960 #ifdef HAVE_TRUCLUSTER
961         int clua_result;
962 #endif
963 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
964         if (iter->mode == 6) {
965                 iter->result6 = internal_next6(iter);
966                 if (iter->result6 != ISC_R_NOMORE)
967                         return (iter->result6);
968                 if (iter->first6) {
969                         iter->first6 = ISC_FALSE;
970                         return (ISC_R_SUCCESS);
971                 }
972         }
973 #endif
974 #ifdef HAVE_TRUCLUSTER
975         if (!iter->clua_done) {
976                 clua_result = clua_getaliasaddress(&iter->clua_sa,
977                                                    &iter->clua_context);
978                 if (clua_result != CLUA_SUCCESS)
979                         iter->clua_done = ISC_TRUE;
980                 return (ISC_R_SUCCESS);
981         }
982 #endif
983         return (internal_next4(iter));
984 }
985
986 static void
987 internal_destroy(isc_interfaceiter_t *iter) {
988         (void) close(iter->socket);
989 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
990         if (iter->socket6 != -1)
991                 (void) close(iter->socket6);
992         if (iter->buf6 != NULL) {
993                 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
994         }
995 #endif
996 #ifdef __linux
997         if (iter->proc != NULL)
998                 fclose(iter->proc);
999 #endif
1000 }
1001
1002 static
1003 void internal_first(isc_interfaceiter_t *iter) {
1004 #ifdef HAVE_TRUCLUSTER
1005         int clua_result;
1006 #endif
1007         iter->pos = 0;
1008 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1009         iter->pos6 = 0;
1010         if (iter->result6 == ISC_R_NOMORE)
1011                 iter->result6 = ISC_R_SUCCESS;
1012         iter->first6 = ISC_TRUE;
1013 #endif
1014 #ifdef HAVE_TRUCLUSTER
1015         iter->clua_context = 0;
1016         clua_result = clua_getaliasaddress(&iter->clua_sa,
1017                                            &iter->clua_context);
1018         iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
1019 #endif
1020 #ifdef __linux
1021         linux_if_inet6_first(iter);
1022 #endif
1023 }