1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 6*7c478bd9Sstevel@tonic-gate /* 7*7c478bd9Sstevel@tonic-gate * include/foreachaddr.c 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * Copyright 1990,1991,2000,2001,2002 by the Massachusetts Institute of Technology. 10*7c478bd9Sstevel@tonic-gate * All Rights Reserved. 11*7c478bd9Sstevel@tonic-gate * 12*7c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 13*7c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 14*7c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 15*7c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 16*7c478bd9Sstevel@tonic-gate * 17*7c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 18*7c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 19*7c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 20*7c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 21*7c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 22*7c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 23*7c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 24*7c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 25*7c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 26*7c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 27*7c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 28*7c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 29*7c478bd9Sstevel@tonic-gate * or implied warranty. 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate * Iterate over the protocol addresses supported by this host, invoking 33*7c478bd9Sstevel@tonic-gate * a callback function or three supplied by the caller. 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * XNS support is untested, but "should just work". (Hah!) 36*7c478bd9Sstevel@tonic-gate */ 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate /* This is the primary "export" of this file. It's a static function, 39*7c478bd9Sstevel@tonic-gate so this file must be #included in the .c file containing the 40*7c478bd9Sstevel@tonic-gate caller. 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate This function iterates over all the addresses it can find for the 43*7c478bd9Sstevel@tonic-gate local system, in one or two passes. In each pass, and between the 44*7c478bd9Sstevel@tonic-gate two, it can invoke callback functions supplied by the caller. The 45*7c478bd9Sstevel@tonic-gate two passes should operate on the same information, though not 46*7c478bd9Sstevel@tonic-gate necessarily in the same order each time. Duplicate and local 47*7c478bd9Sstevel@tonic-gate addresses should be eliminated. Storage passed to callback 48*7c478bd9Sstevel@tonic-gate functions should not be assumed to be valid after foreach_localaddr 49*7c478bd9Sstevel@tonic-gate returns. 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate The int return value is an errno value (XXX or krb5_error_code 52*7c478bd9Sstevel@tonic-gate returned for a socket error) if something internal to 53*7c478bd9Sstevel@tonic-gate foreach_localaddr fails. If one of the callback functions wants to 54*7c478bd9Sstevel@tonic-gate indicate an error, it should store something via the 'data' handle. 55*7c478bd9Sstevel@tonic-gate If any callback function returns a non-zero value, 56*7c478bd9Sstevel@tonic-gate foreach_localaddr will clean up and return immediately. 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate Multiple definitions are provided below, dependent on various 59*7c478bd9Sstevel@tonic-gate system facilities for extracting the necessary information. */ 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate /* Solaris Kerberos: changing foreach_localaddr to non-static as it's called in 62*7c478bd9Sstevel@tonic-gate * a couple places. 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #ifdef TEST 66*7c478bd9Sstevel@tonic-gate # define Tprintf(X) printf X 67*7c478bd9Sstevel@tonic-gate # define Tperror(X) perror(X) 68*7c478bd9Sstevel@tonic-gate #else 69*7c478bd9Sstevel@tonic-gate # define Tprintf(X) (void) X 70*7c478bd9Sstevel@tonic-gate # define Tperror(X) (void)(X) 71*7c478bd9Sstevel@tonic-gate #endif 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * The SIOCGIF* ioctls require a socket. 75*7c478bd9Sstevel@tonic-gate * It doesn't matter *what* kind of socket they use, but it has to be 76*7c478bd9Sstevel@tonic-gate * a socket. 77*7c478bd9Sstevel@tonic-gate * 78*7c478bd9Sstevel@tonic-gate * Of course, you can't just ask the kernel for a socket of arbitrary 79*7c478bd9Sstevel@tonic-gate * type; you have to ask for one with a valid type. 80*7c478bd9Sstevel@tonic-gate * 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate #ifdef HAVE_NETINET_IN_H 83*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 84*7c478bd9Sstevel@tonic-gate #ifndef USE_AF 85*7c478bd9Sstevel@tonic-gate #define USE_AF AF_INET 86*7c478bd9Sstevel@tonic-gate #define USE_TYPE SOCK_DGRAM 87*7c478bd9Sstevel@tonic-gate #define USE_PROTO 0 88*7c478bd9Sstevel@tonic-gate #endif 89*7c478bd9Sstevel@tonic-gate #endif 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate #ifdef KRB5_USE_NS 92*7c478bd9Sstevel@tonic-gate #include <netns/ns.h> 93*7c478bd9Sstevel@tonic-gate #ifndef USE_AF 94*7c478bd9Sstevel@tonic-gate #define USE_AF AF_NS 95*7c478bd9Sstevel@tonic-gate #define USE_TYPE SOCK_DGRAM 96*7c478bd9Sstevel@tonic-gate #define USE_PROTO 0 /* guess */ 97*7c478bd9Sstevel@tonic-gate #endif 98*7c478bd9Sstevel@tonic-gate #endif 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * Add more address families here. 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate #include <errno.h> 104*7c478bd9Sstevel@tonic-gate #include <fake-addrinfo.h> 105*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 106*7c478bd9Sstevel@tonic-gate #include <k5-int.h> 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* 109*7c478bd9Sstevel@tonic-gate * Return all the protocol addresses of this host. 110*7c478bd9Sstevel@tonic-gate * 111*7c478bd9Sstevel@tonic-gate * We could kludge up something to return all addresses, assuming that 112*7c478bd9Sstevel@tonic-gate * they're valid kerberos protocol addresses, but we wouldn't know the 113*7c478bd9Sstevel@tonic-gate * real size of the sockaddr or know which part of it was actually the 114*7c478bd9Sstevel@tonic-gate * host part. 115*7c478bd9Sstevel@tonic-gate * 116*7c478bd9Sstevel@tonic-gate * This uses the SIOCGIFCONF, SIOCGIFFLAGS, and SIOCGIFADDR ioctl's. 117*7c478bd9Sstevel@tonic-gate */ 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate /* 120*7c478bd9Sstevel@tonic-gate * BSD 4.4 defines the size of an ifreq to be 121*7c478bd9Sstevel@tonic-gate * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len 122*7c478bd9Sstevel@tonic-gate * However, under earlier systems, sa_len isn't present, so the size is 123*7c478bd9Sstevel@tonic-gate * just sizeof(struct ifreq). 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SA_LEN 126*7c478bd9Sstevel@tonic-gate #ifndef max 127*7c478bd9Sstevel@tonic-gate #define max(a,b) ((a) > (b) ? (a) : (b)) 128*7c478bd9Sstevel@tonic-gate #endif 129*7c478bd9Sstevel@tonic-gate #define ifreq_size(i) max(sizeof(struct ifreq),\ 130*7c478bd9Sstevel@tonic-gate sizeof((i).ifr_name)+(i).ifr_addr.sa_len) 131*7c478bd9Sstevel@tonic-gate #else 132*7c478bd9Sstevel@tonic-gate #define ifreq_size(i) sizeof(struct ifreq) 133*7c478bd9Sstevel@tonic-gate #endif /* HAVE_SA_LEN*/ 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate #ifdef SIOCGLIFCONF /* Solaris */ 137*7c478bd9Sstevel@tonic-gate static int 138*7c478bd9Sstevel@tonic-gate get_lifconf (int af, int s, size_t *lenp, char *buf) 139*7c478bd9Sstevel@tonic-gate /*@modifies *buf,*lenp@*/ 140*7c478bd9Sstevel@tonic-gate { 141*7c478bd9Sstevel@tonic-gate int ret; 142*7c478bd9Sstevel@tonic-gate struct lifconf lifc; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate lifc.lifc_family = af; 145*7c478bd9Sstevel@tonic-gate lifc.lifc_flags = 0; 146*7c478bd9Sstevel@tonic-gate lifc.lifc_len = *lenp; 147*7c478bd9Sstevel@tonic-gate lifc.lifc_buf = buf; 148*7c478bd9Sstevel@tonic-gate memset(buf, 0, *lenp); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate ret = ioctl (s, SIOCGLIFCONF, (char *)&lifc); 151*7c478bd9Sstevel@tonic-gate if (ret) 152*7c478bd9Sstevel@tonic-gate Tperror ("SIOCGLIFCONF"); 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate *lenp = lifc.lifc_len; 155*7c478bd9Sstevel@tonic-gate return ret; 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate #endif 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate /* Return value is errno if internal stuff failed, otherwise zero, 160*7c478bd9Sstevel@tonic-gate even in the case where a called function terminated the iteration. 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate If one of the callback functions wants to pass back an error 163*7c478bd9Sstevel@tonic-gate indication, it should do it via some field pointed to by the DATA 164*7c478bd9Sstevel@tonic-gate argument. */ 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate int 167*7c478bd9Sstevel@tonic-gate foreach_localaddr (void *data, 168*7c478bd9Sstevel@tonic-gate int (*pass1fn) (void *, struct sockaddr *), 169*7c478bd9Sstevel@tonic-gate int (*betweenfn) (void *), 170*7c478bd9Sstevel@tonic-gate int (*pass2fn) (void *, struct sockaddr *)) 171*7c478bd9Sstevel@tonic-gate { 172*7c478bd9Sstevel@tonic-gate /* Okay, this is kind of odd. We have to use each of the address 173*7c478bd9Sstevel@tonic-gate families we care about, because with an AF_INET socket, extra 174*7c478bd9Sstevel@tonic-gate interfaces like hme0:1 that have only AF_INET6 addresses will 175*7c478bd9Sstevel@tonic-gate cause errors. Similarly, if hme0 has more AF_INET addresses 176*7c478bd9Sstevel@tonic-gate than AF_INET6 addresses, we won't be able to retrieve all of 177*7c478bd9Sstevel@tonic-gate the AF_INET addresses if we use an AF_INET6 socket. Since 178*7c478bd9Sstevel@tonic-gate neither family is guaranteed to have the greater number of 179*7c478bd9Sstevel@tonic-gate addresses, we should use both. 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate If it weren't for this little quirk, we could use one socket of 182*7c478bd9Sstevel@tonic-gate any type, and ask for addresses of all types. At least, it 183*7c478bd9Sstevel@tonic-gate seems to work that way. */ 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* Solaris kerberos: avoid using AF_NS if no define */ 186*7c478bd9Sstevel@tonic-gate #if defined (KRB5_USE_INET6) && defined (KRB5_USE_NS) 187*7c478bd9Sstevel@tonic-gate static const int afs[] = { AF_INET, AF_NS, AF_INET6 }; 188*7c478bd9Sstevel@tonic-gate #elif defined (KRB5_USE_INET6) 189*7c478bd9Sstevel@tonic-gate static const int afs[] = { AF_INET, AF_INET6 }; 190*7c478bd9Sstevel@tonic-gate #else 191*7c478bd9Sstevel@tonic-gate static const int afs[] = { AF_INET }; 192*7c478bd9Sstevel@tonic-gate #endif 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate #define N_AFS (sizeof (afs) / sizeof (afs[0])) 195*7c478bd9Sstevel@tonic-gate struct { 196*7c478bd9Sstevel@tonic-gate int af; 197*7c478bd9Sstevel@tonic-gate int sock; 198*7c478bd9Sstevel@tonic-gate void *buf; 199*7c478bd9Sstevel@tonic-gate size_t buf_size; 200*7c478bd9Sstevel@tonic-gate struct lifnum lifnum; 201*7c478bd9Sstevel@tonic-gate } afp[N_AFS]; 202*7c478bd9Sstevel@tonic-gate int code, i, j; 203*7c478bd9Sstevel@tonic-gate int retval = 0, afidx; 204*7c478bd9Sstevel@tonic-gate krb5_error_code sock_err = 0; 205*7c478bd9Sstevel@tonic-gate struct lifreq *lifr, lifreq, *lifr2; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate #define FOREACH_AF() for (afidx = 0; afidx < N_AFS; afidx++) 208*7c478bd9Sstevel@tonic-gate #define P (afp[afidx]) 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate KRB5_LOG0(KRB5_INFO, "foreach_localaddr() start"); 211*7c478bd9Sstevel@tonic-gate /* init */ 212*7c478bd9Sstevel@tonic-gate FOREACH_AF () { 213*7c478bd9Sstevel@tonic-gate P.af = afs[afidx]; 214*7c478bd9Sstevel@tonic-gate P.sock = -1; 215*7c478bd9Sstevel@tonic-gate P.buf = 0; 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* first pass: get raw data, discard uninteresting addresses, callback */ 219*7c478bd9Sstevel@tonic-gate FOREACH_AF () { 220*7c478bd9Sstevel@tonic-gate KRB5_LOG (KRB5_INFO, "foreach_localaddr() trying af %d", P.af); 221*7c478bd9Sstevel@tonic-gate P.sock = socket (P.af, USE_TYPE, USE_PROTO); 222*7c478bd9Sstevel@tonic-gate if (P.sock < 0) { 223*7c478bd9Sstevel@tonic-gate sock_err = SOCKET_ERROR; 224*7c478bd9Sstevel@tonic-gate Tperror ("socket"); 225*7c478bd9Sstevel@tonic-gate continue; 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate P.lifnum.lifn_family = P.af; 229*7c478bd9Sstevel@tonic-gate P.lifnum.lifn_flags = 0; 230*7c478bd9Sstevel@tonic-gate P.lifnum.lifn_count = 0; 231*7c478bd9Sstevel@tonic-gate code = ioctl (P.sock, SIOCGLIFNUM, &P.lifnum); 232*7c478bd9Sstevel@tonic-gate if (code) { 233*7c478bd9Sstevel@tonic-gate Tperror ("ioctl(SIOCGLIFNUM)"); 234*7c478bd9Sstevel@tonic-gate retval = errno; 235*7c478bd9Sstevel@tonic-gate goto punt; 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate KRB5_LOG (KRB5_INFO, "foreach_localaddr() lifn_count %d", 239*7c478bd9Sstevel@tonic-gate P.lifnum.lifn_count); 240*7c478bd9Sstevel@tonic-gate P.buf_size = P.lifnum.lifn_count * sizeof (struct lifreq) * 2; 241*7c478bd9Sstevel@tonic-gate P.buf = malloc (P.buf_size); 242*7c478bd9Sstevel@tonic-gate if (P.buf == NULL) { 243*7c478bd9Sstevel@tonic-gate retval = errno; 244*7c478bd9Sstevel@tonic-gate goto punt; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate code = get_lifconf (P.af, P.sock, &P.buf_size, P.buf); 248*7c478bd9Sstevel@tonic-gate if (code < 0) { 249*7c478bd9Sstevel@tonic-gate retval = errno; 250*7c478bd9Sstevel@tonic-gate goto punt; 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate for (i = 0; i < P.buf_size; i+= sizeof (*lifr)) { 254*7c478bd9Sstevel@tonic-gate /*LINTED*/ 255*7c478bd9Sstevel@tonic-gate lifr = (struct lifreq *)((caddr_t) P.buf+i); 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate strncpy(lifreq.lifr_name, lifr->lifr_name, 258*7c478bd9Sstevel@tonic-gate sizeof (lifreq.lifr_name)); 259*7c478bd9Sstevel@tonic-gate KRB5_LOG (KRB5_INFO, "foreach_localaddr() interface %s", 260*7c478bd9Sstevel@tonic-gate lifreq.lifr_name); 261*7c478bd9Sstevel@tonic-gate /* ioctl unknown to lclint */ 262*7c478bd9Sstevel@tonic-gate if (ioctl (P.sock, SIOCGLIFFLAGS, (char *)&lifreq) < 0) { 263*7c478bd9Sstevel@tonic-gate Tperror ("ioctl(SIOCGLIFFLAGS)"); 264*7c478bd9Sstevel@tonic-gate skip: 265*7c478bd9Sstevel@tonic-gate KRB5_LOG (KRB5_INFO, 266*7c478bd9Sstevel@tonic-gate "foreach_localaddr() skipping interface %s", 267*7c478bd9Sstevel@tonic-gate lifr->lifr_name); 268*7c478bd9Sstevel@tonic-gate /* mark for next pass */ 269*7c478bd9Sstevel@tonic-gate lifr->lifr_name[0] = '\0'; 270*7c478bd9Sstevel@tonic-gate continue; 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate #ifdef IFF_LOOPBACK 274*7c478bd9Sstevel@tonic-gate /* None of the current callers want loopback addresses. */ 275*7c478bd9Sstevel@tonic-gate if (lifreq.lifr_flags & IFF_LOOPBACK) { 276*7c478bd9Sstevel@tonic-gate Tprintf ((" loopback\n")); 277*7c478bd9Sstevel@tonic-gate goto skip; 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate #endif 280*7c478bd9Sstevel@tonic-gate /* Ignore interfaces that are down. */ 281*7c478bd9Sstevel@tonic-gate if ((lifreq.lifr_flags & IFF_UP) == 0) { 282*7c478bd9Sstevel@tonic-gate Tprintf ((" down\n")); 283*7c478bd9Sstevel@tonic-gate goto skip; 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate /* Make sure we didn't process this address already. */ 287*7c478bd9Sstevel@tonic-gate for (j = 0; j < i; j += sizeof (*lifr2)) { 288*7c478bd9Sstevel@tonic-gate /*LINTED*/ 289*7c478bd9Sstevel@tonic-gate lifr2 = (struct lifreq *)((caddr_t) P.buf+j); 290*7c478bd9Sstevel@tonic-gate if (lifr2->lifr_name[0] == '\0') 291*7c478bd9Sstevel@tonic-gate continue; 292*7c478bd9Sstevel@tonic-gate if (lifr2->lifr_addr.ss_family == lifr->lifr_addr.ss_family 293*7c478bd9Sstevel@tonic-gate /* Compare address info. If this isn't good enough -- 294*7c478bd9Sstevel@tonic-gate i.e., if random padding bytes turn out to differ 295*7c478bd9Sstevel@tonic-gate when the addresses are the same -- then we'll have 296*7c478bd9Sstevel@tonic-gate to do it on a per address family basis. */ 297*7c478bd9Sstevel@tonic-gate && !memcmp (&lifr2->lifr_addr, &lifr->lifr_addr, 298*7c478bd9Sstevel@tonic-gate sizeof (*lifr))) { 299*7c478bd9Sstevel@tonic-gate Tprintf ((" duplicate addr\n")); 300*7c478bd9Sstevel@tonic-gate KRB5_LOG0 (KRB5_INFO, "foreach_localaddr() dup addr"); 301*7c478bd9Sstevel@tonic-gate goto skip; 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate if ((*pass1fn) (data, ss2sa (&lifr->lifr_addr))) 306*7c478bd9Sstevel@tonic-gate goto punt; 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate /* Did we actually get any working sockets? */ 311*7c478bd9Sstevel@tonic-gate FOREACH_AF () 312*7c478bd9Sstevel@tonic-gate if (P.sock != -1) 313*7c478bd9Sstevel@tonic-gate goto have_working_socket; 314*7c478bd9Sstevel@tonic-gate retval = sock_err; 315*7c478bd9Sstevel@tonic-gate goto punt; 316*7c478bd9Sstevel@tonic-gate have_working_socket: 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if (betweenfn != NULL && (*betweenfn)(data)) 319*7c478bd9Sstevel@tonic-gate goto punt; 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate if (pass2fn) 322*7c478bd9Sstevel@tonic-gate FOREACH_AF () 323*7c478bd9Sstevel@tonic-gate if (P.sock >= 0) { 324*7c478bd9Sstevel@tonic-gate for (i = 0; i < P.buf_size; i+= sizeof (*lifr)) { 325*7c478bd9Sstevel@tonic-gate /*LINTED*/ 326*7c478bd9Sstevel@tonic-gate lifr = (struct lifreq *)((caddr_t) P.buf+i); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if (lifr->lifr_name[0] == '\0') 329*7c478bd9Sstevel@tonic-gate /* Marked in first pass to be ignored. */ 330*7c478bd9Sstevel@tonic-gate continue; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate KRB5_LOG (KRB5_INFO, 333*7c478bd9Sstevel@tonic-gate "foreach_localaddr() doing pass2fn i = %d", 334*7c478bd9Sstevel@tonic-gate i); 335*7c478bd9Sstevel@tonic-gate if ((*pass2fn) (data, ss2sa (&lifr->lifr_addr))) 336*7c478bd9Sstevel@tonic-gate goto punt; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate punt: 340*7c478bd9Sstevel@tonic-gate FOREACH_AF () { 341*7c478bd9Sstevel@tonic-gate closesocket(P.sock); 342*7c478bd9Sstevel@tonic-gate free (P.buf); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate return retval; 346*7c478bd9Sstevel@tonic-gate } 347