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