17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
5*1da57d55SToomas Soome
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate * include/foreachaddr.c
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * Copyright 1990,1991,2000,2001,2002 by the Massachusetts Institute of Technology.
107c478bd9Sstevel@tonic-gate * All Rights Reserved.
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may
137c478bd9Sstevel@tonic-gate * require a specific license from the United States Government.
147c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
157c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting.
16*1da57d55SToomas Soome *
177c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
187c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
197c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
207c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
217c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
227c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
237c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior
247c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label
257c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a
267c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
277c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of
287c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
297c478bd9Sstevel@tonic-gate * or implied warranty.
30*1da57d55SToomas Soome *
317c478bd9Sstevel@tonic-gate *
327c478bd9Sstevel@tonic-gate * Iterate over the protocol addresses supported by this host, invoking
337c478bd9Sstevel@tonic-gate * a callback function or three supplied by the caller.
347c478bd9Sstevel@tonic-gate *
357c478bd9Sstevel@tonic-gate * XNS support is untested, but "should just work". (Hah!)
367c478bd9Sstevel@tonic-gate */
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate /* This is the primary "export" of this file. It's a static function,
397c478bd9Sstevel@tonic-gate so this file must be #included in the .c file containing the
407c478bd9Sstevel@tonic-gate caller.
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate This function iterates over all the addresses it can find for the
437c478bd9Sstevel@tonic-gate local system, in one or two passes. In each pass, and between the
447c478bd9Sstevel@tonic-gate two, it can invoke callback functions supplied by the caller. The
457c478bd9Sstevel@tonic-gate two passes should operate on the same information, though not
467c478bd9Sstevel@tonic-gate necessarily in the same order each time. Duplicate and local
477c478bd9Sstevel@tonic-gate addresses should be eliminated. Storage passed to callback
487c478bd9Sstevel@tonic-gate functions should not be assumed to be valid after foreach_localaddr
497c478bd9Sstevel@tonic-gate returns.
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate The int return value is an errno value (XXX or krb5_error_code
527c478bd9Sstevel@tonic-gate returned for a socket error) if something internal to
537c478bd9Sstevel@tonic-gate foreach_localaddr fails. If one of the callback functions wants to
547c478bd9Sstevel@tonic-gate indicate an error, it should store something via the 'data' handle.
557c478bd9Sstevel@tonic-gate If any callback function returns a non-zero value,
567c478bd9Sstevel@tonic-gate foreach_localaddr will clean up and return immediately.
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate Multiple definitions are provided below, dependent on various
597c478bd9Sstevel@tonic-gate system facilities for extracting the necessary information. */
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate /* Solaris Kerberos: changing foreach_localaddr to non-static as it's called in
627c478bd9Sstevel@tonic-gate * a couple places.
637c478bd9Sstevel@tonic-gate */
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate #ifdef TEST
667c478bd9Sstevel@tonic-gate # define Tprintf(X) printf X
677c478bd9Sstevel@tonic-gate # define Tperror(X) perror(X)
687c478bd9Sstevel@tonic-gate #else
697c478bd9Sstevel@tonic-gate # define Tprintf(X) (void) X
707c478bd9Sstevel@tonic-gate # define Tperror(X) (void)(X)
717c478bd9Sstevel@tonic-gate #endif
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate * The SIOCGIF* ioctls require a socket.
757c478bd9Sstevel@tonic-gate * It doesn't matter *what* kind of socket they use, but it has to be
767c478bd9Sstevel@tonic-gate * a socket.
777c478bd9Sstevel@tonic-gate *
787c478bd9Sstevel@tonic-gate * Of course, you can't just ask the kernel for a socket of arbitrary
797c478bd9Sstevel@tonic-gate * type; you have to ask for one with a valid type.
807c478bd9Sstevel@tonic-gate *
817c478bd9Sstevel@tonic-gate */
827c478bd9Sstevel@tonic-gate #ifdef HAVE_NETINET_IN_H
837c478bd9Sstevel@tonic-gate #include <netinet/in.h>
847c478bd9Sstevel@tonic-gate #ifndef USE_AF
857c478bd9Sstevel@tonic-gate #define USE_AF AF_INET
867c478bd9Sstevel@tonic-gate #define USE_TYPE SOCK_DGRAM
877c478bd9Sstevel@tonic-gate #define USE_PROTO 0
887c478bd9Sstevel@tonic-gate #endif
897c478bd9Sstevel@tonic-gate #endif
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate #ifdef KRB5_USE_NS
927c478bd9Sstevel@tonic-gate #include <netns/ns.h>
937c478bd9Sstevel@tonic-gate #ifndef USE_AF
947c478bd9Sstevel@tonic-gate #define USE_AF AF_NS
957c478bd9Sstevel@tonic-gate #define USE_TYPE SOCK_DGRAM
967c478bd9Sstevel@tonic-gate #define USE_PROTO 0 /* guess */
977c478bd9Sstevel@tonic-gate #endif
987c478bd9Sstevel@tonic-gate #endif
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate * Add more address families here.
1017c478bd9Sstevel@tonic-gate */
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate #include <errno.h>
1047c478bd9Sstevel@tonic-gate #include <fake-addrinfo.h>
1057c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
1067c478bd9Sstevel@tonic-gate #include <k5-int.h>
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate * Return all the protocol addresses of this host.
1107c478bd9Sstevel@tonic-gate *
1117c478bd9Sstevel@tonic-gate * We could kludge up something to return all addresses, assuming that
1127c478bd9Sstevel@tonic-gate * they're valid kerberos protocol addresses, but we wouldn't know the
1137c478bd9Sstevel@tonic-gate * real size of the sockaddr or know which part of it was actually the
1147c478bd9Sstevel@tonic-gate * host part.
1157c478bd9Sstevel@tonic-gate *
1167c478bd9Sstevel@tonic-gate * This uses the SIOCGIFCONF, SIOCGIFFLAGS, and SIOCGIFADDR ioctl's.
1177c478bd9Sstevel@tonic-gate */
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate * BSD 4.4 defines the size of an ifreq to be
1217c478bd9Sstevel@tonic-gate * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
122*1da57d55SToomas Soome * However, under earlier systems, sa_len isn't present, so the size is
1237c478bd9Sstevel@tonic-gate * just sizeof(struct ifreq).
1247c478bd9Sstevel@tonic-gate */
1257c478bd9Sstevel@tonic-gate #ifdef HAVE_SA_LEN
1267c478bd9Sstevel@tonic-gate #ifndef max
1277c478bd9Sstevel@tonic-gate #define max(a,b) ((a) > (b) ? (a) : (b))
1287c478bd9Sstevel@tonic-gate #endif
1297c478bd9Sstevel@tonic-gate #define ifreq_size(i) max(sizeof(struct ifreq),\
1307c478bd9Sstevel@tonic-gate sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
1317c478bd9Sstevel@tonic-gate #else
1327c478bd9Sstevel@tonic-gate #define ifreq_size(i) sizeof(struct ifreq)
1337c478bd9Sstevel@tonic-gate #endif /* HAVE_SA_LEN*/
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate #ifdef SIOCGLIFCONF /* Solaris */
1377c478bd9Sstevel@tonic-gate static int
get_lifconf(int af,int s,size_t * lenp,char * buf)1387c478bd9Sstevel@tonic-gate get_lifconf (int af, int s, size_t *lenp, char *buf)
1397c478bd9Sstevel@tonic-gate /*@modifies *buf,*lenp@*/
1407c478bd9Sstevel@tonic-gate {
1417c478bd9Sstevel@tonic-gate int ret;
1427c478bd9Sstevel@tonic-gate struct lifconf lifc;
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate lifc.lifc_family = af;
1457c478bd9Sstevel@tonic-gate lifc.lifc_flags = 0;
1467c478bd9Sstevel@tonic-gate lifc.lifc_len = *lenp;
1477c478bd9Sstevel@tonic-gate lifc.lifc_buf = buf;
1487c478bd9Sstevel@tonic-gate memset(buf, 0, *lenp);
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate ret = ioctl (s, SIOCGLIFCONF, (char *)&lifc);
1517c478bd9Sstevel@tonic-gate if (ret)
1527c478bd9Sstevel@tonic-gate Tperror ("SIOCGLIFCONF");
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate *lenp = lifc.lifc_len;
1557c478bd9Sstevel@tonic-gate return ret;
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate #endif
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate /* Return value is errno if internal stuff failed, otherwise zero,
1607c478bd9Sstevel@tonic-gate even in the case where a called function terminated the iteration.
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate If one of the callback functions wants to pass back an error
1637c478bd9Sstevel@tonic-gate indication, it should do it via some field pointed to by the DATA
1647c478bd9Sstevel@tonic-gate argument. */
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate int
foreach_localaddr(void * data,int (* pass1fn)(void *,struct sockaddr *),int (* betweenfn)(void *),int (* pass2fn)(void *,struct sockaddr *))1677c478bd9Sstevel@tonic-gate foreach_localaddr (void *data,
1687c478bd9Sstevel@tonic-gate int (*pass1fn) (void *, struct sockaddr *),
1697c478bd9Sstevel@tonic-gate int (*betweenfn) (void *),
1707c478bd9Sstevel@tonic-gate int (*pass2fn) (void *, struct sockaddr *))
1717c478bd9Sstevel@tonic-gate {
1727c478bd9Sstevel@tonic-gate /* Okay, this is kind of odd. We have to use each of the address
1737c478bd9Sstevel@tonic-gate families we care about, because with an AF_INET socket, extra
1747c478bd9Sstevel@tonic-gate interfaces like hme0:1 that have only AF_INET6 addresses will
1757c478bd9Sstevel@tonic-gate cause errors. Similarly, if hme0 has more AF_INET addresses
1767c478bd9Sstevel@tonic-gate than AF_INET6 addresses, we won't be able to retrieve all of
1777c478bd9Sstevel@tonic-gate the AF_INET addresses if we use an AF_INET6 socket. Since
1787c478bd9Sstevel@tonic-gate neither family is guaranteed to have the greater number of
1797c478bd9Sstevel@tonic-gate addresses, we should use both.
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate If it weren't for this little quirk, we could use one socket of
1827c478bd9Sstevel@tonic-gate any type, and ask for addresses of all types. At least, it
1837c478bd9Sstevel@tonic-gate seems to work that way. */
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate /* Solaris kerberos: avoid using AF_NS if no define */
1867c478bd9Sstevel@tonic-gate #if defined (KRB5_USE_INET6) && defined (KRB5_USE_NS)
1877c478bd9Sstevel@tonic-gate static const int afs[] = { AF_INET, AF_NS, AF_INET6 };
1887c478bd9Sstevel@tonic-gate #elif defined (KRB5_USE_INET6)
1897c478bd9Sstevel@tonic-gate static const int afs[] = { AF_INET, AF_INET6 };
1907c478bd9Sstevel@tonic-gate #else
1917c478bd9Sstevel@tonic-gate static const int afs[] = { AF_INET };
1927c478bd9Sstevel@tonic-gate #endif
193*1da57d55SToomas Soome
1947c478bd9Sstevel@tonic-gate #define N_AFS (sizeof (afs) / sizeof (afs[0]))
1957c478bd9Sstevel@tonic-gate struct {
1967c478bd9Sstevel@tonic-gate int af;
1977c478bd9Sstevel@tonic-gate int sock;
1987c478bd9Sstevel@tonic-gate void *buf;
1997c478bd9Sstevel@tonic-gate size_t buf_size;
2007c478bd9Sstevel@tonic-gate struct lifnum lifnum;
2017c478bd9Sstevel@tonic-gate } afp[N_AFS];
2027c478bd9Sstevel@tonic-gate int code, i, j;
2037c478bd9Sstevel@tonic-gate int retval = 0, afidx;
2047c478bd9Sstevel@tonic-gate krb5_error_code sock_err = 0;
2057c478bd9Sstevel@tonic-gate struct lifreq *lifr, lifreq, *lifr2;
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate #define FOREACH_AF() for (afidx = 0; afidx < N_AFS; afidx++)
2087c478bd9Sstevel@tonic-gate #define P (afp[afidx])
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "foreach_localaddr() start");
2117c478bd9Sstevel@tonic-gate /* init */
2127c478bd9Sstevel@tonic-gate FOREACH_AF () {
2137c478bd9Sstevel@tonic-gate P.af = afs[afidx];
2147c478bd9Sstevel@tonic-gate P.sock = -1;
2157c478bd9Sstevel@tonic-gate P.buf = 0;
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate /* first pass: get raw data, discard uninteresting addresses, callback */
2197c478bd9Sstevel@tonic-gate FOREACH_AF () {
2207c478bd9Sstevel@tonic-gate KRB5_LOG (KRB5_INFO, "foreach_localaddr() trying af %d", P.af);
2217c478bd9Sstevel@tonic-gate P.sock = socket (P.af, USE_TYPE, USE_PROTO);
2227c478bd9Sstevel@tonic-gate if (P.sock < 0) {
2237c478bd9Sstevel@tonic-gate sock_err = SOCKET_ERROR;
2247c478bd9Sstevel@tonic-gate Tperror ("socket");
2257c478bd9Sstevel@tonic-gate continue;
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate P.lifnum.lifn_family = P.af;
2297c478bd9Sstevel@tonic-gate P.lifnum.lifn_flags = 0;
2307c478bd9Sstevel@tonic-gate P.lifnum.lifn_count = 0;
2317c478bd9Sstevel@tonic-gate code = ioctl (P.sock, SIOCGLIFNUM, &P.lifnum);
2327c478bd9Sstevel@tonic-gate if (code) {
2337c478bd9Sstevel@tonic-gate Tperror ("ioctl(SIOCGLIFNUM)");
2347c478bd9Sstevel@tonic-gate retval = errno;
2357c478bd9Sstevel@tonic-gate goto punt;
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate KRB5_LOG (KRB5_INFO, "foreach_localaddr() lifn_count %d",
2397c478bd9Sstevel@tonic-gate P.lifnum.lifn_count);
2407c478bd9Sstevel@tonic-gate P.buf_size = P.lifnum.lifn_count * sizeof (struct lifreq) * 2;
2417c478bd9Sstevel@tonic-gate P.buf = malloc (P.buf_size);
2427c478bd9Sstevel@tonic-gate if (P.buf == NULL) {
2437c478bd9Sstevel@tonic-gate retval = errno;
2447c478bd9Sstevel@tonic-gate goto punt;
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate code = get_lifconf (P.af, P.sock, &P.buf_size, P.buf);
2487c478bd9Sstevel@tonic-gate if (code < 0) {
2497c478bd9Sstevel@tonic-gate retval = errno;
2507c478bd9Sstevel@tonic-gate goto punt;
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate for (i = 0; i < P.buf_size; i+= sizeof (*lifr)) {
2547c478bd9Sstevel@tonic-gate /*LINTED*/
2557c478bd9Sstevel@tonic-gate lifr = (struct lifreq *)((caddr_t) P.buf+i);
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate strncpy(lifreq.lifr_name, lifr->lifr_name,
2587c478bd9Sstevel@tonic-gate sizeof (lifreq.lifr_name));
2597c478bd9Sstevel@tonic-gate KRB5_LOG (KRB5_INFO, "foreach_localaddr() interface %s",
2607c478bd9Sstevel@tonic-gate lifreq.lifr_name);
2617c478bd9Sstevel@tonic-gate /* ioctl unknown to lclint */
2627c478bd9Sstevel@tonic-gate if (ioctl (P.sock, SIOCGLIFFLAGS, (char *)&lifreq) < 0) {
2637c478bd9Sstevel@tonic-gate Tperror ("ioctl(SIOCGLIFFLAGS)");
2647c478bd9Sstevel@tonic-gate skip:
265*1da57d55SToomas Soome KRB5_LOG (KRB5_INFO,
2667c478bd9Sstevel@tonic-gate "foreach_localaddr() skipping interface %s",
2677c478bd9Sstevel@tonic-gate lifr->lifr_name);
2687c478bd9Sstevel@tonic-gate /* mark for next pass */
2697c478bd9Sstevel@tonic-gate lifr->lifr_name[0] = '\0';
2707c478bd9Sstevel@tonic-gate continue;
2717c478bd9Sstevel@tonic-gate }
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate #ifdef IFF_LOOPBACK
2747c478bd9Sstevel@tonic-gate /* None of the current callers want loopback addresses. */
2757c478bd9Sstevel@tonic-gate if (lifreq.lifr_flags & IFF_LOOPBACK) {
2767c478bd9Sstevel@tonic-gate Tprintf ((" loopback\n"));
2777c478bd9Sstevel@tonic-gate goto skip;
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate #endif
2807c478bd9Sstevel@tonic-gate /* Ignore interfaces that are down. */
2817c478bd9Sstevel@tonic-gate if ((lifreq.lifr_flags & IFF_UP) == 0) {
2827c478bd9Sstevel@tonic-gate Tprintf ((" down\n"));
2837c478bd9Sstevel@tonic-gate goto skip;
2847c478bd9Sstevel@tonic-gate }
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate /* Make sure we didn't process this address already. */
2877c478bd9Sstevel@tonic-gate for (j = 0; j < i; j += sizeof (*lifr2)) {
2887c478bd9Sstevel@tonic-gate /*LINTED*/
2897c478bd9Sstevel@tonic-gate lifr2 = (struct lifreq *)((caddr_t) P.buf+j);
2907c478bd9Sstevel@tonic-gate if (lifr2->lifr_name[0] == '\0')
2917c478bd9Sstevel@tonic-gate continue;
2927c478bd9Sstevel@tonic-gate if (lifr2->lifr_addr.ss_family == lifr->lifr_addr.ss_family
2937c478bd9Sstevel@tonic-gate /* Compare address info. If this isn't good enough --
2947c478bd9Sstevel@tonic-gate i.e., if random padding bytes turn out to differ
2957c478bd9Sstevel@tonic-gate when the addresses are the same -- then we'll have
2967c478bd9Sstevel@tonic-gate to do it on a per address family basis. */
2977c478bd9Sstevel@tonic-gate && !memcmp (&lifr2->lifr_addr, &lifr->lifr_addr,
2987c478bd9Sstevel@tonic-gate sizeof (*lifr))) {
2997c478bd9Sstevel@tonic-gate Tprintf ((" duplicate addr\n"));
3007c478bd9Sstevel@tonic-gate KRB5_LOG0 (KRB5_INFO, "foreach_localaddr() dup addr");
3017c478bd9Sstevel@tonic-gate goto skip;
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate if ((*pass1fn) (data, ss2sa (&lifr->lifr_addr)))
3067c478bd9Sstevel@tonic-gate goto punt;
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate /* Did we actually get any working sockets? */
3117c478bd9Sstevel@tonic-gate FOREACH_AF ()
3127c478bd9Sstevel@tonic-gate if (P.sock != -1)
3137c478bd9Sstevel@tonic-gate goto have_working_socket;
3147c478bd9Sstevel@tonic-gate retval = sock_err;
3157c478bd9Sstevel@tonic-gate goto punt;
3167c478bd9Sstevel@tonic-gate have_working_socket:
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate if (betweenfn != NULL && (*betweenfn)(data))
3197c478bd9Sstevel@tonic-gate goto punt;
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate if (pass2fn)
3227c478bd9Sstevel@tonic-gate FOREACH_AF ()
3237c478bd9Sstevel@tonic-gate if (P.sock >= 0) {
3247c478bd9Sstevel@tonic-gate for (i = 0; i < P.buf_size; i+= sizeof (*lifr)) {
3257c478bd9Sstevel@tonic-gate /*LINTED*/
3267c478bd9Sstevel@tonic-gate lifr = (struct lifreq *)((caddr_t) P.buf+i);
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate if (lifr->lifr_name[0] == '\0')
3297c478bd9Sstevel@tonic-gate /* Marked in first pass to be ignored. */
3307c478bd9Sstevel@tonic-gate continue;
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate KRB5_LOG (KRB5_INFO,
3337c478bd9Sstevel@tonic-gate "foreach_localaddr() doing pass2fn i = %d",
3347c478bd9Sstevel@tonic-gate i);
3357c478bd9Sstevel@tonic-gate if ((*pass2fn) (data, ss2sa (&lifr->lifr_addr)))
3367c478bd9Sstevel@tonic-gate goto punt;
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate punt:
3407c478bd9Sstevel@tonic-gate FOREACH_AF () {
3417c478bd9Sstevel@tonic-gate closesocket(P.sock);
3427c478bd9Sstevel@tonic-gate free (P.buf);
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate return retval;
3467c478bd9Sstevel@tonic-gate }
347