Import of bind-9.3.2-P1
[dragonfly.git] / contrib / bind-9.3 / lib / isc / unix / ifiter_ioctl.c
1 /*
2  * Copyright (C) 2004, 2005  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.17 2005/10/14 02:13:07 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->pos < (unsigned int) iter->ifc.ifc_len);
533
534 #ifdef __linux
535         result = linux_if_inet6_current(iter);
536         if (result != ISC_R_NOMORE)
537                 return (result);
538         iter->first = ISC_TRUE;
539 #endif
540
541         ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
542
543         memset(&ifreq, 0, sizeof(ifreq));
544         memcpy(&ifreq, ifrp, sizeof(ifreq));
545
546         family = ifreq.ifr_addr.sa_family;
547 #if defined(ISC_PLATFORM_HAVEIPV6)
548         if (family != AF_INET && family != AF_INET6)
549 #else
550         if (family != AF_INET)
551 #endif
552                 return (ISC_R_IGNORE);
553
554         memset(&iter->current, 0, sizeof(iter->current));
555         iter->current.af = family;
556
557         INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
558         memset(iter->current.name, 0, sizeof(iter->current.name));
559         memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
560
561         get_addr(family, &iter->current.address,
562                  (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
563
564         /*
565          * If the interface does not have a address ignore it.
566          */
567         switch (family) {
568         case AF_INET:
569                 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
570                         return (ISC_R_IGNORE);
571                 break;
572         case AF_INET6:
573                 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
574                            sizeof(in6addr_any)) == 0)
575                         return (ISC_R_IGNORE);
576                 break;
577         }
578
579         /*
580          * Get interface flags.
581          */
582
583         iter->current.flags = 0;
584
585         /*
586          * Ignore the HP/UX warning about "interger overflow during
587          * conversion.  It comes from its own macro definition,
588          * and is really hard to shut up.
589          */
590         if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
591                 isc__strerror(errno, strbuf, sizeof(strbuf));
592                 UNEXPECTED_ERROR(__FILE__, __LINE__,
593                                  "%s: getting interface flags: %s",
594                                  ifreq.ifr_name, strbuf);
595                 return (ISC_R_IGNORE);
596         }
597
598         if ((ifreq.ifr_flags & IFF_UP) != 0)
599                 iter->current.flags |= INTERFACE_F_UP;
600
601 #ifdef IFF_POINTOPOINT
602         if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
603                 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
604 #endif
605
606         if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
607                 iter->current.flags |= INTERFACE_F_LOOPBACK;
608
609         if (family == AF_INET)
610                 goto inet;
611
612 #if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
613         memset(&lifreq, 0, sizeof(lifreq));
614         memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
615         memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
616                sizeof(iter->current.address.type.in6));
617
618         if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
619                 isc__strerror(errno, strbuf, sizeof(strbuf));
620                 UNEXPECTED_ERROR(__FILE__, __LINE__,
621                                  "%s: getting interface address: %s",
622                                  ifreq.ifr_name, strbuf);
623                 return (ISC_R_IGNORE);
624         }
625         prefixlen = lifreq.lifr_addrlen;
626 #else
627         isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
628         isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
629                       ISC_LOGMODULE_INTERFACE,
630                       ISC_LOG_INFO,
631                       isc_msgcat_get(isc_msgcat,
632                                      ISC_MSGSET_IFITERIOCTL,
633                                      ISC_MSG_GETIFCONFIG,
634                                      "prefix length for %s is unknown "
635                                      "(assume 128)"), sabuf);
636         prefixlen = 128;
637 #endif
638
639         /*
640          * Netmask already zeroed.
641          */
642         iter->current.netmask.family = family;
643         for (i = 0; i < 16; i++) {
644                 if (prefixlen > 8) {
645                         bits = 0;
646                         prefixlen -= 8;
647                 } else {
648                         bits = 8 - prefixlen;
649                         prefixlen = 0;
650                 }
651                 iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
652         }
653         return (ISC_R_SUCCESS);
654
655  inet:
656         if (family != AF_INET)
657                 return (ISC_R_IGNORE);
658 #ifdef IFF_POINTOPOINT
659         /*
660          * If the interface is point-to-point, get the destination address.
661          */
662         if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
663                 /*
664                  * Ignore the HP/UX warning about "interger overflow during
665                  * conversion.  It comes from its own macro definition,
666                  * and is really hard to shut up.
667                  */
668                 if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
669                     < 0) {
670                         isc__strerror(errno, strbuf, sizeof(strbuf));
671                         UNEXPECTED_ERROR(__FILE__, __LINE__,
672                                 isc_msgcat_get(isc_msgcat,
673                                                ISC_MSGSET_IFITERIOCTL,
674                                                ISC_MSG_GETDESTADDR,
675                                                "%s: getting "
676                                                "destination address: %s"),
677                                          ifreq.ifr_name, strbuf);
678                         return (ISC_R_IGNORE);
679                 }
680                 get_addr(family, &iter->current.dstaddress,
681                          (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
682         }
683 #endif
684
685         /*
686          * Get the network mask.
687          */
688         memset(&ifreq, 0, sizeof(ifreq));
689         memcpy(&ifreq, ifrp, sizeof(ifreq));
690         /*
691          * Ignore the HP/UX warning about "interger overflow during
692          * conversion.  It comes from its own macro definition,
693          * and is really hard to shut up.
694          */
695         if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
696                 isc__strerror(errno, strbuf, sizeof(strbuf));
697                 UNEXPECTED_ERROR(__FILE__, __LINE__,
698                         isc_msgcat_get(isc_msgcat,
699                                        ISC_MSGSET_IFITERIOCTL,
700                                        ISC_MSG_GETNETMASK,
701                                        "%s: getting netmask: %s"),
702                                        ifreq.ifr_name, strbuf);
703                 return (ISC_R_IGNORE);
704         }
705         get_addr(family, &iter->current.netmask,
706                  (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
707         return (ISC_R_SUCCESS);
708 }
709
710 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
711 static isc_result_t
712 internal_current6(isc_interfaceiter_t *iter) {
713         struct LIFREQ *ifrp;
714         struct LIFREQ lifreq;
715         int family;
716         char strbuf[ISC_STRERRORSIZE];
717         int fd;
718
719         REQUIRE(VALID_IFITER(iter));
720         if (iter->result6 != ISC_R_SUCCESS)
721                 return (iter->result6);
722         REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
723
724         ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
725
726         memset(&lifreq, 0, sizeof(lifreq));
727         memcpy(&lifreq, ifrp, sizeof(lifreq));
728
729         family = lifreq.lifr_addr.ss_family;
730 #ifdef ISC_PLATFORM_HAVEIPV6
731         if (family != AF_INET && family != AF_INET6)
732 #else
733         if (family != AF_INET)
734 #endif
735                 return (ISC_R_IGNORE);
736
737         memset(&iter->current, 0, sizeof(iter->current));
738         iter->current.af = family;
739
740         INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
741         memset(iter->current.name, 0, sizeof(iter->current.name));
742         memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
743
744         get_addr(family, &iter->current.address,
745                  (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
746
747         /*
748          * If the interface does not have a address ignore it.
749          */
750         switch (family) {
751         case AF_INET:
752                 if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
753                         return (ISC_R_IGNORE);
754                 break;
755         case AF_INET6:
756                 if (memcmp(&iter->current.address.type.in6, &in6addr_any,
757                            sizeof(in6addr_any)) == 0)
758                         return (ISC_R_IGNORE);
759                 break;
760         }
761
762         /*
763          * Get interface flags.
764          */
765
766         iter->current.flags = 0;
767
768         if (family == AF_INET6)
769                 fd = iter->socket6;
770         else
771                 fd = iter->socket;
772
773         /*
774          * Ignore the HP/UX warning about "interger overflow during
775          * conversion.  It comes from its own macro definition,
776          * and is really hard to shut up.
777          */
778         if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
779                 isc__strerror(errno, strbuf, sizeof(strbuf));
780                 UNEXPECTED_ERROR(__FILE__, __LINE__,
781                                  "%s: getting interface flags: %s",
782                                  lifreq.lifr_name, strbuf);
783                 return (ISC_R_IGNORE);
784         }
785
786         if ((lifreq.lifr_flags & IFF_UP) != 0)
787                 iter->current.flags |= INTERFACE_F_UP;
788
789 #ifdef IFF_POINTOPOINT
790         if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
791                 iter->current.flags |= INTERFACE_F_POINTTOPOINT;
792 #endif
793
794         if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
795                 iter->current.flags |= INTERFACE_F_LOOPBACK;
796
797 #ifdef IFF_POINTOPOINT
798         /*
799          * If the interface is point-to-point, get the destination address.
800          */
801         if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
802                 /*
803                  * Ignore the HP/UX warning about "interger overflow during
804                  * conversion.  It comes from its own macro definition,
805                  * and is really hard to shut up.
806                  */
807                 if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
808                     < 0) {
809                         isc__strerror(errno, strbuf, sizeof(strbuf));
810                         UNEXPECTED_ERROR(__FILE__, __LINE__,
811                                 isc_msgcat_get(isc_msgcat,
812                                                ISC_MSGSET_IFITERIOCTL,
813                                                ISC_MSG_GETDESTADDR,
814                                                "%s: getting "
815                                                "destination address: %s"),
816                                          lifreq.lifr_name, strbuf);
817                         return (ISC_R_IGNORE);
818                 }
819                 get_addr(family, &iter->current.dstaddress,
820                          (struct sockaddr *)&lifreq.lifr_dstaddr,
821                          lifreq.lifr_name);
822         }
823 #endif
824
825         /*
826          * Get the network mask.  Netmask already zeroed.
827          */
828         memset(&lifreq, 0, sizeof(lifreq));
829         memcpy(&lifreq, ifrp, sizeof(lifreq));
830
831 #ifdef lifr_addrlen
832         /*
833          * Special case: if the system provides lifr_addrlen member, the
834          * netmask of an IPv6 address can be derived from the length, since
835          * an IPv6 address always has a contiguous mask.
836          */
837         if (family == AF_INET6) {
838                 int i, bits;
839
840                 iter->current.netmask.family = family;
841                 for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
842                         bits = lifreq.lifr_addrlen - i;
843                         bits = (bits < 8) ? (8 - bits) : 0;
844                         iter->current.netmask.type.in6.s6_addr[i / 8] =
845                                 (~0 << bits) & 0xff;
846                 }
847
848                 return (ISC_R_SUCCESS);
849         }
850 #endif
851
852         /*
853          * Ignore the HP/UX warning about "interger overflow during
854          * conversion.  It comes from its own macro definition,
855          * and is really hard to shut up.
856          */
857         if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
858                 isc__strerror(errno, strbuf, sizeof(strbuf));
859                 UNEXPECTED_ERROR(__FILE__, __LINE__,
860                                  isc_msgcat_get(isc_msgcat,
861                                                 ISC_MSGSET_IFITERIOCTL,
862                                                 ISC_MSG_GETNETMASK,
863                                                 "%s: getting netmask: %s"),
864                                  lifreq.lifr_name, strbuf);
865                 return (ISC_R_IGNORE);
866         }
867         get_addr(family, &iter->current.netmask,
868                  (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
869
870         return (ISC_R_SUCCESS);
871 }
872 #endif
873
874 static isc_result_t
875 internal_current(isc_interfaceiter_t *iter) {
876 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
877         if (iter->mode == 6) {
878                 iter->result6 = internal_current6(iter);
879                 if (iter->result6 != ISC_R_NOMORE)
880                         return (iter->result6);
881         }
882 #endif
883 #ifdef HAVE_TRUCLUSTER
884         if (!iter->clua_done)
885                 return(internal_current_clusteralias(iter));
886 #endif
887         return (internal_current4(iter));
888 }
889
890 /*
891  * Step the iterator to the next interface.  Unlike
892  * isc_interfaceiter_next(), this may leave the iterator
893  * positioned on an interface that will ultimately
894  * be ignored.  Return ISC_R_NOMORE if there are no more
895  * interfaces, otherwise ISC_R_SUCCESS.
896  */
897 static isc_result_t
898 internal_next4(isc_interfaceiter_t *iter) {
899 #ifdef ISC_PLATFORM_HAVESALEN
900         struct ifreq *ifrp;
901 #endif
902
903         REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len);
904
905 #ifdef __linux
906         if (linux_if_inet6_next(iter) == ISC_R_SUCCESS)
907                 return (ISC_R_SUCCESS);
908         if (!iter->first)
909                 return (ISC_R_SUCCESS);
910 #endif
911 #ifdef ISC_PLATFORM_HAVESALEN
912         ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
913
914         if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
915                 iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len;
916         else
917 #endif
918                 iter->pos += sizeof(struct ifreq);
919
920         if (iter->pos >= (unsigned int) iter->ifc.ifc_len)
921                 return (ISC_R_NOMORE);
922
923         return (ISC_R_SUCCESS);
924 }
925
926 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
927 static isc_result_t
928 internal_next6(isc_interfaceiter_t *iter) {
929 #ifdef ISC_PLATFORM_HAVESALEN
930         struct LIFREQ *ifrp;
931 #endif
932         
933         if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
934                 return (iter->result6);
935
936         REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
937
938 #ifdef ISC_PLATFORM_HAVESALEN
939         ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
940
941         if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
942                 iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
943         else
944 #endif
945                 iter->pos6 += sizeof(struct LIFREQ);
946
947         if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
948                 return (ISC_R_NOMORE);
949
950         return (ISC_R_SUCCESS);
951 }
952 #endif
953
954 static isc_result_t
955 internal_next(isc_interfaceiter_t *iter) {
956 #ifdef HAVE_TRUCLUSTER
957         int clua_result;
958 #endif
959 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
960         if (iter->mode == 6) {
961                 iter->result6 = internal_next6(iter);
962                 if (iter->result6 != ISC_R_NOMORE)
963                         return (iter->result6);
964                 if (iter->first6) {
965                         iter->first6 = ISC_FALSE;
966                         return (ISC_R_SUCCESS);
967                 }
968         }
969 #endif
970 #ifdef HAVE_TRUCLUSTER
971         if (!iter->clua_done) {
972                 clua_result = clua_getaliasaddress(&iter->clua_sa,
973                                                    &iter->clua_context);
974                 if (clua_result != CLUA_SUCCESS)
975                         iter->clua_done = ISC_TRUE;
976                 return (ISC_R_SUCCESS);
977         }
978 #endif
979         return (internal_next4(iter));
980 }
981
982 static void
983 internal_destroy(isc_interfaceiter_t *iter) {
984         (void) close(iter->socket);
985 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
986         if (iter->socket6 != -1)
987                 (void) close(iter->socket6);
988         if (iter->buf6 != NULL) {
989                 isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
990         }
991 #endif
992 #ifdef __linux
993         if (iter->proc != NULL)
994                 fclose(iter->proc);
995 #endif
996 }
997
998 static
999 void internal_first(isc_interfaceiter_t *iter) {
1000 #ifdef HAVE_TRUCLUSTER
1001         int clua_result;
1002 #endif
1003         iter->pos = 0;
1004 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
1005         iter->pos6 = 0;
1006         if (iter->result6 == ISC_R_NOMORE)
1007                 iter->result6 = ISC_R_SUCCESS;
1008         iter->first6 = ISC_TRUE;
1009 #endif
1010 #ifdef HAVE_TRUCLUSTER
1011         iter->clua_context = 0;
1012         clua_result = clua_getaliasaddress(&iter->clua_sa,
1013                                            &iter->clua_context);
1014         iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
1015 #endif
1016 #ifdef __linux
1017         linux_if_inet6_first(iter);
1018 #endif
1019 }