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