1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate * 26*7c478bd9Sstevel@tonic-gate * lib/libnsl/nss/netdir_inet.c 27*7c478bd9Sstevel@tonic-gate * 28*7c478bd9Sstevel@tonic-gate * This is where we have chosen to combine every useful bit of code for 29*7c478bd9Sstevel@tonic-gate * all the Solaris frontends to lookup hosts, services, and netdir information 30*7c478bd9Sstevel@tonic-gate * for inet family (udp, tcp) transports. gethostbyYY(), getservbyYY(), and 31*7c478bd9Sstevel@tonic-gate * netdir_getbyYY() are all implemented on top of this code. Similarly, 32*7c478bd9Sstevel@tonic-gate * netdir_options, taddr2uaddr, and uaddr2taddr for inet transports also 33*7c478bd9Sstevel@tonic-gate * find a home here. 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * If the netconfig structure supplied has NO nametoaddr libs (i.e. a "-" 36*7c478bd9Sstevel@tonic-gate * in /etc/netconfig), this code calls the name service switch, and 37*7c478bd9Sstevel@tonic-gate * therefore, /etc/nsswitch.conf is effectively the only place that 38*7c478bd9Sstevel@tonic-gate * dictates hosts/serv lookup policy. 39*7c478bd9Sstevel@tonic-gate * If an administrator chooses to bypass the name service switch by 40*7c478bd9Sstevel@tonic-gate * specifying third party supplied nametoaddr libs in /etc/netconfig, this 41*7c478bd9Sstevel@tonic-gate * implementation does NOT call the name service switch, it merely loops 42*7c478bd9Sstevel@tonic-gate * through the nametoaddr libs. In this case, if this code was called 43*7c478bd9Sstevel@tonic-gate * from gethost/servbyYY() we marshal the inet specific struct into 44*7c478bd9Sstevel@tonic-gate * transport independent netbuf or hostserv, and unmarshal the resulting 45*7c478bd9Sstevel@tonic-gate * nd_addrlist or hostservlist back into hostent and servent, as the case 46*7c478bd9Sstevel@tonic-gate * may be. 47*7c478bd9Sstevel@tonic-gate * 48*7c478bd9Sstevel@tonic-gate * Goes without saying that most of the future bugs in gethost/servbyYY 49*7c478bd9Sstevel@tonic-gate * and netdir_getbyYY are lurking somewhere here. 50*7c478bd9Sstevel@tonic-gate */ 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #include "mt.h" 55*7c478bd9Sstevel@tonic-gate #include <ctype.h> 56*7c478bd9Sstevel@tonic-gate #include <stdio.h> 57*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 58*7c478bd9Sstevel@tonic-gate #include <string.h> 59*7c478bd9Sstevel@tonic-gate #include <unistd.h> 60*7c478bd9Sstevel@tonic-gate #include <stropts.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/byteorder.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 66*7c478bd9Sstevel@tonic-gate #include <errno.h> 67*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 68*7c478bd9Sstevel@tonic-gate #include <thread.h> 69*7c478bd9Sstevel@tonic-gate #include <synch.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 71*7c478bd9Sstevel@tonic-gate #include <netdb.h> 72*7c478bd9Sstevel@tonic-gate #include <netconfig.h> 73*7c478bd9Sstevel@tonic-gate #include <netdir.h> 74*7c478bd9Sstevel@tonic-gate #include <tiuser.h> 75*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 76*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 77*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 78*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 79*7c478bd9Sstevel@tonic-gate #include <net/if.h> 80*7c478bd9Sstevel@tonic-gate #include <inet/ip.h> 81*7c478bd9Sstevel@tonic-gate #include <inet/ip6_asp.h> 82*7c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 83*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h> 84*7c478bd9Sstevel@tonic-gate #include <nss_netdir.h> 85*7c478bd9Sstevel@tonic-gate #include <rpc/trace.h> 86*7c478bd9Sstevel@tonic-gate #include <syslog.h> 87*7c478bd9Sstevel@tonic-gate #include <nsswitch.h> 88*7c478bd9Sstevel@tonic-gate #include "nss.h" 89*7c478bd9Sstevel@tonic-gate #include "nsl_stdio_prv.h" 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate #define MAXIFS 32 92*7c478bd9Sstevel@tonic-gate #define UDPDEV "/dev/udp" 93*7c478bd9Sstevel@tonic-gate #define UDP6DEV "/dev/udp6" 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate #define GETHOSTBUF(host_buf) \ 96*7c478bd9Sstevel@tonic-gate NSS_XbyY_ALLOC(&host_buf, sizeof (struct hostent), NSS_BUFLEN_HOSTS) 97*7c478bd9Sstevel@tonic-gate #define GETSERVBUF(serv_buf) \ 98*7c478bd9Sstevel@tonic-gate NSS_XbyY_ALLOC(&serv_buf, sizeof (struct servent), NSS_BUFLEN_SERVICES) 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate #ifdef PIC 101*7c478bd9Sstevel@tonic-gate #define DOOR_GETHOSTBYNAME_R _door_gethostbyname_r 102*7c478bd9Sstevel@tonic-gate #define DOOR_GETHOSTBYADDR_R _door_gethostbyaddr_r 103*7c478bd9Sstevel@tonic-gate #define DOOR_GETIPNODEBYNAME_R _door_getipnodebyname_r 104*7c478bd9Sstevel@tonic-gate #define DOOR_GETIPNODEBYADDR_R _door_getipnodebyaddr_r 105*7c478bd9Sstevel@tonic-gate #else 106*7c478bd9Sstevel@tonic-gate #define DOOR_GETHOSTBYNAME_R _switch_gethostbyname_r 107*7c478bd9Sstevel@tonic-gate #define DOOR_GETHOSTBYADDR_R _switch_gethostbyaddr_r 108*7c478bd9Sstevel@tonic-gate #define DOOR_GETIPNODEBYNAME_R _switch_getipnodebyname_r 109*7c478bd9Sstevel@tonic-gate #define DOOR_GETIPNODEBYADDR_R _switch_getipnodebyaddr_r 110*7c478bd9Sstevel@tonic-gate #endif /* PIC */ 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate #define DONT_SORT "SORT_ADDRS=NO" 113*7c478bd9Sstevel@tonic-gate #define DONT_SORT2 "SORT_ADDRS=FALSE" 114*7c478bd9Sstevel@tonic-gate #define LINESIZE 100 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate /* 117*7c478bd9Sstevel@tonic-gate * constant values of addresses for HOST_SELF_BIND, HOST_SELF_CONNECT 118*7c478bd9Sstevel@tonic-gate * and localhost. 119*7c478bd9Sstevel@tonic-gate * 120*7c478bd9Sstevel@tonic-gate * The following variables are static to the extent that they should 121*7c478bd9Sstevel@tonic-gate * not be visible outside of this file. 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate static char *localaddr[] = {"\000\000\000\000", NULL}; 124*7c478bd9Sstevel@tonic-gate static char *connectaddr[] = {"\177\000\000\001", NULL}; 125*7c478bd9Sstevel@tonic-gate static char *localaddr6[] = 126*7c478bd9Sstevel@tonic-gate {"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", NULL}; 127*7c478bd9Sstevel@tonic-gate static char *connectaddr6[] = 128*7c478bd9Sstevel@tonic-gate {"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", NULL}; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* IPv4 nd_addrlist */ 131*7c478bd9Sstevel@tonic-gate static mutex_t nd_addr_lock = DEFAULTMUTEX; 132*7c478bd9Sstevel@tonic-gate static struct sockaddr_in sa_con; 133*7c478bd9Sstevel@tonic-gate static struct netbuf nd_conbuf = {sizeof (sa_con),\ 134*7c478bd9Sstevel@tonic-gate sizeof (sa_con), (char *)&sa_con}; 135*7c478bd9Sstevel@tonic-gate static struct nd_addrlist nd_conaddrlist = {1, &nd_conbuf}; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate /* IPv6 nd_addrlist */ 138*7c478bd9Sstevel@tonic-gate static mutex_t nd6_addr_lock = DEFAULTMUTEX; 139*7c478bd9Sstevel@tonic-gate static struct sockaddr_in6 sa6_con; 140*7c478bd9Sstevel@tonic-gate static struct netbuf nd6_conbuf = {sizeof (sa6_con),\ 141*7c478bd9Sstevel@tonic-gate sizeof (sa6_con), (char *)&sa6_con}; 142*7c478bd9Sstevel@tonic-gate static struct nd_addrlist nd6_conaddrlist = {1, &nd6_conbuf}; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate #define LOCALHOST "localhost" 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate struct servent *_switch_getservbyname_r(const char *, const char *, 147*7c478bd9Sstevel@tonic-gate struct servent *, char *, int); 148*7c478bd9Sstevel@tonic-gate struct servent *_switch_getservbyport_r(int, const char *, struct servent *, 149*7c478bd9Sstevel@tonic-gate char *, int); 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate static int __herrno2netdir(int h_errnop); 152*7c478bd9Sstevel@tonic-gate static struct ifinfo *get_local_info(void); 153*7c478bd9Sstevel@tonic-gate static int islocal(); 154*7c478bd9Sstevel@tonic-gate static int getbroadcastnets(struct netconfig *, struct in_addr **); 155*7c478bd9Sstevel@tonic-gate static int hent2ndaddr(int, char **, int *, struct nd_addrlist **); 156*7c478bd9Sstevel@tonic-gate static int ndaddr2hent(int, const char *, struct nd_addrlist *, 157*7c478bd9Sstevel@tonic-gate struct hostent *, char *, int); 158*7c478bd9Sstevel@tonic-gate static int hsents2ndhostservs(struct hostent *, struct servent *, ushort_t, 159*7c478bd9Sstevel@tonic-gate struct nd_hostservlist **); 160*7c478bd9Sstevel@tonic-gate static int ndaddr2srent(const char *, const char *, ushort_t, struct servent *, 161*7c478bd9Sstevel@tonic-gate char *, int); 162*7c478bd9Sstevel@tonic-gate static int ndhostserv2hent(struct netbuf *, struct nd_hostservlist *, 163*7c478bd9Sstevel@tonic-gate struct hostent *, char *, int); 164*7c478bd9Sstevel@tonic-gate static int ndhostserv2srent(int, const char *, struct nd_hostservlist *, 165*7c478bd9Sstevel@tonic-gate struct servent *, char *, int); 166*7c478bd9Sstevel@tonic-gate static int nd2herrno(int nerr); 167*7c478bd9Sstevel@tonic-gate static void order_haddrlist_inet(char **haddrlist, size_t addrcount); 168*7c478bd9Sstevel@tonic-gate static void order_haddrlist_inet6(char **haddrlist, size_t addrcount); 169*7c478bd9Sstevel@tonic-gate static int dstcmp(const void *, const void *); 170*7c478bd9Sstevel@tonic-gate static int nss_strioctl(int af, int cmd, void *ptr, int ilen); 171*7c478bd9Sstevel@tonic-gate static struct in_addr _inet_makeaddr(in_addr_t, in_addr_t); 172*7c478bd9Sstevel@tonic-gate static boolean_t _read_nsw_file(void); 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate /* 175*7c478bd9Sstevel@tonic-gate * Begin: PART I 176*7c478bd9Sstevel@tonic-gate * Top Level Interfaces that gethost/serv/netdir funnel through. 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* 180*7c478bd9Sstevel@tonic-gate * gethost/servbyname always call this function; if they call 181*7c478bd9Sstevel@tonic-gate * with nametoaddr libs in nconf, we call netdir_getbyname 182*7c478bd9Sstevel@tonic-gate * implementation: __classic_netdir_getbyname, otherwise nsswitch. 183*7c478bd9Sstevel@tonic-gate * 184*7c478bd9Sstevel@tonic-gate * netdir_getbyname calls this only if nametoaddr libs are NOT 185*7c478bd9Sstevel@tonic-gate * specified for inet transports; i.e. it's supposed to follow 186*7c478bd9Sstevel@tonic-gate * the name service switch. 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate int 189*7c478bd9Sstevel@tonic-gate _get_hostserv_inetnetdir_byname(struct netconfig *nconf, 190*7c478bd9Sstevel@tonic-gate struct nss_netdirbyname_in *args, union nss_netdirbyname_out *res) 191*7c478bd9Sstevel@tonic-gate { 192*7c478bd9Sstevel@tonic-gate int server_port; 193*7c478bd9Sstevel@tonic-gate int *servp = &server_port; 194*7c478bd9Sstevel@tonic-gate char **haddrlist; 195*7c478bd9Sstevel@tonic-gate uint32_t dotnameaddr; 196*7c478bd9Sstevel@tonic-gate char *dotnamelist[2]; 197*7c478bd9Sstevel@tonic-gate struct in_addr *inaddrs = NULL; 198*7c478bd9Sstevel@tonic-gate struct in6_addr v6nameaddr; 199*7c478bd9Sstevel@tonic-gate char **baddrlist = NULL; 200*7c478bd9Sstevel@tonic-gate extern int _inet_aton(); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate if (nconf == NULL) { 204*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 205*7c478bd9Sstevel@tonic-gate return (ND_BADARG); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate * 1. gethostbyname()/netdir_getbyname() special cases: 210*7c478bd9Sstevel@tonic-gate */ 211*7c478bd9Sstevel@tonic-gate switch (args->op_t) { 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate case NSS_HOST: 214*7c478bd9Sstevel@tonic-gate /* 215*7c478bd9Sstevel@tonic-gate * Worth the performance gain -- assuming a lot of inet apps 216*7c478bd9Sstevel@tonic-gate * actively use "localhost". 217*7c478bd9Sstevel@tonic-gate */ 218*7c478bd9Sstevel@tonic-gate if (strcmp(args->arg.nss.host.name, LOCALHOST) == 0) { 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate mutex_lock(&nd_addr_lock); 221*7c478bd9Sstevel@tonic-gate IN_SET_LOOPBACK_ADDR(&sa_con); 222*7c478bd9Sstevel@tonic-gate _nderror = ndaddr2hent(AF_INET, args->arg.nss.host.name, 223*7c478bd9Sstevel@tonic-gate &nd_conaddrlist, res->nss.host.hent, 224*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buf, 225*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buflen); 226*7c478bd9Sstevel@tonic-gate mutex_unlock(&nd_addr_lock); 227*7c478bd9Sstevel@tonic-gate if (_nderror != ND_OK) 228*7c478bd9Sstevel@tonic-gate *(res->nss.host.herrno_p) = 229*7c478bd9Sstevel@tonic-gate nd2herrno(_nderror); 230*7c478bd9Sstevel@tonic-gate return (_nderror); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate /* 233*7c478bd9Sstevel@tonic-gate * If the caller passed in a dot separated IP notation to 234*7c478bd9Sstevel@tonic-gate * gethostbyname, return that back as the address. 235*7c478bd9Sstevel@tonic-gate * The nd_addr_lock mutex was added to be truely re-entrant. 236*7c478bd9Sstevel@tonic-gate */ 237*7c478bd9Sstevel@tonic-gate if (_inet_aton(args->arg.nss.host.name, 238*7c478bd9Sstevel@tonic-gate (struct in_addr *)&dotnameaddr)) { 239*7c478bd9Sstevel@tonic-gate mutex_lock(&nd_addr_lock); 240*7c478bd9Sstevel@tonic-gate (void) memset((char *)&sa_con, 0, sizeof (sa_con)); 241*7c478bd9Sstevel@tonic-gate sa_con.sin_family = AF_INET; 242*7c478bd9Sstevel@tonic-gate sa_con.sin_addr.s_addr = dotnameaddr; 243*7c478bd9Sstevel@tonic-gate _nderror = ndaddr2hent(AF_INET, args->arg.nss.host.name, 244*7c478bd9Sstevel@tonic-gate &nd_conaddrlist, res->nss.host.hent, 245*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buf, 246*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buflen); 247*7c478bd9Sstevel@tonic-gate mutex_unlock(&nd_addr_lock); 248*7c478bd9Sstevel@tonic-gate if (_nderror != ND_OK) 249*7c478bd9Sstevel@tonic-gate *(res->nss.host.herrno_p) = 250*7c478bd9Sstevel@tonic-gate nd2herrno(_nderror); 251*7c478bd9Sstevel@tonic-gate return (_nderror); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate break; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate case NSS_HOST6: 256*7c478bd9Sstevel@tonic-gate /* 257*7c478bd9Sstevel@tonic-gate * Handle case of literal address string. 258*7c478bd9Sstevel@tonic-gate */ 259*7c478bd9Sstevel@tonic-gate if (strchr(args->arg.nss.host6.name, ':') != NULL && 260*7c478bd9Sstevel@tonic-gate (inet_pton(AF_INET6, args->arg.nss.host6.name, 261*7c478bd9Sstevel@tonic-gate &v6nameaddr) != 0)) { 262*7c478bd9Sstevel@tonic-gate int ret; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate mutex_lock(&nd6_addr_lock); 265*7c478bd9Sstevel@tonic-gate (void) memset((char *)&sa6_con, 0, sizeof (sa6_con)); 266*7c478bd9Sstevel@tonic-gate sa6_con.sin6_family = AF_INET6; 267*7c478bd9Sstevel@tonic-gate memcpy((char *)&(sa6_con.sin6_addr.s6_addr), 268*7c478bd9Sstevel@tonic-gate &v6nameaddr, sizeof (struct in6_addr)); 269*7c478bd9Sstevel@tonic-gate ret = ndaddr2hent(AF_INET6, 270*7c478bd9Sstevel@tonic-gate args->arg.nss.host6.name, 271*7c478bd9Sstevel@tonic-gate &nd6_conaddrlist, res->nss.host.hent, 272*7c478bd9Sstevel@tonic-gate args->arg.nss.host6.buf, 273*7c478bd9Sstevel@tonic-gate args->arg.nss.host6.buflen); 274*7c478bd9Sstevel@tonic-gate mutex_unlock(&nd6_addr_lock); 275*7c478bd9Sstevel@tonic-gate if (ret != ND_OK) 276*7c478bd9Sstevel@tonic-gate *(res->nss.host.herrno_p) = nd2herrno(ret); 277*7c478bd9Sstevel@tonic-gate else 278*7c478bd9Sstevel@tonic-gate res->nss.host.hent->h_aliases = NULL; 279*7c478bd9Sstevel@tonic-gate return (ret); 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate break; 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate case NETDIR_BY: 284*7c478bd9Sstevel@tonic-gate if (args->arg.nd_hs == 0) { 285*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 286*7c478bd9Sstevel@tonic-gate return (ND_BADARG); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate /* 289*7c478bd9Sstevel@tonic-gate * If servname is NULL, return 0 as the port number 290*7c478bd9Sstevel@tonic-gate * If servname is rpcbind, return 111 as the port number 291*7c478bd9Sstevel@tonic-gate * If servname is a number, return it back as the port 292*7c478bd9Sstevel@tonic-gate * number. 293*7c478bd9Sstevel@tonic-gate */ 294*7c478bd9Sstevel@tonic-gate if (args->arg.nd_hs->h_serv == 0) { 295*7c478bd9Sstevel@tonic-gate *servp = htons(0); 296*7c478bd9Sstevel@tonic-gate } else if (strcmp(args->arg.nd_hs->h_serv, "rpcbind") 297*7c478bd9Sstevel@tonic-gate == 0) { 298*7c478bd9Sstevel@tonic-gate *servp = htons(111); 299*7c478bd9Sstevel@tonic-gate } else if (strspn(args->arg.nd_hs->h_serv, "0123456789") 300*7c478bd9Sstevel@tonic-gate == strlen(args->arg.nd_hs->h_serv)) { 301*7c478bd9Sstevel@tonic-gate *servp = htons(atoi(args->arg.nd_hs->h_serv)); 302*7c478bd9Sstevel@tonic-gate } else { 303*7c478bd9Sstevel@tonic-gate /* i.e. need to call a name service on this */ 304*7c478bd9Sstevel@tonic-gate servp = NULL; 305*7c478bd9Sstevel@tonic-gate } 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* 308*7c478bd9Sstevel@tonic-gate * If the hostname is HOST_SELF_BIND, we return 0.0.0.0 309*7c478bd9Sstevel@tonic-gate * so the binding can be contacted through all 310*7c478bd9Sstevel@tonic-gate * interfaces. If the hostname is HOST_SELF_CONNECT, 311*7c478bd9Sstevel@tonic-gate * we return 127.0.0.1 so the address can be connected 312*7c478bd9Sstevel@tonic-gate * to locally. If the hostname is HOST_ANY, we return 313*7c478bd9Sstevel@tonic-gate * no addresses because IP doesn't know how to specify 314*7c478bd9Sstevel@tonic-gate * a service without a host. And finally if we specify 315*7c478bd9Sstevel@tonic-gate * HOST_BROADCAST then we ask a tli fd to tell us what 316*7c478bd9Sstevel@tonic-gate * the broadcast addresses are for any udp 317*7c478bd9Sstevel@tonic-gate * interfaces on this machine. 318*7c478bd9Sstevel@tonic-gate */ 319*7c478bd9Sstevel@tonic-gate if (args->arg.nd_hs->h_host == 0) { 320*7c478bd9Sstevel@tonic-gate _nderror = ND_NOHOST; 321*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 322*7c478bd9Sstevel@tonic-gate } else if ((strcmp(args->arg.nd_hs->h_host, 323*7c478bd9Sstevel@tonic-gate HOST_SELF_BIND) == 0)) { 324*7c478bd9Sstevel@tonic-gate haddrlist = localaddr; 325*7c478bd9Sstevel@tonic-gate } else if ((strcmp(args->arg.nd_hs->h_host, 326*7c478bd9Sstevel@tonic-gate HOST_SELF_CONNECT) == 0)) { 327*7c478bd9Sstevel@tonic-gate haddrlist = connectaddr; 328*7c478bd9Sstevel@tonic-gate } else if ((strcmp(args->arg.nd_hs->h_host, 329*7c478bd9Sstevel@tonic-gate LOCALHOST) == 0)) { 330*7c478bd9Sstevel@tonic-gate haddrlist = connectaddr; 331*7c478bd9Sstevel@tonic-gate } else if ((int)(dotnameaddr = 332*7c478bd9Sstevel@tonic-gate inet_addr(args->arg.nd_hs->h_host)) != -1) { 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * If the caller passed in a dot separated IP 335*7c478bd9Sstevel@tonic-gate * notation to netdir_getbyname, convert that 336*7c478bd9Sstevel@tonic-gate * back into address. 337*7c478bd9Sstevel@tonic-gate */ 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate dotnamelist[0] = (char *)&dotnameaddr; 340*7c478bd9Sstevel@tonic-gate dotnamelist[1] = NULL; 341*7c478bd9Sstevel@tonic-gate haddrlist = dotnamelist; 342*7c478bd9Sstevel@tonic-gate } else if ((strcmp(args->arg.nd_hs->h_host, 343*7c478bd9Sstevel@tonic-gate HOST_BROADCAST) == 0)) { 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * Now that inaddrs and baddrlist are 346*7c478bd9Sstevel@tonic-gate * dynamically allocated, care must be 347*7c478bd9Sstevel@tonic-gate * taken in freeing up the 348*7c478bd9Sstevel@tonic-gate * memory at each 'return()' point. 349*7c478bd9Sstevel@tonic-gate * 350*7c478bd9Sstevel@tonic-gate * Early return protection (using 351*7c478bd9Sstevel@tonic-gate * FREE_return()) is needed only in NETDIR_BY 352*7c478bd9Sstevel@tonic-gate * cases because dynamic allocation is used 353*7c478bd9Sstevel@tonic-gate * when args->op_t == NETDIR_BY. 354*7c478bd9Sstevel@tonic-gate * 355*7c478bd9Sstevel@tonic-gate * Early return protection is not needed in 356*7c478bd9Sstevel@tonic-gate * haddrlist==0 conditionals because dynamic 357*7c478bd9Sstevel@tonic-gate * allocation guarantees haddrlist!=0. 358*7c478bd9Sstevel@tonic-gate * 359*7c478bd9Sstevel@tonic-gate * Early return protection is not needed in most 360*7c478bd9Sstevel@tonic-gate * servp!=0 conditionals because this is handled 361*7c478bd9Sstevel@tonic-gate * (and returned) first. 362*7c478bd9Sstevel@tonic-gate */ 363*7c478bd9Sstevel@tonic-gate #define FREE_return(ret) \ 364*7c478bd9Sstevel@tonic-gate { \ 365*7c478bd9Sstevel@tonic-gate if (inaddrs) \ 366*7c478bd9Sstevel@tonic-gate free(inaddrs); \ 367*7c478bd9Sstevel@tonic-gate if (baddrlist) \ 368*7c478bd9Sstevel@tonic-gate free(baddrlist); \ 369*7c478bd9Sstevel@tonic-gate _nderror = ret; \ 370*7c478bd9Sstevel@tonic-gate return (ret); \ 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate int i, bnets; 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate bnets = getbroadcastnets(nconf, &inaddrs); 375*7c478bd9Sstevel@tonic-gate if (bnets == 0) { 376*7c478bd9Sstevel@tonic-gate _nderror = ND_NOHOST; 377*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate baddrlist = 380*7c478bd9Sstevel@tonic-gate (char **)malloc((bnets+1)*sizeof (char *)); 381*7c478bd9Sstevel@tonic-gate if (baddrlist == NULL) 382*7c478bd9Sstevel@tonic-gate FREE_return(ND_NOMEM); 383*7c478bd9Sstevel@tonic-gate for (i = 0; i < bnets; i++) 384*7c478bd9Sstevel@tonic-gate baddrlist[i] = (char *)&inaddrs[i]; 385*7c478bd9Sstevel@tonic-gate baddrlist[i] = NULL; 386*7c478bd9Sstevel@tonic-gate haddrlist = baddrlist; 387*7c478bd9Sstevel@tonic-gate } else { 388*7c478bd9Sstevel@tonic-gate /* i.e. need to call a name service on this */ 389*7c478bd9Sstevel@tonic-gate haddrlist = 0; 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate if (haddrlist && servp) { 393*7c478bd9Sstevel@tonic-gate int ret; 394*7c478bd9Sstevel@tonic-gate /* 395*7c478bd9Sstevel@tonic-gate * Convert h_addr_list into nd_addrlist. 396*7c478bd9Sstevel@tonic-gate * malloc's will be done, freed using 397*7c478bd9Sstevel@tonic-gate * netdir_free. 398*7c478bd9Sstevel@tonic-gate */ 399*7c478bd9Sstevel@tonic-gate ret = hent2ndaddr(AF_INET, haddrlist, servp, 400*7c478bd9Sstevel@tonic-gate res->nd_alist); 401*7c478bd9Sstevel@tonic-gate FREE_return(ret) 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate break; 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate case NETDIR_BY6: 407*7c478bd9Sstevel@tonic-gate if (args->arg.nd_hs == 0) { 408*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 409*7c478bd9Sstevel@tonic-gate return (ND_BADARG); 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate /* 412*7c478bd9Sstevel@tonic-gate * If servname is NULL, return 0 as the port number. 413*7c478bd9Sstevel@tonic-gate * If servname is rpcbind, return 111 as the port number 414*7c478bd9Sstevel@tonic-gate * If servname is a number, return it back as the port 415*7c478bd9Sstevel@tonic-gate * number. 416*7c478bd9Sstevel@tonic-gate */ 417*7c478bd9Sstevel@tonic-gate if (args->arg.nd_hs->h_serv == 0) { 418*7c478bd9Sstevel@tonic-gate *servp = htons(0); 419*7c478bd9Sstevel@tonic-gate } else if (strcmp(args->arg.nd_hs->h_serv, 420*7c478bd9Sstevel@tonic-gate "rpcbind") == 0) { 421*7c478bd9Sstevel@tonic-gate *servp = htons(111); 422*7c478bd9Sstevel@tonic-gate } else if (strspn(args->arg.nd_hs->h_serv, "0123456789") 423*7c478bd9Sstevel@tonic-gate == strlen(args->arg.nd_hs->h_serv)) { 424*7c478bd9Sstevel@tonic-gate *servp = htons(atoi(args->arg.nd_hs->h_serv)); 425*7c478bd9Sstevel@tonic-gate } else { 426*7c478bd9Sstevel@tonic-gate /* i.e. need to call a name service on this */ 427*7c478bd9Sstevel@tonic-gate servp = NULL; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* 431*7c478bd9Sstevel@tonic-gate * If the hostname is HOST_SELF_BIND, we return ipv6 432*7c478bd9Sstevel@tonic-gate * localaddress so the binding can be contacted through 433*7c478bd9Sstevel@tonic-gate * all interfaces. 434*7c478bd9Sstevel@tonic-gate * If the hostname is HOST_SELF_CONNECT, we return 435*7c478bd9Sstevel@tonic-gate * ipv6 loopback address so the address can be connected 436*7c478bd9Sstevel@tonic-gate * to locally. 437*7c478bd9Sstevel@tonic-gate * If the hostname is HOST_ANY, we return no addresses 438*7c478bd9Sstevel@tonic-gate * because IP doesn't know how to specify a service 439*7c478bd9Sstevel@tonic-gate * without a host. 440*7c478bd9Sstevel@tonic-gate * And finally if we specify HOST_BROADCAST then we 441*7c478bd9Sstevel@tonic-gate * disallow since IPV6 does not have any 442*7c478bd9Sstevel@tonic-gate * broadcast concept. 443*7c478bd9Sstevel@tonic-gate */ 444*7c478bd9Sstevel@tonic-gate if (args->arg.nd_hs->h_host == 0) { 445*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 446*7c478bd9Sstevel@tonic-gate } else if ((strcmp(args->arg.nd_hs->h_host, 447*7c478bd9Sstevel@tonic-gate HOST_SELF_BIND) == 0)) { 448*7c478bd9Sstevel@tonic-gate haddrlist = localaddr6; 449*7c478bd9Sstevel@tonic-gate } else if ((strcmp(args->arg.nd_hs->h_host, 450*7c478bd9Sstevel@tonic-gate HOST_SELF_CONNECT) == 0)) { 451*7c478bd9Sstevel@tonic-gate haddrlist = connectaddr6; 452*7c478bd9Sstevel@tonic-gate } else if ((strcmp(args->arg.nd_hs->h_host, 453*7c478bd9Sstevel@tonic-gate LOCALHOST) == 0)) { 454*7c478bd9Sstevel@tonic-gate haddrlist = connectaddr6; 455*7c478bd9Sstevel@tonic-gate } else if (strchr(args->arg.nd_hs->h_host, ':') 456*7c478bd9Sstevel@tonic-gate != NULL) { 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* 459*7c478bd9Sstevel@tonic-gate * If the caller passed in a dot separated IP notation 460*7c478bd9Sstevel@tonic-gate * to netdir_getbyname, convert that back into address. 461*7c478bd9Sstevel@tonic-gate */ 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate if ((inet_pton(AF_INET6, 464*7c478bd9Sstevel@tonic-gate args->arg.nd_hs->h_host, 465*7c478bd9Sstevel@tonic-gate &v6nameaddr)) != 0) { 466*7c478bd9Sstevel@tonic-gate dotnamelist[0] = (char *)&v6nameaddr; 467*7c478bd9Sstevel@tonic-gate dotnamelist[1] = NULL; 468*7c478bd9Sstevel@tonic-gate haddrlist = dotnamelist; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate else 471*7c478bd9Sstevel@tonic-gate /* not sure what to return */ 472*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate } else if ((strcmp(args->arg.nd_hs->h_host, 475*7c478bd9Sstevel@tonic-gate HOST_BROADCAST) == 0)) { 476*7c478bd9Sstevel@tonic-gate /* 477*7c478bd9Sstevel@tonic-gate * Don't support broadcast in 478*7c478bd9Sstevel@tonic-gate * IPV6 479*7c478bd9Sstevel@tonic-gate */ 480*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 481*7c478bd9Sstevel@tonic-gate } else { 482*7c478bd9Sstevel@tonic-gate /* i.e. need to call a name service on this */ 483*7c478bd9Sstevel@tonic-gate haddrlist = 0; 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate if (haddrlist && servp) { 487*7c478bd9Sstevel@tonic-gate int ret; 488*7c478bd9Sstevel@tonic-gate /* 489*7c478bd9Sstevel@tonic-gate * Convert h_addr_list into nd_addrlist. 490*7c478bd9Sstevel@tonic-gate * malloc's will be done, freed 491*7c478bd9Sstevel@tonic-gate * using netdir_free. 492*7c478bd9Sstevel@tonic-gate */ 493*7c478bd9Sstevel@tonic-gate ret = hent2ndaddr(AF_INET6, haddrlist, 494*7c478bd9Sstevel@tonic-gate servp, res->nd_alist); 495*7c478bd9Sstevel@tonic-gate FREE_return(ret) 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate break; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate /* 503*7c478bd9Sstevel@tonic-gate * 2. Most common scenario. This is the way we ship /etc/netconfig. 504*7c478bd9Sstevel@tonic-gate * Emphasis on improving performance in the "if" part. 505*7c478bd9Sstevel@tonic-gate */ 506*7c478bd9Sstevel@tonic-gate if (nconf->nc_nlookups == 0) { 507*7c478bd9Sstevel@tonic-gate struct hostent *he = NULL, *tmphe; 508*7c478bd9Sstevel@tonic-gate struct servent *se; 509*7c478bd9Sstevel@tonic-gate int ret; 510*7c478bd9Sstevel@tonic-gate nss_XbyY_buf_t *ndbuf4switch = 0; 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate switch (args->op_t) { 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate case NSS_HOST: 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate he = DOOR_GETHOSTBYNAME_R(args->arg.nss.host.name, 517*7c478bd9Sstevel@tonic-gate res->nss.host.hent, args->arg.nss.host.buf, 518*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buflen, 519*7c478bd9Sstevel@tonic-gate res->nss.host.herrno_p); 520*7c478bd9Sstevel@tonic-gate if (he == NULL) 521*7c478bd9Sstevel@tonic-gate return (_nderror = ND_NOHOST); 522*7c478bd9Sstevel@tonic-gate return (_nderror = ND_OK); 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate case NSS_HOST6: 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate he = DOOR_GETIPNODEBYNAME_R(args->arg.nss.host6.name, 527*7c478bd9Sstevel@tonic-gate res->nss.host.hent, args->arg.nss.host.buf, 528*7c478bd9Sstevel@tonic-gate args->arg.nss.host6.buflen, 529*7c478bd9Sstevel@tonic-gate args->arg.nss.host6.af_family, 530*7c478bd9Sstevel@tonic-gate args->arg.nss.host6.flags, 531*7c478bd9Sstevel@tonic-gate res->nss.host.herrno_p); 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate if (he == NULL) { 534*7c478bd9Sstevel@tonic-gate trace1(TR__get_hostserv_inetnetdir_byname, 12); 535*7c478bd9Sstevel@tonic-gate return (_nderror = ND_NOHOST); 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate return (_nderror = ND_OK); 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate case NSS_SERV: 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate se = _switch_getservbyname_r(args->arg.nss.serv.name, 542*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.proto, 543*7c478bd9Sstevel@tonic-gate res->nss.serv, args->arg.nss.serv.buf, 544*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.buflen); 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate _nderror = ND_OK; 547*7c478bd9Sstevel@tonic-gate if (se == 0) 548*7c478bd9Sstevel@tonic-gate _nderror = ND_NOSERV; 549*7c478bd9Sstevel@tonic-gate return (_nderror); 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate case NETDIR_BY: 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate if (servp == 0) { 554*7c478bd9Sstevel@tonic-gate char *proto = 555*7c478bd9Sstevel@tonic-gate (strcmp(nconf->nc_proto, NC_TCP) == 0) ? NC_TCP : NC_UDP; 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate /* 558*7c478bd9Sstevel@tonic-gate * We go through all this for just one port number, 559*7c478bd9Sstevel@tonic-gate * which is most often constant. How about linking in 560*7c478bd9Sstevel@tonic-gate * an indexed database of well-known ports in the name 561*7c478bd9Sstevel@tonic-gate * of performance ? 562*7c478bd9Sstevel@tonic-gate */ 563*7c478bd9Sstevel@tonic-gate GETSERVBUF(ndbuf4switch); 564*7c478bd9Sstevel@tonic-gate if (ndbuf4switch == 0) 565*7c478bd9Sstevel@tonic-gate FREE_return(ND_NOMEM); 566*7c478bd9Sstevel@tonic-gate se = _switch_getservbyname_r(args->arg.nd_hs->h_serv, 567*7c478bd9Sstevel@tonic-gate proto, ndbuf4switch->result, 568*7c478bd9Sstevel@tonic-gate ndbuf4switch->buffer, ndbuf4switch->buflen); 569*7c478bd9Sstevel@tonic-gate if (!se) { 570*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4switch); 571*7c478bd9Sstevel@tonic-gate FREE_return(ND_NOSERV) 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate server_port = se->s_port; 574*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4switch); 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate if (haddrlist == 0) { 578*7c478bd9Sstevel@tonic-gate int h_errnop = 0; 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate GETHOSTBUF(ndbuf4switch); 581*7c478bd9Sstevel@tonic-gate if (ndbuf4switch == 0) { 582*7c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 583*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate /* 586*7c478bd9Sstevel@tonic-gate * Search the ipnodes (v6) path first, 587*7c478bd9Sstevel@tonic-gate * search will return the v4 addresses 588*7c478bd9Sstevel@tonic-gate * as v4mapped addresses. 589*7c478bd9Sstevel@tonic-gate */ 590*7c478bd9Sstevel@tonic-gate if ((tmphe = DOOR_GETIPNODEBYNAME_R( 591*7c478bd9Sstevel@tonic-gate args->arg.nd_hs->h_host, 592*7c478bd9Sstevel@tonic-gate ndbuf4switch->result, ndbuf4switch->buffer, 593*7c478bd9Sstevel@tonic-gate ndbuf4switch->buflen, args->arg.nss.host6.af_family, 594*7c478bd9Sstevel@tonic-gate args->arg.nss.host6.flags, &h_errnop)) != NULL) 595*7c478bd9Sstevel@tonic-gate he = __mappedtov4(tmphe, &h_errnop); 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate if (he == NULL) { 598*7c478bd9Sstevel@tonic-gate /* Failover case, try hosts db for v4 address */ 599*7c478bd9Sstevel@tonic-gate he = DOOR_GETHOSTBYNAME_R( 600*7c478bd9Sstevel@tonic-gate args->arg.nd_hs->h_host, 601*7c478bd9Sstevel@tonic-gate ndbuf4switch->result, ndbuf4switch->buffer, 602*7c478bd9Sstevel@tonic-gate ndbuf4switch->buflen, &h_errnop); 603*7c478bd9Sstevel@tonic-gate if (he == NULL) { 604*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4switch); 605*7c478bd9Sstevel@tonic-gate _nderror = h_errnop ? 606*7c478bd9Sstevel@tonic-gate __herrno2netdir(h_errnop) : 607*7c478bd9Sstevel@tonic-gate ND_NOHOST; 608*7c478bd9Sstevel@tonic-gate return (_nderror); 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate /* 611*7c478bd9Sstevel@tonic-gate * Convert h_addr_list into nd_addrlist. 612*7c478bd9Sstevel@tonic-gate * malloc's will be done, freed using 613*7c478bd9Sstevel@tonic-gate * netdir_free. 614*7c478bd9Sstevel@tonic-gate */ 615*7c478bd9Sstevel@tonic-gate ret = hent2ndaddr(AF_INET, he->h_addr_list, 616*7c478bd9Sstevel@tonic-gate &server_port, res->nd_alist); 617*7c478bd9Sstevel@tonic-gate } else { 618*7c478bd9Sstevel@tonic-gate /* 619*7c478bd9Sstevel@tonic-gate * Convert h_addr_list into nd_addrlist. 620*7c478bd9Sstevel@tonic-gate * malloc's will be done, freed using 621*7c478bd9Sstevel@tonic-gate * netdir_free. 622*7c478bd9Sstevel@tonic-gate */ 623*7c478bd9Sstevel@tonic-gate ret = hent2ndaddr(AF_INET, he->h_addr_list, 624*7c478bd9Sstevel@tonic-gate &server_port, res->nd_alist); 625*7c478bd9Sstevel@tonic-gate freehostent(he); 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate _nderror = ret; 629*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4switch); 630*7c478bd9Sstevel@tonic-gate return (ret); 631*7c478bd9Sstevel@tonic-gate } else { 632*7c478bd9Sstevel@tonic-gate int ret; 633*7c478bd9Sstevel@tonic-gate /* 634*7c478bd9Sstevel@tonic-gate * Convert h_addr_list into nd_addrlist. 635*7c478bd9Sstevel@tonic-gate * malloc's will be done, freed using netdir_free. 636*7c478bd9Sstevel@tonic-gate */ 637*7c478bd9Sstevel@tonic-gate ret = hent2ndaddr(AF_INET, haddrlist, 638*7c478bd9Sstevel@tonic-gate &server_port, res->nd_alist); 639*7c478bd9Sstevel@tonic-gate FREE_return(ret) 640*7c478bd9Sstevel@tonic-gate } 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate case NETDIR_BY6: 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate if (servp == 0) { 646*7c478bd9Sstevel@tonic-gate char *proto = 647*7c478bd9Sstevel@tonic-gate (strcmp(nconf->nc_proto, NC_TCP) == 0) ? NC_TCP : NC_UDP; 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate /* 650*7c478bd9Sstevel@tonic-gate * We go through all this for just 651*7c478bd9Sstevel@tonic-gate * one port number, 652*7c478bd9Sstevel@tonic-gate * which is most often constant. 653*7c478bd9Sstevel@tonic-gate * How about linking in 654*7c478bd9Sstevel@tonic-gate * an indexed database of well-known 655*7c478bd9Sstevel@tonic-gate * ports in the name 656*7c478bd9Sstevel@tonic-gate * of performance ? 657*7c478bd9Sstevel@tonic-gate */ 658*7c478bd9Sstevel@tonic-gate GETSERVBUF(ndbuf4switch); 659*7c478bd9Sstevel@tonic-gate if (ndbuf4switch == 0) 660*7c478bd9Sstevel@tonic-gate FREE_return(ND_NOMEM); 661*7c478bd9Sstevel@tonic-gate se = _switch_getservbyname_r( 662*7c478bd9Sstevel@tonic-gate args->arg.nd_hs->h_serv, 663*7c478bd9Sstevel@tonic-gate proto, ndbuf4switch->result, 664*7c478bd9Sstevel@tonic-gate ndbuf4switch->buffer, ndbuf4switch->buflen); 665*7c478bd9Sstevel@tonic-gate if (!se) { 666*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4switch); 667*7c478bd9Sstevel@tonic-gate FREE_return(ND_NOSERV) 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate server_port = se->s_port; 670*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4switch); 671*7c478bd9Sstevel@tonic-gate } 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate if (haddrlist == 0) { 674*7c478bd9Sstevel@tonic-gate int h_errnop = 0; 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate GETHOSTBUF(ndbuf4switch); 677*7c478bd9Sstevel@tonic-gate if (ndbuf4switch == 0) { 678*7c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 679*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate he = DOOR_GETIPNODEBYNAME_R( 682*7c478bd9Sstevel@tonic-gate args->arg.nd_hs->h_host, 683*7c478bd9Sstevel@tonic-gate ndbuf4switch->result, ndbuf4switch->buffer, 684*7c478bd9Sstevel@tonic-gate ndbuf4switch->buflen, 685*7c478bd9Sstevel@tonic-gate args->arg.nss.host6.af_family, 686*7c478bd9Sstevel@tonic-gate args->arg.nss.host6.flags, &h_errnop); 687*7c478bd9Sstevel@tonic-gate if (he == NULL) { 688*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4switch); 689*7c478bd9Sstevel@tonic-gate _nderror = h_errnop ? 690*7c478bd9Sstevel@tonic-gate __herrno2netdir(h_errnop) : 691*7c478bd9Sstevel@tonic-gate ND_NOHOST; 692*7c478bd9Sstevel@tonic-gate return (_nderror); 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate /* 695*7c478bd9Sstevel@tonic-gate * Convert h_addr_list into nd_addrlist. 696*7c478bd9Sstevel@tonic-gate * malloc's will be done, 697*7c478bd9Sstevel@tonic-gate * freed using netdir_free. 698*7c478bd9Sstevel@tonic-gate */ 699*7c478bd9Sstevel@tonic-gate ret = hent2ndaddr(AF_INET6, 700*7c478bd9Sstevel@tonic-gate ((struct hostent *)(ndbuf4switch->result))->h_addr_list, 701*7c478bd9Sstevel@tonic-gate &server_port, res->nd_alist); 702*7c478bd9Sstevel@tonic-gate _nderror = ret; 703*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4switch); 704*7c478bd9Sstevel@tonic-gate return (ret); 705*7c478bd9Sstevel@tonic-gate } else { 706*7c478bd9Sstevel@tonic-gate int ret; 707*7c478bd9Sstevel@tonic-gate /* 708*7c478bd9Sstevel@tonic-gate * Convert h_addr_list into nd_addrlist. 709*7c478bd9Sstevel@tonic-gate * malloc's will be done, 710*7c478bd9Sstevel@tonic-gate * freed using netdir_free. 711*7c478bd9Sstevel@tonic-gate */ 712*7c478bd9Sstevel@tonic-gate ret = hent2ndaddr(AF_INET6, haddrlist, 713*7c478bd9Sstevel@tonic-gate &server_port, res->nd_alist); 714*7c478bd9Sstevel@tonic-gate FREE_return(ret) 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate default: 718*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 719*7c478bd9Sstevel@tonic-gate return (ND_BADARG); /* should never happen */ 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate } else { 723*7c478bd9Sstevel@tonic-gate /* haddrlist is no longer used, so clean up */ 724*7c478bd9Sstevel@tonic-gate if (inaddrs) 725*7c478bd9Sstevel@tonic-gate free(inaddrs); 726*7c478bd9Sstevel@tonic-gate if (baddrlist) 727*7c478bd9Sstevel@tonic-gate free(baddrlist); 728*7c478bd9Sstevel@tonic-gate } 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate /* 731*7c478bd9Sstevel@tonic-gate * 3. We come this far only if nametoaddr libs are specified for 732*7c478bd9Sstevel@tonic-gate * inet transports and we are called by gethost/servbyname only. 733*7c478bd9Sstevel@tonic-gate */ 734*7c478bd9Sstevel@tonic-gate switch (args->op_t) { 735*7c478bd9Sstevel@tonic-gate struct nd_hostserv service; 736*7c478bd9Sstevel@tonic-gate struct nd_addrlist *addrs; 737*7c478bd9Sstevel@tonic-gate int ret; 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate case NSS_HOST: 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate service.h_host = (char *)args->arg.nss.host.name; 742*7c478bd9Sstevel@tonic-gate service.h_serv = NULL; 743*7c478bd9Sstevel@tonic-gate if ((_nderror = __classic_netdir_getbyname(nconf, 744*7c478bd9Sstevel@tonic-gate &service, &addrs)) != ND_OK) { 745*7c478bd9Sstevel@tonic-gate *(res->nss.host.herrno_p) = nd2herrno(_nderror); 746*7c478bd9Sstevel@tonic-gate return (_nderror); 747*7c478bd9Sstevel@tonic-gate } 748*7c478bd9Sstevel@tonic-gate /* 749*7c478bd9Sstevel@tonic-gate * convert addresses back into sockaddr for gethostbyname. 750*7c478bd9Sstevel@tonic-gate */ 751*7c478bd9Sstevel@tonic-gate ret = ndaddr2hent(AF_INET, service.h_host, addrs, 752*7c478bd9Sstevel@tonic-gate res->nss.host.hent, args->arg.nss.host.buf, 753*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buflen); 754*7c478bd9Sstevel@tonic-gate if (ret != ND_OK) 755*7c478bd9Sstevel@tonic-gate *(res->nss.host.herrno_p) = nd2herrno(ret); 756*7c478bd9Sstevel@tonic-gate netdir_free((char *)addrs, ND_ADDRLIST); 757*7c478bd9Sstevel@tonic-gate _nderror = ret; 758*7c478bd9Sstevel@tonic-gate return (ret); 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate case NSS_SERV: 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate if (args->arg.nss.serv.proto == NULL) { 763*7c478bd9Sstevel@tonic-gate /* 764*7c478bd9Sstevel@tonic-gate * A similar HACK showed up in Solaris 2.3. 765*7c478bd9Sstevel@tonic-gate * The caller wild-carded proto -- i.e. will 766*7c478bd9Sstevel@tonic-gate * accept a match using tcp or udp for the port 767*7c478bd9Sstevel@tonic-gate * number. Since we have no hope of getting 768*7c478bd9Sstevel@tonic-gate * directly to a name service switch backend 769*7c478bd9Sstevel@tonic-gate * from here that understands this semantics, 770*7c478bd9Sstevel@tonic-gate * we try calling the netdir interfaces first 771*7c478bd9Sstevel@tonic-gate * with "tcp" and then "udp". 772*7c478bd9Sstevel@tonic-gate */ 773*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.proto = "tcp"; 774*7c478bd9Sstevel@tonic-gate _nderror = _get_hostserv_inetnetdir_byname(nconf, args, 775*7c478bd9Sstevel@tonic-gate res); 776*7c478bd9Sstevel@tonic-gate if (_nderror != ND_OK) { 777*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.proto = "udp"; 778*7c478bd9Sstevel@tonic-gate _nderror = 779*7c478bd9Sstevel@tonic-gate _get_hostserv_inetnetdir_byname(nconf, 780*7c478bd9Sstevel@tonic-gate args, res); 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate return (_nderror); 783*7c478bd9Sstevel@tonic-gate } 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate /* 786*7c478bd9Sstevel@tonic-gate * Third-parties should optimize their nametoaddr 787*7c478bd9Sstevel@tonic-gate * libraries for the HOST_SELF case. 788*7c478bd9Sstevel@tonic-gate */ 789*7c478bd9Sstevel@tonic-gate service.h_host = HOST_SELF; 790*7c478bd9Sstevel@tonic-gate service.h_serv = (char *)args->arg.nss.serv.name; 791*7c478bd9Sstevel@tonic-gate if ((_nderror = __classic_netdir_getbyname(nconf, 792*7c478bd9Sstevel@tonic-gate &service, &addrs)) != ND_OK) { 793*7c478bd9Sstevel@tonic-gate return (_nderror); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate /* 796*7c478bd9Sstevel@tonic-gate * convert addresses back into servent for getservbyname. 797*7c478bd9Sstevel@tonic-gate */ 798*7c478bd9Sstevel@tonic-gate _nderror = ndaddr2srent(service.h_serv, 799*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.proto, 800*7c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)addrs->n_addrs->buf)->sin_port, 801*7c478bd9Sstevel@tonic-gate res->nss.serv, 802*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.buf, args->arg.nss.serv.buflen); 803*7c478bd9Sstevel@tonic-gate netdir_free((char *)addrs, ND_ADDRLIST); 804*7c478bd9Sstevel@tonic-gate return (_nderror); 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate default: 807*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 808*7c478bd9Sstevel@tonic-gate return (ND_BADARG); /* should never happen */ 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate /* 813*7c478bd9Sstevel@tonic-gate * gethostbyaddr/servbyport always call this function; if they call 814*7c478bd9Sstevel@tonic-gate * with nametoaddr libs in nconf, we call netdir_getbyaddr 815*7c478bd9Sstevel@tonic-gate * implementation __classic_netdir_getbyaddr, otherwise nsswitch. 816*7c478bd9Sstevel@tonic-gate * 817*7c478bd9Sstevel@tonic-gate * netdir_getbyaddr calls this only if nametoaddr libs are NOT 818*7c478bd9Sstevel@tonic-gate * specified for inet transports; i.e. it's supposed to follow 819*7c478bd9Sstevel@tonic-gate * the name service switch. 820*7c478bd9Sstevel@tonic-gate */ 821*7c478bd9Sstevel@tonic-gate int 822*7c478bd9Sstevel@tonic-gate _get_hostserv_inetnetdir_byaddr(struct netconfig *nconf, 823*7c478bd9Sstevel@tonic-gate struct nss_netdirbyaddr_in *args, union nss_netdirbyaddr_out *res) 824*7c478bd9Sstevel@tonic-gate { 825*7c478bd9Sstevel@tonic-gate if (nconf == 0) { 826*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 827*7c478bd9Sstevel@tonic-gate return (_nderror); 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate /* 831*7c478bd9Sstevel@tonic-gate * 1. gethostbyaddr()/netdir_getbyaddr() special cases: 832*7c478bd9Sstevel@tonic-gate */ 833*7c478bd9Sstevel@tonic-gate switch (args->op_t) { 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate case NSS_HOST: 836*7c478bd9Sstevel@tonic-gate /* 837*7c478bd9Sstevel@tonic-gate * Worth the performance gain: assuming a lot of inet apps 838*7c478bd9Sstevel@tonic-gate * actively use "127.0.0.1". 839*7c478bd9Sstevel@tonic-gate */ 840*7c478bd9Sstevel@tonic-gate if (*(uint32_t *)(args->arg.nss.host.addr) == 841*7c478bd9Sstevel@tonic-gate htonl(INADDR_LOOPBACK)) { 842*7c478bd9Sstevel@tonic-gate mutex_lock(&nd_addr_lock); 843*7c478bd9Sstevel@tonic-gate IN_SET_LOOPBACK_ADDR(&sa_con); 844*7c478bd9Sstevel@tonic-gate _nderror = ndaddr2hent(AF_INET, LOCALHOST, 845*7c478bd9Sstevel@tonic-gate &nd_conaddrlist, res->nss.host.hent, 846*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buf, 847*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buflen); 848*7c478bd9Sstevel@tonic-gate mutex_unlock(&nd_addr_lock); 849*7c478bd9Sstevel@tonic-gate if (_nderror != ND_OK) 850*7c478bd9Sstevel@tonic-gate *(res->nss.host.herrno_p) = 851*7c478bd9Sstevel@tonic-gate nd2herrno(_nderror); 852*7c478bd9Sstevel@tonic-gate return (_nderror); 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate break; 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate case NETDIR_BY: 857*7c478bd9Sstevel@tonic-gate case NETDIR_BY_NOSRV: 858*7c478bd9Sstevel@tonic-gate { 859*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate if (args->arg.nd_nbuf == NULL) { 862*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 863*7c478bd9Sstevel@tonic-gate return (_nderror); 864*7c478bd9Sstevel@tonic-gate } 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate /* 867*7c478bd9Sstevel@tonic-gate * Validate the address which was passed 868*7c478bd9Sstevel@tonic-gate * as the request. 869*7c478bd9Sstevel@tonic-gate */ 870*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)args->arg.nd_nbuf->buf; 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate if ((args->arg.nd_nbuf->len != 873*7c478bd9Sstevel@tonic-gate sizeof (struct sockaddr_in)) || 874*7c478bd9Sstevel@tonic-gate (sin->sin_family != AF_INET)) { 875*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 876*7c478bd9Sstevel@tonic-gate return (_nderror); 877*7c478bd9Sstevel@tonic-gate } 878*7c478bd9Sstevel@tonic-gate } 879*7c478bd9Sstevel@tonic-gate break; 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate case NETDIR_BY6: 882*7c478bd9Sstevel@tonic-gate case NETDIR_BY_NOSRV6: 883*7c478bd9Sstevel@tonic-gate { 884*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate if (args->arg.nd_nbuf == NULL) { 887*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 888*7c478bd9Sstevel@tonic-gate return (_nderror); 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate /* 892*7c478bd9Sstevel@tonic-gate * Validate the address which was passed 893*7c478bd9Sstevel@tonic-gate * as the request. 894*7c478bd9Sstevel@tonic-gate */ 895*7c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)args->arg.nd_nbuf->buf; 896*7c478bd9Sstevel@tonic-gate 897*7c478bd9Sstevel@tonic-gate if ((args->arg.nd_nbuf->len != 898*7c478bd9Sstevel@tonic-gate sizeof (struct sockaddr_in6)) || 899*7c478bd9Sstevel@tonic-gate (sin6->sin6_family != AF_INET6)) { 900*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 901*7c478bd9Sstevel@tonic-gate return (_nderror); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate break; 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate /* 909*7c478bd9Sstevel@tonic-gate * 2. Most common scenario. This is the way we ship /etc/netconfig. 910*7c478bd9Sstevel@tonic-gate * Emphasis on improving performance in the "if" part. 911*7c478bd9Sstevel@tonic-gate */ 912*7c478bd9Sstevel@tonic-gate if (nconf->nc_nlookups == 0) { 913*7c478bd9Sstevel@tonic-gate struct hostent *he = NULL, *tmphe; 914*7c478bd9Sstevel@tonic-gate struct servent *se = NULL; 915*7c478bd9Sstevel@tonic-gate nss_XbyY_buf_t *ndbuf4host = 0; 916*7c478bd9Sstevel@tonic-gate nss_XbyY_buf_t *ndbuf4serv = 0; 917*7c478bd9Sstevel@tonic-gate char *proto = 918*7c478bd9Sstevel@tonic-gate (strcmp(nconf->nc_proto, NC_TCP) == 0) ? NC_TCP : NC_UDP; 919*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sa; 920*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 921*7c478bd9Sstevel@tonic-gate struct in_addr *addr4 = 0; 922*7c478bd9Sstevel@tonic-gate struct in6_addr v4mapbuf; 923*7c478bd9Sstevel@tonic-gate int h_errnop; 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate switch (args->op_t) { 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate case NSS_HOST: 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate he = DOOR_GETHOSTBYADDR_R(args->arg.nss.host.addr, 930*7c478bd9Sstevel@tonic-gate args->arg.nss.host.len, args->arg.nss.host.type, 931*7c478bd9Sstevel@tonic-gate res->nss.host.hent, args->arg.nss.host.buf, 932*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buflen, 933*7c478bd9Sstevel@tonic-gate res->nss.host.herrno_p); 934*7c478bd9Sstevel@tonic-gate if (he == 0) 935*7c478bd9Sstevel@tonic-gate _nderror = ND_NOHOST; 936*7c478bd9Sstevel@tonic-gate else 937*7c478bd9Sstevel@tonic-gate _nderror = ND_OK; 938*7c478bd9Sstevel@tonic-gate return (_nderror); 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate case NSS_HOST6: 942*7c478bd9Sstevel@tonic-gate he = DOOR_GETIPNODEBYADDR_R(args->arg.nss.host.addr, 943*7c478bd9Sstevel@tonic-gate args->arg.nss.host.len, args->arg.nss.host.type, 944*7c478bd9Sstevel@tonic-gate res->nss.host.hent, args->arg.nss.host.buf, 945*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buflen, 946*7c478bd9Sstevel@tonic-gate res->nss.host.herrno_p); 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate if (he == 0) 949*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 950*7c478bd9Sstevel@tonic-gate return (ND_OK); 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate case NSS_SERV: 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate se = _switch_getservbyport_r(args->arg.nss.serv.port, 956*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.proto, 957*7c478bd9Sstevel@tonic-gate res->nss.serv, args->arg.nss.serv.buf, 958*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.buflen); 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate if (se == 0) 961*7c478bd9Sstevel@tonic-gate _nderror = ND_NOSERV; 962*7c478bd9Sstevel@tonic-gate else 963*7c478bd9Sstevel@tonic-gate _nderror = ND_OK; 964*7c478bd9Sstevel@tonic-gate return (_nderror); 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate case NETDIR_BY: 967*7c478bd9Sstevel@tonic-gate case NETDIR_BY_NOSRV: 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate GETSERVBUF(ndbuf4serv); 970*7c478bd9Sstevel@tonic-gate if (ndbuf4serv == 0) { 971*7c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 972*7c478bd9Sstevel@tonic-gate return (_nderror); 973*7c478bd9Sstevel@tonic-gate } 974*7c478bd9Sstevel@tonic-gate sa = (struct sockaddr_in *)(args->arg.nd_nbuf->buf); 975*7c478bd9Sstevel@tonic-gate addr4 = (struct in_addr *)&(sa->sin_addr); 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate /* 978*7c478bd9Sstevel@tonic-gate * if NETDIR_BY_NOSRV or port == 0 skip the service 979*7c478bd9Sstevel@tonic-gate * lookup. 980*7c478bd9Sstevel@tonic-gate */ 981*7c478bd9Sstevel@tonic-gate if (args->op_t != NETDIR_BY_NOSRV && sa->sin_port != 0) { 982*7c478bd9Sstevel@tonic-gate se = _switch_getservbyport_r(sa->sin_port, proto, 983*7c478bd9Sstevel@tonic-gate ndbuf4serv->result, ndbuf4serv->buffer, 984*7c478bd9Sstevel@tonic-gate ndbuf4serv->buflen); 985*7c478bd9Sstevel@tonic-gate if (!se) { 986*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4serv); 987*7c478bd9Sstevel@tonic-gate /* 988*7c478bd9Sstevel@tonic-gate * We can live with this - i.e. the address 989*7c478bd9Sstevel@tonic-gate * does not 990*7c478bd9Sstevel@tonic-gate * belong to a well known service. The caller 991*7c478bd9Sstevel@tonic-gate * traditionally accepts a stringified port 992*7c478bd9Sstevel@tonic-gate * number 993*7c478bd9Sstevel@tonic-gate * as the service name. The state of se is used 994*7c478bd9Sstevel@tonic-gate * ahead to indicate the same. 995*7c478bd9Sstevel@tonic-gate * However, we do not tolerate this nonsense 996*7c478bd9Sstevel@tonic-gate * when we cannot get a host name. See below. 997*7c478bd9Sstevel@tonic-gate */ 998*7c478bd9Sstevel@tonic-gate } 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate GETHOSTBUF(ndbuf4host); 1002*7c478bd9Sstevel@tonic-gate if (ndbuf4host == 0) { 1003*7c478bd9Sstevel@tonic-gate if (ndbuf4serv) 1004*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4serv); 1005*7c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 1006*7c478bd9Sstevel@tonic-gate return (_nderror); 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate /* 1010*7c478bd9Sstevel@tonic-gate * Since we're going to search the ipnodes (v6) path first, 1011*7c478bd9Sstevel@tonic-gate * we need to treat the address as a v4mapped address. 1012*7c478bd9Sstevel@tonic-gate */ 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED(addr4, &v4mapbuf); 1015*7c478bd9Sstevel@tonic-gate if ((tmphe = DOOR_GETIPNODEBYADDR_R((char *)&v4mapbuf, 1016*7c478bd9Sstevel@tonic-gate 16, AF_INET6, ndbuf4host->result, 1017*7c478bd9Sstevel@tonic-gate ndbuf4host->buffer, 1018*7c478bd9Sstevel@tonic-gate ndbuf4host->buflen, &h_errnop)) != NULL) 1019*7c478bd9Sstevel@tonic-gate he = __mappedtov4(tmphe, &h_errnop); 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate if (!he) { 1022*7c478bd9Sstevel@tonic-gate /* Failover case, try hosts db for v4 address */ 1023*7c478bd9Sstevel@tonic-gate he = DOOR_GETHOSTBYADDR_R((char *) 1024*7c478bd9Sstevel@tonic-gate &(sa->sin_addr.s_addr), 4, 1025*7c478bd9Sstevel@tonic-gate sa->sin_family, ndbuf4host->result, 1026*7c478bd9Sstevel@tonic-gate ndbuf4host->buffer, ndbuf4host->buflen, 1027*7c478bd9Sstevel@tonic-gate &h_errnop); 1028*7c478bd9Sstevel@tonic-gate if (!he) { 1029*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4host); 1030*7c478bd9Sstevel@tonic-gate if (ndbuf4serv) 1031*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4serv); 1032*7c478bd9Sstevel@tonic-gate _nderror = __herrno2netdir(h_errnop); 1033*7c478bd9Sstevel@tonic-gate return (_nderror); 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate /* 1036*7c478bd9Sstevel@tonic-gate * Convert host names and service names into hostserv 1037*7c478bd9Sstevel@tonic-gate * pairs. malloc's will be done, freed using 1038*7c478bd9Sstevel@tonic-gate * netdir_free. 1039*7c478bd9Sstevel@tonic-gate */ 1040*7c478bd9Sstevel@tonic-gate h_errnop = hsents2ndhostservs(he, se, 1041*7c478bd9Sstevel@tonic-gate sa->sin_port, res->nd_hslist); 1042*7c478bd9Sstevel@tonic-gate } else { 1043*7c478bd9Sstevel@tonic-gate /* 1044*7c478bd9Sstevel@tonic-gate * Convert host names and service names into hostserv 1045*7c478bd9Sstevel@tonic-gate * pairs. malloc's will be done, freed using 1046*7c478bd9Sstevel@tonic-gate * netdir_free. 1047*7c478bd9Sstevel@tonic-gate */ 1048*7c478bd9Sstevel@tonic-gate h_errnop = hsents2ndhostservs(he, se, 1049*7c478bd9Sstevel@tonic-gate sa->sin_port, res->nd_hslist); 1050*7c478bd9Sstevel@tonic-gate freehostent(he); 1051*7c478bd9Sstevel@tonic-gate } 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4host); 1054*7c478bd9Sstevel@tonic-gate if (ndbuf4serv) 1055*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4serv); 1056*7c478bd9Sstevel@tonic-gate _nderror = __herrno2netdir(h_errnop); 1057*7c478bd9Sstevel@tonic-gate return (_nderror); 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate case NETDIR_BY6: 1060*7c478bd9Sstevel@tonic-gate case NETDIR_BY_NOSRV6: 1061*7c478bd9Sstevel@tonic-gate 1062*7c478bd9Sstevel@tonic-gate GETSERVBUF(ndbuf4serv); 1063*7c478bd9Sstevel@tonic-gate if (ndbuf4serv == 0) { 1064*7c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 1065*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 1066*7c478bd9Sstevel@tonic-gate } 1067*7c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)(args->arg.nd_nbuf->buf); 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate /* 1070*7c478bd9Sstevel@tonic-gate * if NETDIR_BY_NOSRV6 or port == 0 skip the service 1071*7c478bd9Sstevel@tonic-gate * lookup. 1072*7c478bd9Sstevel@tonic-gate */ 1073*7c478bd9Sstevel@tonic-gate if (args->op_t != NETDIR_BY_NOSRV6 && sin6->sin6_port == 0) { 1074*7c478bd9Sstevel@tonic-gate se = _switch_getservbyport_r(sin6->sin6_port, proto, 1075*7c478bd9Sstevel@tonic-gate ndbuf4serv->result, ndbuf4serv->buffer, 1076*7c478bd9Sstevel@tonic-gate ndbuf4serv->buflen); 1077*7c478bd9Sstevel@tonic-gate if (!se) { 1078*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4serv); 1079*7c478bd9Sstevel@tonic-gate /* 1080*7c478bd9Sstevel@tonic-gate * We can live with this - i.e. the address does 1081*7c478bd9Sstevel@tonic-gate * not * belong to a well known service. The 1082*7c478bd9Sstevel@tonic-gate * caller traditionally accepts a stringified 1083*7c478bd9Sstevel@tonic-gate * port number 1084*7c478bd9Sstevel@tonic-gate * as the service name. The state of se is used 1085*7c478bd9Sstevel@tonic-gate * ahead to indicate the same. 1086*7c478bd9Sstevel@tonic-gate * However, we do not tolerate this nonsense 1087*7c478bd9Sstevel@tonic-gate * when we cannot get a host name. See below. 1088*7c478bd9Sstevel@tonic-gate */ 1089*7c478bd9Sstevel@tonic-gate } 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate 1092*7c478bd9Sstevel@tonic-gate GETHOSTBUF(ndbuf4host); 1093*7c478bd9Sstevel@tonic-gate if (ndbuf4host == 0) { 1094*7c478bd9Sstevel@tonic-gate if (ndbuf4serv) 1095*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4serv); 1096*7c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 1097*7c478bd9Sstevel@tonic-gate return (_nderror); 1098*7c478bd9Sstevel@tonic-gate } 1099*7c478bd9Sstevel@tonic-gate he = DOOR_GETIPNODEBYADDR_R((char *)&(sin6->sin6_addr), 1100*7c478bd9Sstevel@tonic-gate 16, sin6->sin6_family, ndbuf4host->result, 1101*7c478bd9Sstevel@tonic-gate ndbuf4host->buffer, 1102*7c478bd9Sstevel@tonic-gate ndbuf4host->buflen, &h_errnop); 1103*7c478bd9Sstevel@tonic-gate if (!he) { 1104*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4host); 1105*7c478bd9Sstevel@tonic-gate if (ndbuf4serv) 1106*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4serv); 1107*7c478bd9Sstevel@tonic-gate _nderror = __herrno2netdir(h_errnop); 1108*7c478bd9Sstevel@tonic-gate return (_nderror); 1109*7c478bd9Sstevel@tonic-gate } 1110*7c478bd9Sstevel@tonic-gate /* 1111*7c478bd9Sstevel@tonic-gate * Convert host names and service names into hostserv 1112*7c478bd9Sstevel@tonic-gate * pairs. malloc's will be done, freed using netdir_free. 1113*7c478bd9Sstevel@tonic-gate */ 1114*7c478bd9Sstevel@tonic-gate h_errnop = hsents2ndhostservs(he, se, 1115*7c478bd9Sstevel@tonic-gate sin6->sin6_port, res->nd_hslist); 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4host); 1118*7c478bd9Sstevel@tonic-gate if (ndbuf4serv) 1119*7c478bd9Sstevel@tonic-gate NSS_XbyY_FREE(&ndbuf4serv); 1120*7c478bd9Sstevel@tonic-gate _nderror = __herrno2netdir(h_errnop); 1121*7c478bd9Sstevel@tonic-gate return (_nderror); 1122*7c478bd9Sstevel@tonic-gate 1123*7c478bd9Sstevel@tonic-gate default: 1124*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 1125*7c478bd9Sstevel@tonic-gate return (_nderror); /* should never happen */ 1126*7c478bd9Sstevel@tonic-gate } 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate } 1129*7c478bd9Sstevel@tonic-gate /* 1130*7c478bd9Sstevel@tonic-gate * 3. We come this far only if nametoaddr libs are specified for 1131*7c478bd9Sstevel@tonic-gate * inet transports and we are called by gethost/servbyname only. 1132*7c478bd9Sstevel@tonic-gate */ 1133*7c478bd9Sstevel@tonic-gate switch (args->op_t) { 1134*7c478bd9Sstevel@tonic-gate struct netbuf nbuf; 1135*7c478bd9Sstevel@tonic-gate struct nd_hostservlist *addrs; 1136*7c478bd9Sstevel@tonic-gate struct sockaddr_in sa; 1137*7c478bd9Sstevel@tonic-gate 1138*7c478bd9Sstevel@tonic-gate case NSS_HOST: 1139*7c478bd9Sstevel@tonic-gate 1140*7c478bd9Sstevel@tonic-gate sa.sin_addr.s_addr = *(uint32_t *)args->arg.nss.host.addr; 1141*7c478bd9Sstevel@tonic-gate sa.sin_family = AF_INET; 1142*7c478bd9Sstevel@tonic-gate /* Hopefully, third-parties get this optimization */ 1143*7c478bd9Sstevel@tonic-gate sa.sin_port = 0; 1144*7c478bd9Sstevel@tonic-gate nbuf.buf = (char *)&sa; 1145*7c478bd9Sstevel@tonic-gate nbuf.len = nbuf.maxlen = sizeof (sa); 1146*7c478bd9Sstevel@tonic-gate if ((_nderror = __classic_netdir_getbyaddr(nconf, 1147*7c478bd9Sstevel@tonic-gate &addrs, &nbuf)) != 0) { 1148*7c478bd9Sstevel@tonic-gate *(res->nss.host.herrno_p) = nd2herrno(_nderror); 1149*7c478bd9Sstevel@tonic-gate return (_nderror); 1150*7c478bd9Sstevel@tonic-gate } 1151*7c478bd9Sstevel@tonic-gate /* 1152*7c478bd9Sstevel@tonic-gate * convert the host-serv pairs into h_aliases and hent. 1153*7c478bd9Sstevel@tonic-gate */ 1154*7c478bd9Sstevel@tonic-gate _nderror = ndhostserv2hent(&nbuf, addrs, res->nss.host.hent, 1155*7c478bd9Sstevel@tonic-gate args->arg.nss.host.buf, args->arg.nss.host.buflen); 1156*7c478bd9Sstevel@tonic-gate if (_nderror != ND_OK) 1157*7c478bd9Sstevel@tonic-gate *(res->nss.host.herrno_p) = nd2herrno(_nderror); 1158*7c478bd9Sstevel@tonic-gate netdir_free((char *)addrs, ND_HOSTSERVLIST); 1159*7c478bd9Sstevel@tonic-gate return (_nderror); 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate case NSS_SERV: 1162*7c478bd9Sstevel@tonic-gate 1163*7c478bd9Sstevel@tonic-gate if (args->arg.nss.serv.proto == NULL) { 1164*7c478bd9Sstevel@tonic-gate /* 1165*7c478bd9Sstevel@tonic-gate * A similar HACK showed up in Solaris 2.3. 1166*7c478bd9Sstevel@tonic-gate * The caller wild-carded proto -- i.e. will 1167*7c478bd9Sstevel@tonic-gate * accept a match on tcp or udp for the port 1168*7c478bd9Sstevel@tonic-gate * number. Since we have no hope of getting 1169*7c478bd9Sstevel@tonic-gate * directly to a name service switch backend 1170*7c478bd9Sstevel@tonic-gate * from here that understands this semantics, 1171*7c478bd9Sstevel@tonic-gate * we try calling the netdir interfaces first 1172*7c478bd9Sstevel@tonic-gate * with "tcp" and then "udp". 1173*7c478bd9Sstevel@tonic-gate */ 1174*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.proto = "tcp"; 1175*7c478bd9Sstevel@tonic-gate _nderror = _get_hostserv_inetnetdir_byaddr(nconf, args, 1176*7c478bd9Sstevel@tonic-gate res); 1177*7c478bd9Sstevel@tonic-gate if (_nderror != ND_OK) { 1178*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.proto = "udp"; 1179*7c478bd9Sstevel@tonic-gate _nderror = 1180*7c478bd9Sstevel@tonic-gate _get_hostserv_inetnetdir_byaddr(nconf, 1181*7c478bd9Sstevel@tonic-gate args, res); 1182*7c478bd9Sstevel@tonic-gate } 1183*7c478bd9Sstevel@tonic-gate return (_nderror); 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate 1186*7c478bd9Sstevel@tonic-gate /* 1187*7c478bd9Sstevel@tonic-gate * Third-party nametoaddr_libs should be optimized for 1188*7c478bd9Sstevel@tonic-gate * this case. It also gives a special semantics twist to 1189*7c478bd9Sstevel@tonic-gate * netdir_getbyaddr. Only for the INADDR_ANY case, it gives 1190*7c478bd9Sstevel@tonic-gate * higher priority to service lookups (over host lookups). 1191*7c478bd9Sstevel@tonic-gate * If service lookup fails, the backend returns ND_NOSERV to 1192*7c478bd9Sstevel@tonic-gate * facilitate lookup in the "next" naming service. 1193*7c478bd9Sstevel@tonic-gate * BugId: 1075403. 1194*7c478bd9Sstevel@tonic-gate */ 1195*7c478bd9Sstevel@tonic-gate sa.sin_addr.s_addr = INADDR_ANY; 1196*7c478bd9Sstevel@tonic-gate sa.sin_family = AF_INET; 1197*7c478bd9Sstevel@tonic-gate sa.sin_port = (ushort_t)args->arg.nss.serv.port; 1198*7c478bd9Sstevel@tonic-gate sa.sin_zero[0] = '\0'; 1199*7c478bd9Sstevel@tonic-gate nbuf.buf = (char *)&sa; 1200*7c478bd9Sstevel@tonic-gate nbuf.len = nbuf.maxlen = sizeof (sa); 1201*7c478bd9Sstevel@tonic-gate if ((_nderror = __classic_netdir_getbyaddr(nconf, 1202*7c478bd9Sstevel@tonic-gate &addrs, &nbuf)) != ND_OK) { 1203*7c478bd9Sstevel@tonic-gate return (_nderror); 1204*7c478bd9Sstevel@tonic-gate } 1205*7c478bd9Sstevel@tonic-gate /* 1206*7c478bd9Sstevel@tonic-gate * convert the host-serv pairs into s_aliases and servent. 1207*7c478bd9Sstevel@tonic-gate */ 1208*7c478bd9Sstevel@tonic-gate _nderror = ndhostserv2srent(args->arg.nss.serv.port, 1209*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.proto, addrs, res->nss.serv, 1210*7c478bd9Sstevel@tonic-gate args->arg.nss.serv.buf, args->arg.nss.serv.buflen); 1211*7c478bd9Sstevel@tonic-gate netdir_free((char *)addrs, ND_HOSTSERVLIST); 1212*7c478bd9Sstevel@tonic-gate return (_nderror); 1213*7c478bd9Sstevel@tonic-gate 1214*7c478bd9Sstevel@tonic-gate default: 1215*7c478bd9Sstevel@tonic-gate _nderror = ND_BADARG; 1216*7c478bd9Sstevel@tonic-gate return (_nderror); /* should never happen */ 1217*7c478bd9Sstevel@tonic-gate } 1218*7c478bd9Sstevel@tonic-gate } 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate /* 1221*7c478bd9Sstevel@tonic-gate * Part II: Name Service Switch interfacing routines. 1222*7c478bd9Sstevel@tonic-gate */ 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root_hosts); 1225*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root_ipnodes); 1226*7c478bd9Sstevel@tonic-gate static DEFINE_NSS_DB_ROOT(db_root_services); 1227*7c478bd9Sstevel@tonic-gate 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate /* 1230*7c478bd9Sstevel@tonic-gate * There is a copy of __nss2herrno() in nsswitch/files/gethostent.c. 1231*7c478bd9Sstevel@tonic-gate * It is there because /etc/lib/nss_files.so.1 cannot call 1232*7c478bd9Sstevel@tonic-gate * routines in libnsl. Care should be taken to keep the two copies 1233*7c478bd9Sstevel@tonic-gate * in sync. 1234*7c478bd9Sstevel@tonic-gate */ 1235*7c478bd9Sstevel@tonic-gate int 1236*7c478bd9Sstevel@tonic-gate __nss2herrno(nss_status_t nsstat) 1237*7c478bd9Sstevel@tonic-gate { 1238*7c478bd9Sstevel@tonic-gate switch (nsstat) { 1239*7c478bd9Sstevel@tonic-gate case NSS_SUCCESS: 1240*7c478bd9Sstevel@tonic-gate /* no macro-defined success code for h_errno */ 1241*7c478bd9Sstevel@tonic-gate return (0); 1242*7c478bd9Sstevel@tonic-gate case NSS_NOTFOUND: 1243*7c478bd9Sstevel@tonic-gate return (HOST_NOT_FOUND); 1244*7c478bd9Sstevel@tonic-gate case NSS_TRYAGAIN: 1245*7c478bd9Sstevel@tonic-gate return (TRY_AGAIN); 1246*7c478bd9Sstevel@tonic-gate case NSS_UNAVAIL: 1247*7c478bd9Sstevel@tonic-gate return (NO_RECOVERY); 1248*7c478bd9Sstevel@tonic-gate } 1249*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1250*7c478bd9Sstevel@tonic-gate return (0); /* keep gcc happy */ 1251*7c478bd9Sstevel@tonic-gate } 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate nss_status_t 1254*7c478bd9Sstevel@tonic-gate _herrno2nss(int h_errno) 1255*7c478bd9Sstevel@tonic-gate { 1256*7c478bd9Sstevel@tonic-gate switch (h_errno) { 1257*7c478bd9Sstevel@tonic-gate case 0: 1258*7c478bd9Sstevel@tonic-gate return (NSS_SUCCESS); 1259*7c478bd9Sstevel@tonic-gate case TRY_AGAIN: 1260*7c478bd9Sstevel@tonic-gate return (NSS_TRYAGAIN); 1261*7c478bd9Sstevel@tonic-gate case NO_RECOVERY: 1262*7c478bd9Sstevel@tonic-gate case NETDB_INTERNAL: 1263*7c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL); 1264*7c478bd9Sstevel@tonic-gate case HOST_NOT_FOUND: 1265*7c478bd9Sstevel@tonic-gate case NO_DATA: 1266*7c478bd9Sstevel@tonic-gate default: 1267*7c478bd9Sstevel@tonic-gate return (NSS_NOTFOUND); 1268*7c478bd9Sstevel@tonic-gate } 1269*7c478bd9Sstevel@tonic-gate } 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate static int 1272*7c478bd9Sstevel@tonic-gate __herrno2netdir(int h_errnop) 1273*7c478bd9Sstevel@tonic-gate { 1274*7c478bd9Sstevel@tonic-gate switch (h_errnop) { 1275*7c478bd9Sstevel@tonic-gate case 0: 1276*7c478bd9Sstevel@tonic-gate return (ND_OK); 1277*7c478bd9Sstevel@tonic-gate case HOST_NOT_FOUND: 1278*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 1279*7c478bd9Sstevel@tonic-gate case TRY_AGAIN: 1280*7c478bd9Sstevel@tonic-gate return (ND_TRY_AGAIN); 1281*7c478bd9Sstevel@tonic-gate case NO_RECOVERY: 1282*7c478bd9Sstevel@tonic-gate case NETDB_INTERNAL: 1283*7c478bd9Sstevel@tonic-gate return (ND_NO_RECOVERY); 1284*7c478bd9Sstevel@tonic-gate case NO_DATA: 1285*7c478bd9Sstevel@tonic-gate return (ND_NO_DATA); 1286*7c478bd9Sstevel@tonic-gate default: 1287*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 1288*7c478bd9Sstevel@tonic-gate } 1289*7c478bd9Sstevel@tonic-gate } 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate /* 1292*7c478bd9Sstevel@tonic-gate * The _switch_getXXbyYY_r() routines should be static. They used to 1293*7c478bd9Sstevel@tonic-gate * be exported in SunOS 5.3, and in fact publicised as work-around 1294*7c478bd9Sstevel@tonic-gate * interfaces for getting CNAME/aliases, and therefore, we preserve 1295*7c478bd9Sstevel@tonic-gate * their signatures here. Just in case. 1296*7c478bd9Sstevel@tonic-gate */ 1297*7c478bd9Sstevel@tonic-gate 1298*7c478bd9Sstevel@tonic-gate struct hostent * 1299*7c478bd9Sstevel@tonic-gate _switch_gethostbyname_r(const char *name, struct hostent *result, char *buffer, 1300*7c478bd9Sstevel@tonic-gate int buflen, int *h_errnop) 1301*7c478bd9Sstevel@tonic-gate { 1302*7c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 1303*7c478bd9Sstevel@tonic-gate nss_status_t res; 1304*7c478bd9Sstevel@tonic-gate 1305*7c478bd9Sstevel@tonic-gate trace2(TR__switch_gethostbyname_r, 0, buflen); 1306*7c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2hostent); 1307*7c478bd9Sstevel@tonic-gate arg.key.name = name; 1308*7c478bd9Sstevel@tonic-gate arg.stayopen = 0; 1309*7c478bd9Sstevel@tonic-gate res = nss_search(&db_root_hosts, _nss_initf_hosts, 1310*7c478bd9Sstevel@tonic-gate NSS_DBOP_HOSTS_BYNAME, &arg); 1311*7c478bd9Sstevel@tonic-gate arg.status = res; 1312*7c478bd9Sstevel@tonic-gate *h_errnop = arg.h_errno; 1313*7c478bd9Sstevel@tonic-gate if (arg.returnval != NULL) 1314*7c478bd9Sstevel@tonic-gate order_haddrlist_af(result->h_addrtype, result->h_addr_list); 1315*7c478bd9Sstevel@tonic-gate trace2(TR__switch_gethostbyname_r, 1, buflen); 1316*7c478bd9Sstevel@tonic-gate return ((struct hostent *)NSS_XbyY_FINI(&arg)); 1317*7c478bd9Sstevel@tonic-gate } 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate struct hostent * 1320*7c478bd9Sstevel@tonic-gate _switch_getipnodebyname_r(const char *name, struct hostent *result, 1321*7c478bd9Sstevel@tonic-gate char *buffer, int buflen, int af_family, int flags, int *h_errnop) 1322*7c478bd9Sstevel@tonic-gate { 1323*7c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 1324*7c478bd9Sstevel@tonic-gate nss_status_t res; 1325*7c478bd9Sstevel@tonic-gate 1326*7c478bd9Sstevel@tonic-gate trace2(TR__switch_getipnodebyname_r, 0, buflen); 1327*7c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2hostent6); 1328*7c478bd9Sstevel@tonic-gate arg.key.ipnode.name = name; 1329*7c478bd9Sstevel@tonic-gate arg.key.ipnode.af_family = af_family; 1330*7c478bd9Sstevel@tonic-gate arg.key.ipnode.flags = flags; 1331*7c478bd9Sstevel@tonic-gate arg.stayopen = 0; 1332*7c478bd9Sstevel@tonic-gate res = nss_search(&db_root_ipnodes, _nss_initf_ipnodes, 1333*7c478bd9Sstevel@tonic-gate NSS_DBOP_IPNODES_BYNAME, &arg); 1334*7c478bd9Sstevel@tonic-gate arg.status = res; 1335*7c478bd9Sstevel@tonic-gate *h_errnop = arg.h_errno; 1336*7c478bd9Sstevel@tonic-gate if (arg.returnval != NULL) 1337*7c478bd9Sstevel@tonic-gate order_haddrlist_af(result->h_addrtype, result->h_addr_list); 1338*7c478bd9Sstevel@tonic-gate trace2(TR__switch_getipnodebyname_r, 1, buflen); 1339*7c478bd9Sstevel@tonic-gate return ((struct hostent *)NSS_XbyY_FINI(&arg)); 1340*7c478bd9Sstevel@tonic-gate } 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate struct hostent * 1343*7c478bd9Sstevel@tonic-gate _switch_gethostbyaddr_r(const char *addr, int len, int type, 1344*7c478bd9Sstevel@tonic-gate struct hostent *result, char *buffer, int buflen, int *h_errnop) 1345*7c478bd9Sstevel@tonic-gate { 1346*7c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 1347*7c478bd9Sstevel@tonic-gate nss_status_t res; 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate trace3(TR__switch_gethostbyaddr_r, 0, len, buflen); 1350*7c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2hostent); 1351*7c478bd9Sstevel@tonic-gate arg.key.hostaddr.addr = addr; 1352*7c478bd9Sstevel@tonic-gate arg.key.hostaddr.len = len; 1353*7c478bd9Sstevel@tonic-gate arg.key.hostaddr.type = type; 1354*7c478bd9Sstevel@tonic-gate arg.stayopen = 0; 1355*7c478bd9Sstevel@tonic-gate res = nss_search(&db_root_hosts, _nss_initf_hosts, 1356*7c478bd9Sstevel@tonic-gate NSS_DBOP_HOSTS_BYADDR, &arg); 1357*7c478bd9Sstevel@tonic-gate arg.status = res; 1358*7c478bd9Sstevel@tonic-gate *h_errnop = arg.h_errno; 1359*7c478bd9Sstevel@tonic-gate trace3(TR__switch_gethostbyaddr_r, 1, len, buflen); 1360*7c478bd9Sstevel@tonic-gate return (struct hostent *)NSS_XbyY_FINI(&arg); 1361*7c478bd9Sstevel@tonic-gate } 1362*7c478bd9Sstevel@tonic-gate 1363*7c478bd9Sstevel@tonic-gate struct hostent * 1364*7c478bd9Sstevel@tonic-gate _switch_getipnodebyaddr_r(const char *addr, int len, int type, 1365*7c478bd9Sstevel@tonic-gate struct hostent *result, char *buffer, int buflen, int *h_errnop) 1366*7c478bd9Sstevel@tonic-gate { 1367*7c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 1368*7c478bd9Sstevel@tonic-gate nss_status_t res; 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate trace3(TR__switch_getipnodebyaddr_r, 0, len, buflen); 1371*7c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2hostent6); 1372*7c478bd9Sstevel@tonic-gate arg.key.hostaddr.addr = addr; 1373*7c478bd9Sstevel@tonic-gate arg.key.hostaddr.len = len; 1374*7c478bd9Sstevel@tonic-gate arg.key.hostaddr.type = type; 1375*7c478bd9Sstevel@tonic-gate arg.stayopen = 0; 1376*7c478bd9Sstevel@tonic-gate res = nss_search(&db_root_ipnodes, _nss_initf_ipnodes, 1377*7c478bd9Sstevel@tonic-gate NSS_DBOP_IPNODES_BYADDR, &arg); 1378*7c478bd9Sstevel@tonic-gate arg.status = res; 1379*7c478bd9Sstevel@tonic-gate *h_errnop = arg.h_errno; 1380*7c478bd9Sstevel@tonic-gate trace3(TR__switch_getipnodebyaddr_r, 1, len, buflen); 1381*7c478bd9Sstevel@tonic-gate return (struct hostent *)NSS_XbyY_FINI(&arg); 1382*7c478bd9Sstevel@tonic-gate } 1383*7c478bd9Sstevel@tonic-gate 1384*7c478bd9Sstevel@tonic-gate static void 1385*7c478bd9Sstevel@tonic-gate _nss_initf_services(nss_db_params_t *p) 1386*7c478bd9Sstevel@tonic-gate { 1387*7c478bd9Sstevel@tonic-gate /* === need tracepoints */ 1388*7c478bd9Sstevel@tonic-gate p->name = NSS_DBNAM_SERVICES; 1389*7c478bd9Sstevel@tonic-gate p->default_config = NSS_DEFCONF_SERVICES; 1390*7c478bd9Sstevel@tonic-gate } 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate struct servent * 1393*7c478bd9Sstevel@tonic-gate _switch_getservbyname_r(const char *name, const char *proto, 1394*7c478bd9Sstevel@tonic-gate struct servent *result, char *buffer, int buflen) 1395*7c478bd9Sstevel@tonic-gate { 1396*7c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 1397*7c478bd9Sstevel@tonic-gate nss_status_t res; 1398*7c478bd9Sstevel@tonic-gate 1399*7c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2servent); 1400*7c478bd9Sstevel@tonic-gate arg.key.serv.serv.name = name; 1401*7c478bd9Sstevel@tonic-gate arg.key.serv.proto = proto; 1402*7c478bd9Sstevel@tonic-gate arg.stayopen = 0; 1403*7c478bd9Sstevel@tonic-gate res = nss_search(&db_root_services, _nss_initf_services, 1404*7c478bd9Sstevel@tonic-gate NSS_DBOP_SERVICES_BYNAME, &arg); 1405*7c478bd9Sstevel@tonic-gate arg.status = res; 1406*7c478bd9Sstevel@tonic-gate return ((struct servent *)NSS_XbyY_FINI(&arg)); 1407*7c478bd9Sstevel@tonic-gate } 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate struct servent * 1410*7c478bd9Sstevel@tonic-gate _switch_getservbyport_r(int port, const char *proto, struct servent *result, 1411*7c478bd9Sstevel@tonic-gate char *buffer, int buflen) 1412*7c478bd9Sstevel@tonic-gate { 1413*7c478bd9Sstevel@tonic-gate nss_XbyY_args_t arg; 1414*7c478bd9Sstevel@tonic-gate nss_status_t res; 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate NSS_XbyY_INIT(&arg, result, buffer, buflen, str2servent); 1417*7c478bd9Sstevel@tonic-gate arg.key.serv.serv.port = port; 1418*7c478bd9Sstevel@tonic-gate arg.key.serv.proto = proto; 1419*7c478bd9Sstevel@tonic-gate arg.stayopen = 0; 1420*7c478bd9Sstevel@tonic-gate res = nss_search(&db_root_services, _nss_initf_services, 1421*7c478bd9Sstevel@tonic-gate NSS_DBOP_SERVICES_BYPORT, &arg); 1422*7c478bd9Sstevel@tonic-gate arg.status = res; 1423*7c478bd9Sstevel@tonic-gate return ((struct servent *)NSS_XbyY_FINI(&arg)); 1424*7c478bd9Sstevel@tonic-gate } 1425*7c478bd9Sstevel@tonic-gate 1426*7c478bd9Sstevel@tonic-gate 1427*7c478bd9Sstevel@tonic-gate /* 1428*7c478bd9Sstevel@tonic-gate * Return values: 0 = success, 1 = parse error, 2 = erange ... 1429*7c478bd9Sstevel@tonic-gate * The structure pointer passed in is a structure in the caller's space 1430*7c478bd9Sstevel@tonic-gate * wherein the field pointers would be set to areas in the buffer if 1431*7c478bd9Sstevel@tonic-gate * need be. instring and buffer should be separate areas. 1432*7c478bd9Sstevel@tonic-gate * 1433*7c478bd9Sstevel@tonic-gate * Defined here because we need it and we (libnsl) cannot have a dependency 1434*7c478bd9Sstevel@tonic-gate * on libsocket (however, libsocket always depends on libnsl). 1435*7c478bd9Sstevel@tonic-gate */ 1436*7c478bd9Sstevel@tonic-gate int 1437*7c478bd9Sstevel@tonic-gate str2servent(const char *instr, int lenstr, void *ent, char *buffer, int buflen) 1438*7c478bd9Sstevel@tonic-gate { 1439*7c478bd9Sstevel@tonic-gate struct servent *serv = (struct servent *)ent; 1440*7c478bd9Sstevel@tonic-gate const char *p, *fieldstart, *limit, *namestart; 1441*7c478bd9Sstevel@tonic-gate ssize_t fieldlen, namelen = 0; 1442*7c478bd9Sstevel@tonic-gate char numbuf[12]; 1443*7c478bd9Sstevel@tonic-gate char *numend; 1444*7c478bd9Sstevel@tonic-gate 1445*7c478bd9Sstevel@tonic-gate if ((instr >= buffer && (buffer + buflen) > instr) || 1446*7c478bd9Sstevel@tonic-gate (buffer >= instr && (instr + lenstr) > buffer)) { 1447*7c478bd9Sstevel@tonic-gate return (NSS_STR_PARSE_PARSE); 1448*7c478bd9Sstevel@tonic-gate } 1449*7c478bd9Sstevel@tonic-gate 1450*7c478bd9Sstevel@tonic-gate p = instr; 1451*7c478bd9Sstevel@tonic-gate limit = p + lenstr; 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate while (p < limit && isspace(*p)) { 1454*7c478bd9Sstevel@tonic-gate p++; 1455*7c478bd9Sstevel@tonic-gate } 1456*7c478bd9Sstevel@tonic-gate namestart = p; 1457*7c478bd9Sstevel@tonic-gate while (p < limit && !isspace(*p)) { 1458*7c478bd9Sstevel@tonic-gate p++; /* Skip over the canonical name */ 1459*7c478bd9Sstevel@tonic-gate } 1460*7c478bd9Sstevel@tonic-gate namelen = p - namestart; 1461*7c478bd9Sstevel@tonic-gate 1462*7c478bd9Sstevel@tonic-gate if (buflen <= namelen) { /* not enough buffer */ 1463*7c478bd9Sstevel@tonic-gate return (NSS_STR_PARSE_ERANGE); 1464*7c478bd9Sstevel@tonic-gate } 1465*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer, namestart, namelen); 1466*7c478bd9Sstevel@tonic-gate buffer[namelen] = '\0'; 1467*7c478bd9Sstevel@tonic-gate serv->s_name = buffer; 1468*7c478bd9Sstevel@tonic-gate 1469*7c478bd9Sstevel@tonic-gate while (p < limit && isspace(*p)) { 1470*7c478bd9Sstevel@tonic-gate p++; 1471*7c478bd9Sstevel@tonic-gate } 1472*7c478bd9Sstevel@tonic-gate 1473*7c478bd9Sstevel@tonic-gate fieldstart = p; 1474*7c478bd9Sstevel@tonic-gate do { 1475*7c478bd9Sstevel@tonic-gate if (p > limit || isspace(*p)) { 1476*7c478bd9Sstevel@tonic-gate /* Syntax error -- no port/proto */ 1477*7c478bd9Sstevel@tonic-gate return (NSS_STR_PARSE_PARSE); 1478*7c478bd9Sstevel@tonic-gate } 1479*7c478bd9Sstevel@tonic-gate } 1480*7c478bd9Sstevel@tonic-gate while (*p++ != '/'); 1481*7c478bd9Sstevel@tonic-gate fieldlen = p - fieldstart - 1; 1482*7c478bd9Sstevel@tonic-gate if (fieldlen == 0 || fieldlen >= sizeof (numbuf)) { 1483*7c478bd9Sstevel@tonic-gate /* Syntax error -- supposed number is empty or too long */ 1484*7c478bd9Sstevel@tonic-gate return (NSS_STR_PARSE_PARSE); 1485*7c478bd9Sstevel@tonic-gate } 1486*7c478bd9Sstevel@tonic-gate (void) memcpy(numbuf, fieldstart, fieldlen); 1487*7c478bd9Sstevel@tonic-gate numbuf[fieldlen] = '\0'; 1488*7c478bd9Sstevel@tonic-gate serv->s_port = htons((int)strtol(numbuf, &numend, 10)); 1489*7c478bd9Sstevel@tonic-gate if (*numend != '\0') { 1490*7c478bd9Sstevel@tonic-gate /* Syntax error -- port number isn't a number */ 1491*7c478bd9Sstevel@tonic-gate return (NSS_STR_PARSE_PARSE); 1492*7c478bd9Sstevel@tonic-gate } 1493*7c478bd9Sstevel@tonic-gate 1494*7c478bd9Sstevel@tonic-gate fieldstart = p; 1495*7c478bd9Sstevel@tonic-gate while (p < limit && !isspace(*p)) { 1496*7c478bd9Sstevel@tonic-gate p++; /* Scan the protocol name */ 1497*7c478bd9Sstevel@tonic-gate } 1498*7c478bd9Sstevel@tonic-gate fieldlen = p - fieldstart + 1; /* Include '\0' this time */ 1499*7c478bd9Sstevel@tonic-gate if (fieldlen > buflen - namelen - 1) { 1500*7c478bd9Sstevel@tonic-gate return (NSS_STR_PARSE_ERANGE); 1501*7c478bd9Sstevel@tonic-gate } 1502*7c478bd9Sstevel@tonic-gate serv->s_proto = buffer + namelen + 1; 1503*7c478bd9Sstevel@tonic-gate (void) memcpy(serv->s_proto, fieldstart, fieldlen - 1); 1504*7c478bd9Sstevel@tonic-gate serv->s_proto[fieldlen - 1] = '\0'; 1505*7c478bd9Sstevel@tonic-gate 1506*7c478bd9Sstevel@tonic-gate while (p < limit && isspace(*p)) { 1507*7c478bd9Sstevel@tonic-gate p++; 1508*7c478bd9Sstevel@tonic-gate } 1509*7c478bd9Sstevel@tonic-gate /* 1510*7c478bd9Sstevel@tonic-gate * Although nss_files_XY_all calls us with # stripped, 1511*7c478bd9Sstevel@tonic-gate * we should be able to deal with it here in order to 1512*7c478bd9Sstevel@tonic-gate * be more useful. 1513*7c478bd9Sstevel@tonic-gate */ 1514*7c478bd9Sstevel@tonic-gate if (p >= limit || *p == '#') { /* no aliases, no problem */ 1515*7c478bd9Sstevel@tonic-gate char **ptr; 1516*7c478bd9Sstevel@tonic-gate 1517*7c478bd9Sstevel@tonic-gate ptr = (char **)ROUND_UP(buffer + namelen + 1 + fieldlen, 1518*7c478bd9Sstevel@tonic-gate sizeof (char *)); 1519*7c478bd9Sstevel@tonic-gate if ((char *)ptr >= buffer + buflen) { 1520*7c478bd9Sstevel@tonic-gate /* hope they don't try to peek in */ 1521*7c478bd9Sstevel@tonic-gate serv->s_aliases = 0; 1522*7c478bd9Sstevel@tonic-gate return (NSS_STR_PARSE_ERANGE); 1523*7c478bd9Sstevel@tonic-gate } else { 1524*7c478bd9Sstevel@tonic-gate *ptr = 0; 1525*7c478bd9Sstevel@tonic-gate serv->s_aliases = ptr; 1526*7c478bd9Sstevel@tonic-gate return (NSS_STR_PARSE_SUCCESS); 1527*7c478bd9Sstevel@tonic-gate } 1528*7c478bd9Sstevel@tonic-gate } 1529*7c478bd9Sstevel@tonic-gate serv->s_aliases = _nss_netdb_aliases(p, (int)(lenstr - (p - instr)), 1530*7c478bd9Sstevel@tonic-gate buffer + namelen + 1 + fieldlen, 1531*7c478bd9Sstevel@tonic-gate (int)(buflen - namelen - 1 - fieldlen)); 1532*7c478bd9Sstevel@tonic-gate return (NSS_STR_PARSE_SUCCESS); 1533*7c478bd9Sstevel@tonic-gate } 1534*7c478bd9Sstevel@tonic-gate 1535*7c478bd9Sstevel@tonic-gate /* 1536*7c478bd9Sstevel@tonic-gate * Part III: All `n sundry routines that are useful only in this 1537*7c478bd9Sstevel@tonic-gate * module. In the interest of keeping this source file shorter, 1538*7c478bd9Sstevel@tonic-gate * we would create them a new module only if the linker allowed 1539*7c478bd9Sstevel@tonic-gate * "library-static" functions. 1540*7c478bd9Sstevel@tonic-gate * 1541*7c478bd9Sstevel@tonic-gate * Routines to order addresses based on local interfaces and netmasks, 1542*7c478bd9Sstevel@tonic-gate * to get and check reserved ports, and to get broadcast nets. 1543*7c478bd9Sstevel@tonic-gate */ 1544*7c478bd9Sstevel@tonic-gate 1545*7c478bd9Sstevel@tonic-gate union __v4v6addr { 1546*7c478bd9Sstevel@tonic-gate struct in6_addr in6; 1547*7c478bd9Sstevel@tonic-gate struct in_addr in4; 1548*7c478bd9Sstevel@tonic-gate }; 1549*7c478bd9Sstevel@tonic-gate 1550*7c478bd9Sstevel@tonic-gate struct __ifaddr { 1551*7c478bd9Sstevel@tonic-gate sa_family_t af; 1552*7c478bd9Sstevel@tonic-gate union __v4v6addr addr; 1553*7c478bd9Sstevel@tonic-gate union __v4v6addr mask; 1554*7c478bd9Sstevel@tonic-gate }; 1555*7c478bd9Sstevel@tonic-gate 1556*7c478bd9Sstevel@tonic-gate struct ifinfo { 1557*7c478bd9Sstevel@tonic-gate int count; 1558*7c478bd9Sstevel@tonic-gate struct __ifaddr *addresses; 1559*7c478bd9Sstevel@tonic-gate }; 1560*7c478bd9Sstevel@tonic-gate 1561*7c478bd9Sstevel@tonic-gate typedef enum {ADDR_ONLINK = 0, ADDR_OFFLINK} addr_class_t; 1562*7c478bd9Sstevel@tonic-gate #define ADDR_NUMCLASSES 2 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate typedef enum {IF_ADDR, IF_MASK} __ifaddr_type; 1565*7c478bd9Sstevel@tonic-gate static int __inet_ifassign(sa_family_t, struct __ifaddr *, __ifaddr_type, 1566*7c478bd9Sstevel@tonic-gate void *); 1567*7c478bd9Sstevel@tonic-gate int __inet_address_is_local_af(void *, sa_family_t, void *); 1568*7c478bd9Sstevel@tonic-gate 1569*7c478bd9Sstevel@tonic-gate #define ifaf(index) (localinfo->addresses[index].af) 1570*7c478bd9Sstevel@tonic-gate #define ifaddr4(index) (localinfo->addresses[index].addr.in4) 1571*7c478bd9Sstevel@tonic-gate #define ifaddr6(index) (localinfo->addresses[index].addr.in6) 1572*7c478bd9Sstevel@tonic-gate #define ifmask4(index) (localinfo->addresses[index].mask.in4) 1573*7c478bd9Sstevel@tonic-gate #define ifmask6(index) (localinfo->addresses[index].mask.in6) 1574*7c478bd9Sstevel@tonic-gate #define ifinfosize(n) (sizeof (struct ifinfo) + (n)*sizeof (struct __ifaddr)) 1575*7c478bd9Sstevel@tonic-gate 1576*7c478bd9Sstevel@tonic-gate #define lifraddrp(lifr) ((lifr.lifr_addr.ss_family == AF_INET6) ? \ 1577*7c478bd9Sstevel@tonic-gate (void *)&((struct sockaddr_in6 *)&lifr.lifr_addr)->sin6_addr : \ 1578*7c478bd9Sstevel@tonic-gate (void *)&((struct sockaddr_in *)&lifr.lifr_addr)->sin_addr) 1579*7c478bd9Sstevel@tonic-gate 1580*7c478bd9Sstevel@tonic-gate #define ifassign(lifr, index, type) \ 1581*7c478bd9Sstevel@tonic-gate __inet_ifassign(lifr.lifr_addr.ss_family, \ 1582*7c478bd9Sstevel@tonic-gate &localinfo->addresses[index], type, \ 1583*7c478bd9Sstevel@tonic-gate lifraddrp(lifr)) 1584*7c478bd9Sstevel@tonic-gate 1585*7c478bd9Sstevel@tonic-gate /* 1586*7c478bd9Sstevel@tonic-gate * The number of nanoseconds the order_haddrlist_inet() function waits 1587*7c478bd9Sstevel@tonic-gate * to retreive IP interface information. The default is five minutes. 1588*7c478bd9Sstevel@tonic-gate */ 1589*7c478bd9Sstevel@tonic-gate #define IFINFOTIMEOUT ((hrtime_t)300 * NANOSEC) 1590*7c478bd9Sstevel@tonic-gate 1591*7c478bd9Sstevel@tonic-gate /* 1592*7c478bd9Sstevel@tonic-gate * Sort the addresses in haddrlist. Since the sorting algorithms are 1593*7c478bd9Sstevel@tonic-gate * address-family specific, the work is done in the address-family 1594*7c478bd9Sstevel@tonic-gate * specific order_haddrlist_<family> functions. 1595*7c478bd9Sstevel@tonic-gate * 1596*7c478bd9Sstevel@tonic-gate * Do not sort addresses if SORT_ADDRS variable is set to NO or FALSE 1597*7c478bd9Sstevel@tonic-gate * in the configuration file /etc/default/nss. This is useful in case 1598*7c478bd9Sstevel@tonic-gate * the order of addresses returned by the nameserver needs to be 1599*7c478bd9Sstevel@tonic-gate * maintained. (DNS round robin feature is one example) 1600*7c478bd9Sstevel@tonic-gate */ 1601*7c478bd9Sstevel@tonic-gate void 1602*7c478bd9Sstevel@tonic-gate order_haddrlist_af(sa_family_t af, char **haddrlist) 1603*7c478bd9Sstevel@tonic-gate { 1604*7c478bd9Sstevel@tonic-gate size_t addrcount; 1605*7c478bd9Sstevel@tonic-gate char **addrptr; 1606*7c478bd9Sstevel@tonic-gate static boolean_t checksortcfg = B_TRUE; 1607*7c478bd9Sstevel@tonic-gate static boolean_t nosort = B_FALSE; 1608*7c478bd9Sstevel@tonic-gate static mutex_t checksortcfg_lock = DEFAULTMUTEX; 1609*7c478bd9Sstevel@tonic-gate 1610*7c478bd9Sstevel@tonic-gate if (haddrlist == NULL) 1611*7c478bd9Sstevel@tonic-gate return; 1612*7c478bd9Sstevel@tonic-gate 1613*7c478bd9Sstevel@tonic-gate /* 1614*7c478bd9Sstevel@tonic-gate * Check if SORT_ADDRS is set to NO or FALSE in the configuration 1615*7c478bd9Sstevel@tonic-gate * file. We do not have to sort addresses in that case. 1616*7c478bd9Sstevel@tonic-gate */ 1617*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&checksortcfg_lock); 1618*7c478bd9Sstevel@tonic-gate if (checksortcfg == B_TRUE) { 1619*7c478bd9Sstevel@tonic-gate checksortcfg = B_FALSE; 1620*7c478bd9Sstevel@tonic-gate nosort = _read_nsw_file(); 1621*7c478bd9Sstevel@tonic-gate } 1622*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&checksortcfg_lock); 1623*7c478bd9Sstevel@tonic-gate 1624*7c478bd9Sstevel@tonic-gate if (nosort) 1625*7c478bd9Sstevel@tonic-gate return; 1626*7c478bd9Sstevel@tonic-gate 1627*7c478bd9Sstevel@tonic-gate /* Count the addresses to sort */ 1628*7c478bd9Sstevel@tonic-gate addrcount = 0; 1629*7c478bd9Sstevel@tonic-gate for (addrptr = haddrlist; *addrptr != NULL; addrptr++) 1630*7c478bd9Sstevel@tonic-gate addrcount++; 1631*7c478bd9Sstevel@tonic-gate 1632*7c478bd9Sstevel@tonic-gate /* 1633*7c478bd9Sstevel@tonic-gate * If there's only one address or no addresses to sort, then 1634*7c478bd9Sstevel@tonic-gate * there's nothing for us to do. 1635*7c478bd9Sstevel@tonic-gate */ 1636*7c478bd9Sstevel@tonic-gate if (addrcount <= 1) 1637*7c478bd9Sstevel@tonic-gate return; 1638*7c478bd9Sstevel@tonic-gate 1639*7c478bd9Sstevel@tonic-gate /* Call the address-family specific sorting functions. */ 1640*7c478bd9Sstevel@tonic-gate switch (af) { 1641*7c478bd9Sstevel@tonic-gate case AF_INET: 1642*7c478bd9Sstevel@tonic-gate order_haddrlist_inet(haddrlist, addrcount); 1643*7c478bd9Sstevel@tonic-gate break; 1644*7c478bd9Sstevel@tonic-gate case AF_INET6: 1645*7c478bd9Sstevel@tonic-gate order_haddrlist_inet6(haddrlist, addrcount); 1646*7c478bd9Sstevel@tonic-gate break; 1647*7c478bd9Sstevel@tonic-gate default: 1648*7c478bd9Sstevel@tonic-gate break; 1649*7c478bd9Sstevel@tonic-gate } 1650*7c478bd9Sstevel@tonic-gate } 1651*7c478bd9Sstevel@tonic-gate 1652*7c478bd9Sstevel@tonic-gate /* 1653*7c478bd9Sstevel@tonic-gate * Move any local (on-link) addresses toward the beginning of haddrlist. 1654*7c478bd9Sstevel@tonic-gate * The order within these two classes is preserved. 1655*7c478bd9Sstevel@tonic-gate * 1656*7c478bd9Sstevel@tonic-gate * The interface list is retrieved no more often than every 1657*7c478bd9Sstevel@tonic-gate * IFINFOTIMEOUT nanoseconds. Access to the interface list is 1658*7c478bd9Sstevel@tonic-gate * protected by an RW lock. 1659*7c478bd9Sstevel@tonic-gate * 1660*7c478bd9Sstevel@tonic-gate * If this function encounters an error, haddrlist is unaltered. 1661*7c478bd9Sstevel@tonic-gate */ 1662*7c478bd9Sstevel@tonic-gate static void 1663*7c478bd9Sstevel@tonic-gate order_haddrlist_inet(char **haddrlist, size_t addrcount) 1664*7c478bd9Sstevel@tonic-gate { 1665*7c478bd9Sstevel@tonic-gate static struct ifinfo *localinfo = NULL; 1666*7c478bd9Sstevel@tonic-gate static hrtime_t then = 0; /* the last time localinfo was updated */ 1667*7c478bd9Sstevel@tonic-gate hrtime_t now; 1668*7c478bd9Sstevel@tonic-gate static rwlock_t localinfo_lock = DEFAULTRWLOCK; 1669*7c478bd9Sstevel@tonic-gate uint8_t *sortbuf; 1670*7c478bd9Sstevel@tonic-gate size_t sortbuf_size; 1671*7c478bd9Sstevel@tonic-gate struct in_addr **inaddrlist = (struct in_addr **)haddrlist; 1672*7c478bd9Sstevel@tonic-gate struct in_addr **sorted; 1673*7c478bd9Sstevel@tonic-gate struct in_addr **classnext[ADDR_NUMCLASSES]; 1674*7c478bd9Sstevel@tonic-gate uint_t classcount[ADDR_NUMCLASSES]; 1675*7c478bd9Sstevel@tonic-gate addr_class_t *sortclass; 1676*7c478bd9Sstevel@tonic-gate int i; 1677*7c478bd9Sstevel@tonic-gate int rc; 1678*7c478bd9Sstevel@tonic-gate 1679*7c478bd9Sstevel@tonic-gate 1680*7c478bd9Sstevel@tonic-gate /* 1681*7c478bd9Sstevel@tonic-gate * The classes in the sortclass array correspond to the class 1682*7c478bd9Sstevel@tonic-gate * of the address in the haddrlist list of the same index. 1683*7c478bd9Sstevel@tonic-gate * The classes are: 1684*7c478bd9Sstevel@tonic-gate * 1685*7c478bd9Sstevel@tonic-gate * ADDR_ONLINK on-link address 1686*7c478bd9Sstevel@tonic-gate * ADDR_OFFLINK off-link address 1687*7c478bd9Sstevel@tonic-gate */ 1688*7c478bd9Sstevel@tonic-gate sortbuf_size = addrcount * 1689*7c478bd9Sstevel@tonic-gate (sizeof (struct in_addr *) + sizeof (addr_class_t)); 1690*7c478bd9Sstevel@tonic-gate if ((sortbuf = malloc(sortbuf_size)) == NULL) 1691*7c478bd9Sstevel@tonic-gate return; 1692*7c478bd9Sstevel@tonic-gate sorted = (struct in_addr **)sortbuf; 1693*7c478bd9Sstevel@tonic-gate sortclass = (addr_class_t *)(sortbuf + 1694*7c478bd9Sstevel@tonic-gate (addrcount * sizeof (struct in_addr *))); 1695*7c478bd9Sstevel@tonic-gate 1696*7c478bd9Sstevel@tonic-gate /* 1697*7c478bd9Sstevel@tonic-gate * Get a read lock, and check if the interface information 1698*7c478bd9Sstevel@tonic-gate * is too old. 1699*7c478bd9Sstevel@tonic-gate */ 1700*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&localinfo_lock); 1701*7c478bd9Sstevel@tonic-gate now = gethrtime(); 1702*7c478bd9Sstevel@tonic-gate if (localinfo == NULL || ((now - then) > IFINFOTIMEOUT)) { 1703*7c478bd9Sstevel@tonic-gate /* Need to update I/F info. Upgrade to write lock. */ 1704*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&localinfo_lock); 1705*7c478bd9Sstevel@tonic-gate (void) rw_wrlock(&localinfo_lock); 1706*7c478bd9Sstevel@tonic-gate /* 1707*7c478bd9Sstevel@tonic-gate * Another thread might have updated "then" between 1708*7c478bd9Sstevel@tonic-gate * the rw_unlock() and rw_wrlock() calls above, so 1709*7c478bd9Sstevel@tonic-gate * re-check the timeout. 1710*7c478bd9Sstevel@tonic-gate */ 1711*7c478bd9Sstevel@tonic-gate if (localinfo == NULL || ((now - then) > IFINFOTIMEOUT)) { 1712*7c478bd9Sstevel@tonic-gate if (localinfo != NULL) 1713*7c478bd9Sstevel@tonic-gate free(localinfo); 1714*7c478bd9Sstevel@tonic-gate if ((localinfo = get_local_info()) == NULL) { 1715*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&localinfo_lock); 1716*7c478bd9Sstevel@tonic-gate free(sortbuf); 1717*7c478bd9Sstevel@tonic-gate return; 1718*7c478bd9Sstevel@tonic-gate } 1719*7c478bd9Sstevel@tonic-gate then = now; 1720*7c478bd9Sstevel@tonic-gate } 1721*7c478bd9Sstevel@tonic-gate /* Downgrade to read lock */ 1722*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&localinfo_lock); 1723*7c478bd9Sstevel@tonic-gate (void) rw_rdlock(&localinfo_lock); 1724*7c478bd9Sstevel@tonic-gate /* 1725*7c478bd9Sstevel@tonic-gate * Another thread may have updated the I/F info, 1726*7c478bd9Sstevel@tonic-gate * so verify that the 'localinfo' pointer still 1727*7c478bd9Sstevel@tonic-gate * is non-NULL. 1728*7c478bd9Sstevel@tonic-gate */ 1729*7c478bd9Sstevel@tonic-gate if (localinfo == NULL) { 1730*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&localinfo_lock); 1731*7c478bd9Sstevel@tonic-gate free(sortbuf); 1732*7c478bd9Sstevel@tonic-gate return; 1733*7c478bd9Sstevel@tonic-gate } 1734*7c478bd9Sstevel@tonic-gate } 1735*7c478bd9Sstevel@tonic-gate 1736*7c478bd9Sstevel@tonic-gate /* 1737*7c478bd9Sstevel@tonic-gate * Classify the addresses. We also maintain the classcount 1738*7c478bd9Sstevel@tonic-gate * array to keep track of the number of addresses in each 1739*7c478bd9Sstevel@tonic-gate * class. 1740*7c478bd9Sstevel@tonic-gate */ 1741*7c478bd9Sstevel@tonic-gate memset(classcount, 0, sizeof (classcount)); 1742*7c478bd9Sstevel@tonic-gate for (i = 0; i < addrcount; i++) { 1743*7c478bd9Sstevel@tonic-gate if (__inet_address_is_local_af(localinfo, AF_INET, 1744*7c478bd9Sstevel@tonic-gate inaddrlist[i])) 1745*7c478bd9Sstevel@tonic-gate sortclass[i] = ADDR_ONLINK; 1746*7c478bd9Sstevel@tonic-gate else 1747*7c478bd9Sstevel@tonic-gate sortclass[i] = ADDR_OFFLINK; 1748*7c478bd9Sstevel@tonic-gate classcount[sortclass[i]]++; 1749*7c478bd9Sstevel@tonic-gate } 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate /* Don't need the interface list anymore in this call */ 1752*7c478bd9Sstevel@tonic-gate (void) rw_unlock(&localinfo_lock); 1753*7c478bd9Sstevel@tonic-gate 1754*7c478bd9Sstevel@tonic-gate /* 1755*7c478bd9Sstevel@tonic-gate * Each element in the classnext array points to the next 1756*7c478bd9Sstevel@tonic-gate * element for that class in the sorted address list. 'rc' is 1757*7c478bd9Sstevel@tonic-gate * the running count of elements as we sum the class 1758*7c478bd9Sstevel@tonic-gate * sub-totals. 1759*7c478bd9Sstevel@tonic-gate */ 1760*7c478bd9Sstevel@tonic-gate for (rc = 0, i = 0; i < ADDR_NUMCLASSES; i++) { 1761*7c478bd9Sstevel@tonic-gate classnext[i] = &sorted[rc]; 1762*7c478bd9Sstevel@tonic-gate rc += classcount[i]; 1763*7c478bd9Sstevel@tonic-gate } 1764*7c478bd9Sstevel@tonic-gate 1765*7c478bd9Sstevel@tonic-gate /* Now for the actual rearrangement of the addresses */ 1766*7c478bd9Sstevel@tonic-gate for (i = 0; i < addrcount; i++) { 1767*7c478bd9Sstevel@tonic-gate *(classnext[sortclass[i]]) = inaddrlist[i]; 1768*7c478bd9Sstevel@tonic-gate classnext[sortclass[i]]++; 1769*7c478bd9Sstevel@tonic-gate } 1770*7c478bd9Sstevel@tonic-gate 1771*7c478bd9Sstevel@tonic-gate /* Copy the sorted list to inaddrlist */ 1772*7c478bd9Sstevel@tonic-gate (void) memcpy(inaddrlist, sorted, 1773*7c478bd9Sstevel@tonic-gate addrcount * sizeof (struct in_addr *)); 1774*7c478bd9Sstevel@tonic-gate free(sortbuf); 1775*7c478bd9Sstevel@tonic-gate } 1776*7c478bd9Sstevel@tonic-gate 1777*7c478bd9Sstevel@tonic-gate /* 1778*7c478bd9Sstevel@tonic-gate * This function implements the IPv6 Default Address Selection's 1779*7c478bd9Sstevel@tonic-gate * destination address ordering mechanism. The algorithm is described 1780*7c478bd9Sstevel@tonic-gate * in getaddrinfo(3SOCKET). 1781*7c478bd9Sstevel@tonic-gate */ 1782*7c478bd9Sstevel@tonic-gate static void 1783*7c478bd9Sstevel@tonic-gate order_haddrlist_inet6(char **haddrlist, size_t addrcount) 1784*7c478bd9Sstevel@tonic-gate { 1785*7c478bd9Sstevel@tonic-gate struct dstinforeq *dinfo, *dinfoptr; 1786*7c478bd9Sstevel@tonic-gate int index; 1787*7c478bd9Sstevel@tonic-gate struct in6_addr **in6addrlist = (struct in6_addr **)haddrlist; 1788*7c478bd9Sstevel@tonic-gate struct in6_addr **in6addr; 1789*7c478bd9Sstevel@tonic-gate 1790*7c478bd9Sstevel@tonic-gate if ((dinfo = calloc(addrcount, sizeof (struct dstinforeq))) == NULL) 1791*7c478bd9Sstevel@tonic-gate return; 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate /* Initialize the dstinfo array we'll use for SIOCGDSTINFO */ 1794*7c478bd9Sstevel@tonic-gate dinfoptr = dinfo; 1795*7c478bd9Sstevel@tonic-gate for (in6addr = in6addrlist; *in6addr != NULL; in6addr++) { 1796*7c478bd9Sstevel@tonic-gate dinfoptr->dir_daddr = **in6addr; 1797*7c478bd9Sstevel@tonic-gate dinfoptr++; 1798*7c478bd9Sstevel@tonic-gate } 1799*7c478bd9Sstevel@tonic-gate 1800*7c478bd9Sstevel@tonic-gate if (nss_strioctl(AF_INET6, SIOCGDSTINFO, dinfo, 1801*7c478bd9Sstevel@tonic-gate addrcount * sizeof (struct dstinforeq)) < 0) { 1802*7c478bd9Sstevel@tonic-gate free(dinfo); 1803*7c478bd9Sstevel@tonic-gate return; 1804*7c478bd9Sstevel@tonic-gate } 1805*7c478bd9Sstevel@tonic-gate 1806*7c478bd9Sstevel@tonic-gate /* Sort the dinfo array */ 1807*7c478bd9Sstevel@tonic-gate qsort(dinfo, addrcount, sizeof (struct dstinforeq), dstcmp); 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate /* Copy the addresses back into in6addrlist */ 1810*7c478bd9Sstevel@tonic-gate dinfoptr = dinfo; 1811*7c478bd9Sstevel@tonic-gate for (in6addr = in6addrlist; *in6addr != NULL; in6addr++) { 1812*7c478bd9Sstevel@tonic-gate **in6addr = dinfoptr->dir_daddr; 1813*7c478bd9Sstevel@tonic-gate dinfoptr++; 1814*7c478bd9Sstevel@tonic-gate } 1815*7c478bd9Sstevel@tonic-gate 1816*7c478bd9Sstevel@tonic-gate free(dinfo); 1817*7c478bd9Sstevel@tonic-gate } 1818*7c478bd9Sstevel@tonic-gate 1819*7c478bd9Sstevel@tonic-gate /* 1820*7c478bd9Sstevel@tonic-gate * Determine number of leading bits that are common between two addresses. 1821*7c478bd9Sstevel@tonic-gate * Only consider bits which fall within the prefix length plen. 1822*7c478bd9Sstevel@tonic-gate */ 1823*7c478bd9Sstevel@tonic-gate static uint_t 1824*7c478bd9Sstevel@tonic-gate ip_addr_commonbits_v6(const in6_addr_t *a1, const in6_addr_t *a2) 1825*7c478bd9Sstevel@tonic-gate { 1826*7c478bd9Sstevel@tonic-gate uint_t bits; 1827*7c478bd9Sstevel@tonic-gate uint_t i; 1828*7c478bd9Sstevel@tonic-gate uint32_t diff; /* Bits that differ */ 1829*7c478bd9Sstevel@tonic-gate 1830*7c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) { 1831*7c478bd9Sstevel@tonic-gate if (a1->_S6_un._S6_u32[i] != a2->_S6_un._S6_u32[i]) 1832*7c478bd9Sstevel@tonic-gate break; 1833*7c478bd9Sstevel@tonic-gate } 1834*7c478bd9Sstevel@tonic-gate bits = i * 32; 1835*7c478bd9Sstevel@tonic-gate 1836*7c478bd9Sstevel@tonic-gate if (bits == IPV6_ABITS) 1837*7c478bd9Sstevel@tonic-gate return (IPV6_ABITS); 1838*7c478bd9Sstevel@tonic-gate 1839*7c478bd9Sstevel@tonic-gate /* 1840*7c478bd9Sstevel@tonic-gate * Find number of leading common bits in the word which might 1841*7c478bd9Sstevel@tonic-gate * have some common bits by searching for the first one from the left 1842*7c478bd9Sstevel@tonic-gate * in the xor of the two addresses. 1843*7c478bd9Sstevel@tonic-gate */ 1844*7c478bd9Sstevel@tonic-gate diff = ntohl(a1->_S6_un._S6_u32[i] ^ a2->_S6_un._S6_u32[i]); 1845*7c478bd9Sstevel@tonic-gate if (diff & 0xffff0000ul) 1846*7c478bd9Sstevel@tonic-gate diff >>= 16; 1847*7c478bd9Sstevel@tonic-gate else 1848*7c478bd9Sstevel@tonic-gate bits += 16; 1849*7c478bd9Sstevel@tonic-gate if (diff & 0xff00) 1850*7c478bd9Sstevel@tonic-gate diff >>= 8; 1851*7c478bd9Sstevel@tonic-gate else 1852*7c478bd9Sstevel@tonic-gate bits += 8; 1853*7c478bd9Sstevel@tonic-gate if (diff & 0xf0) 1854*7c478bd9Sstevel@tonic-gate diff >>= 4; 1855*7c478bd9Sstevel@tonic-gate else 1856*7c478bd9Sstevel@tonic-gate bits += 4; 1857*7c478bd9Sstevel@tonic-gate if (diff & 0xc) 1858*7c478bd9Sstevel@tonic-gate diff >>= 2; 1859*7c478bd9Sstevel@tonic-gate else 1860*7c478bd9Sstevel@tonic-gate bits += 2; 1861*7c478bd9Sstevel@tonic-gate if (!(diff & 2)) 1862*7c478bd9Sstevel@tonic-gate bits++; 1863*7c478bd9Sstevel@tonic-gate 1864*7c478bd9Sstevel@tonic-gate /* 1865*7c478bd9Sstevel@tonic-gate * We don't need to shift and check for the last bit. The 1866*7c478bd9Sstevel@tonic-gate * check for IPV6_ABITS above would have caught that. 1867*7c478bd9Sstevel@tonic-gate */ 1868*7c478bd9Sstevel@tonic-gate 1869*7c478bd9Sstevel@tonic-gate return (bits); 1870*7c478bd9Sstevel@tonic-gate } 1871*7c478bd9Sstevel@tonic-gate 1872*7c478bd9Sstevel@tonic-gate 1873*7c478bd9Sstevel@tonic-gate /* 1874*7c478bd9Sstevel@tonic-gate * The following group of functions named rule_*() are individual 1875*7c478bd9Sstevel@tonic-gate * sorting rules for the AF_INET6 address sorting algorithm. The 1876*7c478bd9Sstevel@tonic-gate * functions compare two addresses (described by two dstinforeq 1877*7c478bd9Sstevel@tonic-gate * structures), and determines if one is "greater" than the other, or 1878*7c478bd9Sstevel@tonic-gate * if the two are equal according to that rule. 1879*7c478bd9Sstevel@tonic-gate */ 1880*7c478bd9Sstevel@tonic-gate typedef int (*rulef_t)(const struct dstinforeq *, const struct dstinforeq *); 1881*7c478bd9Sstevel@tonic-gate 1882*7c478bd9Sstevel@tonic-gate /* 1883*7c478bd9Sstevel@tonic-gate * These values of these constants are no accident. Since qsort() 1884*7c478bd9Sstevel@tonic-gate * implements the AF_INET6 address sorting, the comparison function 1885*7c478bd9Sstevel@tonic-gate * must return an integer less than, equal to, or greater than zero to 1886*7c478bd9Sstevel@tonic-gate * indicate if the first address is considered "less than", "equal 1887*7c478bd9Sstevel@tonic-gate * to", or "greater than" the second one. Since we want the best 1888*7c478bd9Sstevel@tonic-gate * addresses first on the list, "less than" is considered preferrable. 1889*7c478bd9Sstevel@tonic-gate */ 1890*7c478bd9Sstevel@tonic-gate #define RULE_PREFER_DA -1 1891*7c478bd9Sstevel@tonic-gate #define RULE_PREFER_DB 1 1892*7c478bd9Sstevel@tonic-gate #define RULE_EQUAL 0 1893*7c478bd9Sstevel@tonic-gate 1894*7c478bd9Sstevel@tonic-gate /* Prefer the addresses that is reachable. */ 1895*7c478bd9Sstevel@tonic-gate static int 1896*7c478bd9Sstevel@tonic-gate rule_reachable(const struct dstinforeq *da, const struct dstinforeq *db) 1897*7c478bd9Sstevel@tonic-gate { 1898*7c478bd9Sstevel@tonic-gate if (da->dir_dreachable == db->dir_dreachable) 1899*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 1900*7c478bd9Sstevel@tonic-gate if (da->dir_dreachable) 1901*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DA); 1902*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DB); 1903*7c478bd9Sstevel@tonic-gate } 1904*7c478bd9Sstevel@tonic-gate 1905*7c478bd9Sstevel@tonic-gate /* Prefer the address whose scope matches that of its source address. */ 1906*7c478bd9Sstevel@tonic-gate static int 1907*7c478bd9Sstevel@tonic-gate rule_matchscope(const struct dstinforeq *da, const struct dstinforeq *db) 1908*7c478bd9Sstevel@tonic-gate { 1909*7c478bd9Sstevel@tonic-gate boolean_t da_scope_match, db_scope_match; 1910*7c478bd9Sstevel@tonic-gate 1911*7c478bd9Sstevel@tonic-gate da_scope_match = da->dir_dscope == da->dir_sscope; 1912*7c478bd9Sstevel@tonic-gate db_scope_match = db->dir_dscope == db->dir_sscope; 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate if (da_scope_match == db_scope_match) 1915*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 1916*7c478bd9Sstevel@tonic-gate if (da_scope_match) 1917*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DA); 1918*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DB); 1919*7c478bd9Sstevel@tonic-gate } 1920*7c478bd9Sstevel@tonic-gate 1921*7c478bd9Sstevel@tonic-gate /* Avoid the address with the link local source address. */ 1922*7c478bd9Sstevel@tonic-gate static int 1923*7c478bd9Sstevel@tonic-gate rule_avoidlinklocal(const struct dstinforeq *da, const struct dstinforeq *db) 1924*7c478bd9Sstevel@tonic-gate { 1925*7c478bd9Sstevel@tonic-gate if (da->dir_sscope == IP6_SCOPE_LINKLOCAL && 1926*7c478bd9Sstevel@tonic-gate da->dir_dscope != IP6_SCOPE_LINKLOCAL && 1927*7c478bd9Sstevel@tonic-gate db->dir_sscope != IP6_SCOPE_LINKLOCAL) 1928*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DB); 1929*7c478bd9Sstevel@tonic-gate if (db->dir_sscope == IP6_SCOPE_LINKLOCAL && 1930*7c478bd9Sstevel@tonic-gate db->dir_dscope != IP6_SCOPE_LINKLOCAL && 1931*7c478bd9Sstevel@tonic-gate da->dir_sscope != IP6_SCOPE_LINKLOCAL) 1932*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DA); 1933*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 1934*7c478bd9Sstevel@tonic-gate } 1935*7c478bd9Sstevel@tonic-gate 1936*7c478bd9Sstevel@tonic-gate /* Prefer the address whose source address isn't deprecated. */ 1937*7c478bd9Sstevel@tonic-gate static int 1938*7c478bd9Sstevel@tonic-gate rule_deprecated(const struct dstinforeq *da, const struct dstinforeq *db) 1939*7c478bd9Sstevel@tonic-gate { 1940*7c478bd9Sstevel@tonic-gate if (da->dir_sdeprecated == db->dir_sdeprecated) 1941*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 1942*7c478bd9Sstevel@tonic-gate if (db->dir_sdeprecated) 1943*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DA); 1944*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DB); 1945*7c478bd9Sstevel@tonic-gate } 1946*7c478bd9Sstevel@tonic-gate 1947*7c478bd9Sstevel@tonic-gate /* Prefer the address whose label matches that of its source address. */ 1948*7c478bd9Sstevel@tonic-gate static int 1949*7c478bd9Sstevel@tonic-gate rule_label(const struct dstinforeq *da, const struct dstinforeq *db) 1950*7c478bd9Sstevel@tonic-gate { 1951*7c478bd9Sstevel@tonic-gate if (da->dir_labelmatch == db->dir_labelmatch) 1952*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 1953*7c478bd9Sstevel@tonic-gate if (da->dir_labelmatch) 1954*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DA); 1955*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DB); 1956*7c478bd9Sstevel@tonic-gate } 1957*7c478bd9Sstevel@tonic-gate 1958*7c478bd9Sstevel@tonic-gate /* Prefer the address with the higher precedence. */ 1959*7c478bd9Sstevel@tonic-gate static int 1960*7c478bd9Sstevel@tonic-gate rule_precedence(const struct dstinforeq *da, const struct dstinforeq *db) 1961*7c478bd9Sstevel@tonic-gate { 1962*7c478bd9Sstevel@tonic-gate if (da->dir_precedence == db->dir_precedence) 1963*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 1964*7c478bd9Sstevel@tonic-gate if (da->dir_precedence > db->dir_precedence) 1965*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DA); 1966*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DB); 1967*7c478bd9Sstevel@tonic-gate } 1968*7c478bd9Sstevel@tonic-gate 1969*7c478bd9Sstevel@tonic-gate /* Prefer the address whose output interface isn't an IP tunnel */ 1970*7c478bd9Sstevel@tonic-gate static int 1971*7c478bd9Sstevel@tonic-gate rule_native(const struct dstinforeq *da, const struct dstinforeq *db) 1972*7c478bd9Sstevel@tonic-gate { 1973*7c478bd9Sstevel@tonic-gate boolean_t isatun, isbtun; 1974*7c478bd9Sstevel@tonic-gate 1975*7c478bd9Sstevel@tonic-gate /* Get the common case out of the way early */ 1976*7c478bd9Sstevel@tonic-gate if (da->dir_dmactype == db->dir_dmactype) 1977*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 1978*7c478bd9Sstevel@tonic-gate 1979*7c478bd9Sstevel@tonic-gate isatun = da->dir_dmactype == DL_IPV4 || da->dir_dmactype == DL_IPV6; 1980*7c478bd9Sstevel@tonic-gate isbtun = db->dir_dmactype == DL_IPV4 || db->dir_dmactype == DL_IPV6; 1981*7c478bd9Sstevel@tonic-gate 1982*7c478bd9Sstevel@tonic-gate if (isatun == isbtun) 1983*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 1984*7c478bd9Sstevel@tonic-gate if (isbtun) 1985*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DA); 1986*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DB); 1987*7c478bd9Sstevel@tonic-gate } 1988*7c478bd9Sstevel@tonic-gate 1989*7c478bd9Sstevel@tonic-gate /* Prefer the address with the smaller scope. */ 1990*7c478bd9Sstevel@tonic-gate static int 1991*7c478bd9Sstevel@tonic-gate rule_scope(const struct dstinforeq *da, const struct dstinforeq *db) 1992*7c478bd9Sstevel@tonic-gate { 1993*7c478bd9Sstevel@tonic-gate if (da->dir_dscope == db->dir_dscope) 1994*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 1995*7c478bd9Sstevel@tonic-gate if (da->dir_dscope < db->dir_dscope) 1996*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DA); 1997*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DB); 1998*7c478bd9Sstevel@tonic-gate } 1999*7c478bd9Sstevel@tonic-gate 2000*7c478bd9Sstevel@tonic-gate /* 2001*7c478bd9Sstevel@tonic-gate * Prefer the address that has the most leading bits in common with its 2002*7c478bd9Sstevel@tonic-gate * source address. 2003*7c478bd9Sstevel@tonic-gate */ 2004*7c478bd9Sstevel@tonic-gate static int 2005*7c478bd9Sstevel@tonic-gate rule_prefix(const struct dstinforeq *da, const struct dstinforeq *db) 2006*7c478bd9Sstevel@tonic-gate { 2007*7c478bd9Sstevel@tonic-gate uint_t da_commonbits, db_commonbits; 2008*7c478bd9Sstevel@tonic-gate boolean_t da_isipv4, db_isipv4; 2009*7c478bd9Sstevel@tonic-gate 2010*7c478bd9Sstevel@tonic-gate da_isipv4 = IN6_IS_ADDR_V4MAPPED(&da->dir_daddr); 2011*7c478bd9Sstevel@tonic-gate db_isipv4 = IN6_IS_ADDR_V4MAPPED(&db->dir_daddr); 2012*7c478bd9Sstevel@tonic-gate 2013*7c478bd9Sstevel@tonic-gate /* 2014*7c478bd9Sstevel@tonic-gate * At this point, the order doesn't matter if the two addresses 2015*7c478bd9Sstevel@tonic-gate * aren't of the same address family. 2016*7c478bd9Sstevel@tonic-gate */ 2017*7c478bd9Sstevel@tonic-gate if (da_isipv4 != db_isipv4) 2018*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 2019*7c478bd9Sstevel@tonic-gate 2020*7c478bd9Sstevel@tonic-gate da_commonbits = ip_addr_commonbits_v6(&da->dir_daddr, &da->dir_saddr); 2021*7c478bd9Sstevel@tonic-gate db_commonbits = ip_addr_commonbits_v6(&db->dir_daddr, &db->dir_saddr); 2022*7c478bd9Sstevel@tonic-gate 2023*7c478bd9Sstevel@tonic-gate if (da_commonbits > db_commonbits) 2024*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DA); 2025*7c478bd9Sstevel@tonic-gate if (da_commonbits < db_commonbits) 2026*7c478bd9Sstevel@tonic-gate return (RULE_PREFER_DB); 2027*7c478bd9Sstevel@tonic-gate return (RULE_EQUAL); 2028*7c478bd9Sstevel@tonic-gate } 2029*7c478bd9Sstevel@tonic-gate 2030*7c478bd9Sstevel@tonic-gate /* 2031*7c478bd9Sstevel@tonic-gate * This is the function passed to qsort() that does the AF_INET6 2032*7c478bd9Sstevel@tonic-gate * address comparisons. It compares two addresses using a list of 2033*7c478bd9Sstevel@tonic-gate * rules. The rules are applied in order until one prefers one 2034*7c478bd9Sstevel@tonic-gate * address over the other. 2035*7c478bd9Sstevel@tonic-gate */ 2036*7c478bd9Sstevel@tonic-gate static int 2037*7c478bd9Sstevel@tonic-gate dstcmp(const void *da, const void *db) 2038*7c478bd9Sstevel@tonic-gate { 2039*7c478bd9Sstevel@tonic-gate int index, result; 2040*7c478bd9Sstevel@tonic-gate rulef_t rules[] = { 2041*7c478bd9Sstevel@tonic-gate rule_reachable, 2042*7c478bd9Sstevel@tonic-gate rule_matchscope, 2043*7c478bd9Sstevel@tonic-gate rule_avoidlinklocal, 2044*7c478bd9Sstevel@tonic-gate rule_deprecated, 2045*7c478bd9Sstevel@tonic-gate rule_label, 2046*7c478bd9Sstevel@tonic-gate rule_precedence, 2047*7c478bd9Sstevel@tonic-gate rule_native, 2048*7c478bd9Sstevel@tonic-gate rule_scope, 2049*7c478bd9Sstevel@tonic-gate rule_prefix, 2050*7c478bd9Sstevel@tonic-gate NULL 2051*7c478bd9Sstevel@tonic-gate }; 2052*7c478bd9Sstevel@tonic-gate 2053*7c478bd9Sstevel@tonic-gate result = 0; 2054*7c478bd9Sstevel@tonic-gate for (index = 0; rules[index] != NULL; index++) { 2055*7c478bd9Sstevel@tonic-gate result = (rules[index])(da, db); 2056*7c478bd9Sstevel@tonic-gate if (result != RULE_EQUAL) 2057*7c478bd9Sstevel@tonic-gate break; 2058*7c478bd9Sstevel@tonic-gate } 2059*7c478bd9Sstevel@tonic-gate 2060*7c478bd9Sstevel@tonic-gate return (result); 2061*7c478bd9Sstevel@tonic-gate } 2062*7c478bd9Sstevel@tonic-gate 2063*7c478bd9Sstevel@tonic-gate /* 2064*7c478bd9Sstevel@tonic-gate * Given haddrlist and a port number, mallocs and populates a new 2065*7c478bd9Sstevel@tonic-gate * nd_addrlist. The new nd_addrlist maintains the order of the addresses 2066*7c478bd9Sstevel@tonic-gate * in haddrlist, which have already been sorted by order_haddrlist_inet() 2067*7c478bd9Sstevel@tonic-gate * or order_haddrlist_inet6(). For IPv6 this function filters out 2068*7c478bd9Sstevel@tonic-gate * IPv4-mapped IPv6 addresses. 2069*7c478bd9Sstevel@tonic-gate */ 2070*7c478bd9Sstevel@tonic-gate int 2071*7c478bd9Sstevel@tonic-gate hent2ndaddr(int af, char **haddrlist, int *servp, struct nd_addrlist **nd_alist) 2072*7c478bd9Sstevel@tonic-gate { 2073*7c478bd9Sstevel@tonic-gate struct nd_addrlist *result; 2074*7c478bd9Sstevel@tonic-gate int num; 2075*7c478bd9Sstevel@tonic-gate struct netbuf *na; 2076*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sinbuf, *sin; 2077*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6buf, *sin6; 2078*7c478bd9Sstevel@tonic-gate struct in_addr **inaddr, **inaddrlist; 2079*7c478bd9Sstevel@tonic-gate struct in6_addr **in6addr, **in6addrlist; 2080*7c478bd9Sstevel@tonic-gate 2081*7c478bd9Sstevel@tonic-gate /* Address count */ 2082*7c478bd9Sstevel@tonic-gate num = 0; 2083*7c478bd9Sstevel@tonic-gate if (af == AF_INET6) { 2084*7c478bd9Sstevel@tonic-gate in6addrlist = (struct in6_addr **)haddrlist; 2085*7c478bd9Sstevel@tonic-gate 2086*7c478bd9Sstevel@tonic-gate /* 2087*7c478bd9Sstevel@tonic-gate * Exclude IPv4-mapped IPv6 addresses from the count, as 2088*7c478bd9Sstevel@tonic-gate * these are not included in the nd_addrlist we return. 2089*7c478bd9Sstevel@tonic-gate */ 2090*7c478bd9Sstevel@tonic-gate for (in6addr = in6addrlist; *in6addr != NULL; in6addr++) 2091*7c478bd9Sstevel@tonic-gate if (!IN6_IS_ADDR_V4MAPPED(*in6addr)) 2092*7c478bd9Sstevel@tonic-gate num++; 2093*7c478bd9Sstevel@tonic-gate } else { 2094*7c478bd9Sstevel@tonic-gate inaddrlist = (struct in_addr **)haddrlist; 2095*7c478bd9Sstevel@tonic-gate 2096*7c478bd9Sstevel@tonic-gate for (inaddr = inaddrlist; *inaddr != NULL; inaddr++) 2097*7c478bd9Sstevel@tonic-gate num++; 2098*7c478bd9Sstevel@tonic-gate } 2099*7c478bd9Sstevel@tonic-gate if (num == 0) 2100*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 2101*7c478bd9Sstevel@tonic-gate 2102*7c478bd9Sstevel@tonic-gate result = malloc(sizeof (struct nd_addrlist)); 2103*7c478bd9Sstevel@tonic-gate if (result == 0) 2104*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2105*7c478bd9Sstevel@tonic-gate 2106*7c478bd9Sstevel@tonic-gate result->n_cnt = num; 2107*7c478bd9Sstevel@tonic-gate result->n_addrs = calloc(num, sizeof (struct netbuf)); 2108*7c478bd9Sstevel@tonic-gate if (result->n_addrs == 0) { 2109*7c478bd9Sstevel@tonic-gate free(result); 2110*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2111*7c478bd9Sstevel@tonic-gate } 2112*7c478bd9Sstevel@tonic-gate 2113*7c478bd9Sstevel@tonic-gate na = result->n_addrs; 2114*7c478bd9Sstevel@tonic-gate if (af == AF_INET) { 2115*7c478bd9Sstevel@tonic-gate sinbuf = calloc(num, sizeof (struct sockaddr_in)); 2116*7c478bd9Sstevel@tonic-gate if (sinbuf == NULL) { 2117*7c478bd9Sstevel@tonic-gate free(result->n_addrs); 2118*7c478bd9Sstevel@tonic-gate free(result); 2119*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2120*7c478bd9Sstevel@tonic-gate } 2121*7c478bd9Sstevel@tonic-gate 2122*7c478bd9Sstevel@tonic-gate sin = sinbuf; 2123*7c478bd9Sstevel@tonic-gate for (inaddr = inaddrlist; *inaddr != NULL; inaddr++) { 2124*7c478bd9Sstevel@tonic-gate na->len = na->maxlen = sizeof (struct sockaddr_in); 2125*7c478bd9Sstevel@tonic-gate na->buf = (char *)sin; 2126*7c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 2127*7c478bd9Sstevel@tonic-gate sin->sin_addr = **inaddr; 2128*7c478bd9Sstevel@tonic-gate sin->sin_port = *servp; 2129*7c478bd9Sstevel@tonic-gate na++; 2130*7c478bd9Sstevel@tonic-gate sin++; 2131*7c478bd9Sstevel@tonic-gate } 2132*7c478bd9Sstevel@tonic-gate } else if (af == AF_INET6) { 2133*7c478bd9Sstevel@tonic-gate sin6buf = calloc(num, sizeof (struct sockaddr_in6)); 2134*7c478bd9Sstevel@tonic-gate if (sin6buf == NULL) { 2135*7c478bd9Sstevel@tonic-gate free(result->n_addrs); 2136*7c478bd9Sstevel@tonic-gate free(result); 2137*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2138*7c478bd9Sstevel@tonic-gate } 2139*7c478bd9Sstevel@tonic-gate 2140*7c478bd9Sstevel@tonic-gate sin6 = sin6buf; 2141*7c478bd9Sstevel@tonic-gate for (in6addr = in6addrlist; *in6addr != NULL; in6addr++) { 2142*7c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(*in6addr)) 2143*7c478bd9Sstevel@tonic-gate continue; 2144*7c478bd9Sstevel@tonic-gate 2145*7c478bd9Sstevel@tonic-gate na->len = na->maxlen = sizeof (struct sockaddr_in6); 2146*7c478bd9Sstevel@tonic-gate na->buf = (char *)sin6; 2147*7c478bd9Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 2148*7c478bd9Sstevel@tonic-gate sin6->sin6_addr = **in6addr; 2149*7c478bd9Sstevel@tonic-gate sin6->sin6_port = *servp; 2150*7c478bd9Sstevel@tonic-gate na++; 2151*7c478bd9Sstevel@tonic-gate sin6++; 2152*7c478bd9Sstevel@tonic-gate } 2153*7c478bd9Sstevel@tonic-gate } 2154*7c478bd9Sstevel@tonic-gate *(nd_alist) = result; 2155*7c478bd9Sstevel@tonic-gate return (ND_OK); 2156*7c478bd9Sstevel@tonic-gate } 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate /* 2159*7c478bd9Sstevel@tonic-gate * Given a hostent and a servent, mallocs and populates 2160*7c478bd9Sstevel@tonic-gate * a new nd_hostservlist with host and service names. 2161*7c478bd9Sstevel@tonic-gate * 2162*7c478bd9Sstevel@tonic-gate * We could be passed in a NULL servent, in which case stringify port. 2163*7c478bd9Sstevel@tonic-gate */ 2164*7c478bd9Sstevel@tonic-gate int 2165*7c478bd9Sstevel@tonic-gate hsents2ndhostservs(struct hostent *he, struct servent *se, 2166*7c478bd9Sstevel@tonic-gate ushort_t port, struct nd_hostservlist **hslist) 2167*7c478bd9Sstevel@tonic-gate { 2168*7c478bd9Sstevel@tonic-gate struct nd_hostservlist *result; 2169*7c478bd9Sstevel@tonic-gate struct nd_hostserv *hs; 2170*7c478bd9Sstevel@tonic-gate int hosts, servs, i, j; 2171*7c478bd9Sstevel@tonic-gate char **hn, **sn; 2172*7c478bd9Sstevel@tonic-gate 2173*7c478bd9Sstevel@tonic-gate if ((result = (struct nd_hostservlist *) 2174*7c478bd9Sstevel@tonic-gate malloc(sizeof (struct nd_hostservlist))) == 0) 2175*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2176*7c478bd9Sstevel@tonic-gate 2177*7c478bd9Sstevel@tonic-gate /* 2178*7c478bd9Sstevel@tonic-gate * We initialize the counters to 1 rather than zero because 2179*7c478bd9Sstevel@tonic-gate * we have to count the "official" name as well as the aliases. 2180*7c478bd9Sstevel@tonic-gate */ 2181*7c478bd9Sstevel@tonic-gate for (hn = he->h_aliases, hosts = 1; hn && *hn; hn++, hosts++); 2182*7c478bd9Sstevel@tonic-gate if (se) 2183*7c478bd9Sstevel@tonic-gate for (sn = se->s_aliases, servs = 1; sn && *sn; sn++, servs++); 2184*7c478bd9Sstevel@tonic-gate else 2185*7c478bd9Sstevel@tonic-gate servs = 1; 2186*7c478bd9Sstevel@tonic-gate 2187*7c478bd9Sstevel@tonic-gate if ((hs = (struct nd_hostserv *)calloc(hosts * servs, 2188*7c478bd9Sstevel@tonic-gate sizeof (struct nd_hostserv))) == 0) { 2189*7c478bd9Sstevel@tonic-gate free((void *)result); 2190*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2191*7c478bd9Sstevel@tonic-gate } 2192*7c478bd9Sstevel@tonic-gate 2193*7c478bd9Sstevel@tonic-gate result->h_cnt = servs * hosts; 2194*7c478bd9Sstevel@tonic-gate result->h_hostservs = hs; 2195*7c478bd9Sstevel@tonic-gate 2196*7c478bd9Sstevel@tonic-gate for (i = 0, hn = he->h_aliases; i < hosts; i++) { 2197*7c478bd9Sstevel@tonic-gate sn = se ? se->s_aliases : NULL; 2198*7c478bd9Sstevel@tonic-gate 2199*7c478bd9Sstevel@tonic-gate for (j = 0; j < servs; j++) { 2200*7c478bd9Sstevel@tonic-gate if (i == 0) 2201*7c478bd9Sstevel@tonic-gate hs->h_host = strdup(he->h_name); 2202*7c478bd9Sstevel@tonic-gate else 2203*7c478bd9Sstevel@tonic-gate hs->h_host = strdup(*hn); 2204*7c478bd9Sstevel@tonic-gate if (j == 0) { 2205*7c478bd9Sstevel@tonic-gate if (se) 2206*7c478bd9Sstevel@tonic-gate hs->h_serv = strdup(se->s_name); 2207*7c478bd9Sstevel@tonic-gate else { 2208*7c478bd9Sstevel@tonic-gate /* Convert to a number string */ 2209*7c478bd9Sstevel@tonic-gate char stmp[16]; 2210*7c478bd9Sstevel@tonic-gate 2211*7c478bd9Sstevel@tonic-gate (void) sprintf(stmp, "%d", port); 2212*7c478bd9Sstevel@tonic-gate hs->h_serv = strdup(stmp); 2213*7c478bd9Sstevel@tonic-gate } 2214*7c478bd9Sstevel@tonic-gate } else 2215*7c478bd9Sstevel@tonic-gate hs->h_serv = strdup(*sn++); 2216*7c478bd9Sstevel@tonic-gate 2217*7c478bd9Sstevel@tonic-gate if ((hs->h_host == 0) || (hs->h_serv == 0)) { 2218*7c478bd9Sstevel@tonic-gate free((void *)result->h_hostservs); 2219*7c478bd9Sstevel@tonic-gate free((void *)result); 2220*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2221*7c478bd9Sstevel@tonic-gate } 2222*7c478bd9Sstevel@tonic-gate hs++; 2223*7c478bd9Sstevel@tonic-gate } 2224*7c478bd9Sstevel@tonic-gate if (i) 2225*7c478bd9Sstevel@tonic-gate hn++; 2226*7c478bd9Sstevel@tonic-gate } 2227*7c478bd9Sstevel@tonic-gate *(hslist) = result; 2228*7c478bd9Sstevel@tonic-gate return (ND_OK); 2229*7c478bd9Sstevel@tonic-gate } 2230*7c478bd9Sstevel@tonic-gate 2231*7c478bd9Sstevel@tonic-gate /* 2232*7c478bd9Sstevel@tonic-gate * Process results from nd_addrlist ( returned by netdir_getbyname) 2233*7c478bd9Sstevel@tonic-gate * into a hostent using buf. 2234*7c478bd9Sstevel@tonic-gate * *** ASSUMES that nd_addrlist->n_addrs->buf contains IP addresses in 2235*7c478bd9Sstevel@tonic-gate * sockaddr_in's *** 2236*7c478bd9Sstevel@tonic-gate */ 2237*7c478bd9Sstevel@tonic-gate int 2238*7c478bd9Sstevel@tonic-gate ndaddr2hent(int af, const char *nam, struct nd_addrlist *addrs, 2239*7c478bd9Sstevel@tonic-gate struct hostent *result, char *buffer, int buflen) 2240*7c478bd9Sstevel@tonic-gate { 2241*7c478bd9Sstevel@tonic-gate int i, count; 2242*7c478bd9Sstevel@tonic-gate struct in_addr *addrp; 2243*7c478bd9Sstevel@tonic-gate struct in6_addr *addr6p; 2244*7c478bd9Sstevel@tonic-gate char **addrvec; 2245*7c478bd9Sstevel@tonic-gate struct netbuf *na; 2246*7c478bd9Sstevel@tonic-gate size_t len; 2247*7c478bd9Sstevel@tonic-gate 2248*7c478bd9Sstevel@tonic-gate result->h_name = buffer; 2249*7c478bd9Sstevel@tonic-gate result->h_addrtype = af; 2250*7c478bd9Sstevel@tonic-gate result->h_length = (af == AF_INET) ? sizeof (*addrp): 2251*7c478bd9Sstevel@tonic-gate sizeof (*addr6p); 2252*7c478bd9Sstevel@tonic-gate 2253*7c478bd9Sstevel@tonic-gate /* 2254*7c478bd9Sstevel@tonic-gate * Build addrlist at start of buffer (after name); store the 2255*7c478bd9Sstevel@tonic-gate * addresses themselves at the end of the buffer. 2256*7c478bd9Sstevel@tonic-gate */ 2257*7c478bd9Sstevel@tonic-gate len = strlen(nam) + 1; 2258*7c478bd9Sstevel@tonic-gate addrvec = (char **)ROUND_UP(buffer + len, sizeof (*addrvec)); 2259*7c478bd9Sstevel@tonic-gate result->h_addr_list = addrvec; 2260*7c478bd9Sstevel@tonic-gate 2261*7c478bd9Sstevel@tonic-gate if (af == AF_INET) { 2262*7c478bd9Sstevel@tonic-gate addrp = (struct in_addr *)ROUND_DOWN(buffer + buflen, 2263*7c478bd9Sstevel@tonic-gate sizeof (*addrp)); 2264*7c478bd9Sstevel@tonic-gate 2265*7c478bd9Sstevel@tonic-gate count = addrs->n_cnt; 2266*7c478bd9Sstevel@tonic-gate if ((char *)(&addrvec[count + 1]) > (char *)(&addrp[-count])) 2267*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2268*7c478bd9Sstevel@tonic-gate 2269*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer, nam, len); 2270*7c478bd9Sstevel@tonic-gate 2271*7c478bd9Sstevel@tonic-gate for (na = addrs->n_addrs, i = 0; i < count; na++, i++) { 2272*7c478bd9Sstevel@tonic-gate --addrp; 2273*7c478bd9Sstevel@tonic-gate (void) memcpy(addrp, 2274*7c478bd9Sstevel@tonic-gate &((struct sockaddr_in *)na->buf)->sin_addr, 2275*7c478bd9Sstevel@tonic-gate sizeof (*addrp)); 2276*7c478bd9Sstevel@tonic-gate *addrvec++ = (char *)addrp; 2277*7c478bd9Sstevel@tonic-gate } 2278*7c478bd9Sstevel@tonic-gate } else { 2279*7c478bd9Sstevel@tonic-gate addr6p = (struct in6_addr *)ROUND_DOWN(buffer + buflen, 2280*7c478bd9Sstevel@tonic-gate sizeof (*addr6p)); 2281*7c478bd9Sstevel@tonic-gate 2282*7c478bd9Sstevel@tonic-gate count = addrs->n_cnt; 2283*7c478bd9Sstevel@tonic-gate if ((char *)(&addrvec[count + 1]) > (char *)(&addr6p[-count])) 2284*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2285*7c478bd9Sstevel@tonic-gate 2286*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer, nam, len); 2287*7c478bd9Sstevel@tonic-gate 2288*7c478bd9Sstevel@tonic-gate for (na = addrs->n_addrs, i = 0; i < count; na++, i++) { 2289*7c478bd9Sstevel@tonic-gate --addr6p; 2290*7c478bd9Sstevel@tonic-gate (void) memcpy(addr6p, 2291*7c478bd9Sstevel@tonic-gate &((struct sockaddr_in6 *)na->buf)->sin6_addr, 2292*7c478bd9Sstevel@tonic-gate sizeof (*addr6p)); 2293*7c478bd9Sstevel@tonic-gate *addrvec++ = (char *)addr6p; 2294*7c478bd9Sstevel@tonic-gate } 2295*7c478bd9Sstevel@tonic-gate } 2296*7c478bd9Sstevel@tonic-gate *addrvec = 0; 2297*7c478bd9Sstevel@tonic-gate result->h_aliases = addrvec; 2298*7c478bd9Sstevel@tonic-gate 2299*7c478bd9Sstevel@tonic-gate return (ND_OK); 2300*7c478bd9Sstevel@tonic-gate } 2301*7c478bd9Sstevel@tonic-gate 2302*7c478bd9Sstevel@tonic-gate /* 2303*7c478bd9Sstevel@tonic-gate * Process results from nd_addrlist ( returned by netdir_getbyname) 2304*7c478bd9Sstevel@tonic-gate * into a servent using buf. 2305*7c478bd9Sstevel@tonic-gate */ 2306*7c478bd9Sstevel@tonic-gate int 2307*7c478bd9Sstevel@tonic-gate ndaddr2srent(const char *name, const char *proto, ushort_t port, 2308*7c478bd9Sstevel@tonic-gate struct servent *result, char *buffer, int buflen) 2309*7c478bd9Sstevel@tonic-gate { 2310*7c478bd9Sstevel@tonic-gate size_t i; 2311*7c478bd9Sstevel@tonic-gate char *bufend = (buffer + buflen); 2312*7c478bd9Sstevel@tonic-gate 2313*7c478bd9Sstevel@tonic-gate result->s_port = (int)port; 2314*7c478bd9Sstevel@tonic-gate 2315*7c478bd9Sstevel@tonic-gate result->s_aliases = 2316*7c478bd9Sstevel@tonic-gate (char **)ROUND_UP(buffer, sizeof (char *)); 2317*7c478bd9Sstevel@tonic-gate result->s_aliases[0] = NULL; 2318*7c478bd9Sstevel@tonic-gate buffer = (char *)&result->s_aliases[1]; 2319*7c478bd9Sstevel@tonic-gate result->s_name = buffer; 2320*7c478bd9Sstevel@tonic-gate i = strlen(name) + 1; 2321*7c478bd9Sstevel@tonic-gate if ((buffer + i) > bufend) 2322*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2323*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer, name, i); 2324*7c478bd9Sstevel@tonic-gate buffer += i; 2325*7c478bd9Sstevel@tonic-gate 2326*7c478bd9Sstevel@tonic-gate result->s_proto = buffer; 2327*7c478bd9Sstevel@tonic-gate i = strlen(proto) + 1; 2328*7c478bd9Sstevel@tonic-gate if ((buffer + i) > bufend) 2329*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2330*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer, proto, i); 2331*7c478bd9Sstevel@tonic-gate buffer += i; 2332*7c478bd9Sstevel@tonic-gate 2333*7c478bd9Sstevel@tonic-gate return (ND_OK); 2334*7c478bd9Sstevel@tonic-gate } 2335*7c478bd9Sstevel@tonic-gate 2336*7c478bd9Sstevel@tonic-gate /* 2337*7c478bd9Sstevel@tonic-gate * Process results from nd_hostservlist ( returned by netdir_getbyaddr) 2338*7c478bd9Sstevel@tonic-gate * into a hostent using buf. 2339*7c478bd9Sstevel@tonic-gate * *** ASSUMES that nd_buf->buf is a sockaddr_in *** 2340*7c478bd9Sstevel@tonic-gate */ 2341*7c478bd9Sstevel@tonic-gate int 2342*7c478bd9Sstevel@tonic-gate ndhostserv2hent(struct netbuf *nbuf, struct nd_hostservlist *addrs, 2343*7c478bd9Sstevel@tonic-gate struct hostent *result, char *buffer, int buflen) 2344*7c478bd9Sstevel@tonic-gate { 2345*7c478bd9Sstevel@tonic-gate int i, count; 2346*7c478bd9Sstevel@tonic-gate char *aliasp; 2347*7c478bd9Sstevel@tonic-gate char **aliasvec; 2348*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sa; 2349*7c478bd9Sstevel@tonic-gate struct nd_hostserv *hs; 2350*7c478bd9Sstevel@tonic-gate const char *la; 2351*7c478bd9Sstevel@tonic-gate size_t length; 2352*7c478bd9Sstevel@tonic-gate 2353*7c478bd9Sstevel@tonic-gate /* First, give the lonely address a specious home in h_addr_list. */ 2354*7c478bd9Sstevel@tonic-gate aliasp = (char *)ROUND_UP(buffer, sizeof (sa->sin_addr)); 2355*7c478bd9Sstevel@tonic-gate sa = (struct sockaddr_in *)nbuf->buf; 2356*7c478bd9Sstevel@tonic-gate (void) memcpy(aliasp, (char *)&(sa->sin_addr), sizeof (sa->sin_addr)); 2357*7c478bd9Sstevel@tonic-gate aliasvec = (char **)ROUND_UP(aliasp + sizeof (sa->sin_addr), 2358*7c478bd9Sstevel@tonic-gate sizeof (*aliasvec)); 2359*7c478bd9Sstevel@tonic-gate result->h_addr_list = aliasvec; 2360*7c478bd9Sstevel@tonic-gate *aliasvec++ = aliasp; 2361*7c478bd9Sstevel@tonic-gate *aliasvec++ = 0; 2362*7c478bd9Sstevel@tonic-gate 2363*7c478bd9Sstevel@tonic-gate /* 2364*7c478bd9Sstevel@tonic-gate * Build h_aliases at start of buffer (after addr and h_addr_list); 2365*7c478bd9Sstevel@tonic-gate * store the alias strings at the end of the buffer (before h_name). 2366*7c478bd9Sstevel@tonic-gate */ 2367*7c478bd9Sstevel@tonic-gate 2368*7c478bd9Sstevel@tonic-gate aliasp = buffer + buflen; 2369*7c478bd9Sstevel@tonic-gate 2370*7c478bd9Sstevel@tonic-gate result->h_aliases = aliasvec; 2371*7c478bd9Sstevel@tonic-gate 2372*7c478bd9Sstevel@tonic-gate hs = addrs->h_hostservs; 2373*7c478bd9Sstevel@tonic-gate if (! hs) 2374*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 2375*7c478bd9Sstevel@tonic-gate 2376*7c478bd9Sstevel@tonic-gate length = strlen(hs->h_host) + 1; 2377*7c478bd9Sstevel@tonic-gate aliasp -= length; 2378*7c478bd9Sstevel@tonic-gate if ((char *)(&aliasvec[1]) > aliasp) 2379*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2380*7c478bd9Sstevel@tonic-gate (void) memcpy(aliasp, hs->h_host, length); 2381*7c478bd9Sstevel@tonic-gate 2382*7c478bd9Sstevel@tonic-gate result->h_name = aliasp; 2383*7c478bd9Sstevel@tonic-gate result->h_addrtype = AF_INET; 2384*7c478bd9Sstevel@tonic-gate result->h_length = sizeof (sa->sin_addr); 2385*7c478bd9Sstevel@tonic-gate 2386*7c478bd9Sstevel@tonic-gate /* 2387*7c478bd9Sstevel@tonic-gate * Assumption: the netdir nametoaddr_libs 2388*7c478bd9Sstevel@tonic-gate * sort the vector of (host, serv) pairs in such a way that 2389*7c478bd9Sstevel@tonic-gate * all pairs with the same host name are contiguous. 2390*7c478bd9Sstevel@tonic-gate */ 2391*7c478bd9Sstevel@tonic-gate la = hs->h_host; 2392*7c478bd9Sstevel@tonic-gate count = addrs->h_cnt; 2393*7c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++, hs++) 2394*7c478bd9Sstevel@tonic-gate if (strcmp(la, hs->h_host) != 0) { 2395*7c478bd9Sstevel@tonic-gate size_t len = strlen(hs->h_host) + 1; 2396*7c478bd9Sstevel@tonic-gate 2397*7c478bd9Sstevel@tonic-gate aliasp -= len; 2398*7c478bd9Sstevel@tonic-gate if ((char *)(&aliasvec[2]) > aliasp) 2399*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2400*7c478bd9Sstevel@tonic-gate (void) memcpy(aliasp, hs->h_host, len); 2401*7c478bd9Sstevel@tonic-gate *aliasvec++ = aliasp; 2402*7c478bd9Sstevel@tonic-gate la = hs->h_host; 2403*7c478bd9Sstevel@tonic-gate } 2404*7c478bd9Sstevel@tonic-gate *aliasvec = 0; 2405*7c478bd9Sstevel@tonic-gate 2406*7c478bd9Sstevel@tonic-gate return (ND_OK); 2407*7c478bd9Sstevel@tonic-gate } 2408*7c478bd9Sstevel@tonic-gate 2409*7c478bd9Sstevel@tonic-gate /* 2410*7c478bd9Sstevel@tonic-gate * Process results from nd_hostservlist ( returned by netdir_getbyaddr) 2411*7c478bd9Sstevel@tonic-gate * into a servent using buf. 2412*7c478bd9Sstevel@tonic-gate */ 2413*7c478bd9Sstevel@tonic-gate int 2414*7c478bd9Sstevel@tonic-gate ndhostserv2srent(int port, const char *proto, struct nd_hostservlist *addrs, 2415*7c478bd9Sstevel@tonic-gate struct servent *result, char *buffer, int buflen) 2416*7c478bd9Sstevel@tonic-gate { 2417*7c478bd9Sstevel@tonic-gate int i, count; 2418*7c478bd9Sstevel@tonic-gate char *aliasp; 2419*7c478bd9Sstevel@tonic-gate char **aliasvec; 2420*7c478bd9Sstevel@tonic-gate struct nd_hostserv *hs; 2421*7c478bd9Sstevel@tonic-gate const char *host_cname; 2422*7c478bd9Sstevel@tonic-gate size_t leni, lenj; 2423*7c478bd9Sstevel@tonic-gate 2424*7c478bd9Sstevel@tonic-gate result->s_port = port; 2425*7c478bd9Sstevel@tonic-gate /* 2426*7c478bd9Sstevel@tonic-gate * Build s_aliases at start of buffer; 2427*7c478bd9Sstevel@tonic-gate * store proto and aliases at the end of the buffer (before h_name). 2428*7c478bd9Sstevel@tonic-gate */ 2429*7c478bd9Sstevel@tonic-gate 2430*7c478bd9Sstevel@tonic-gate aliasp = buffer + buflen; 2431*7c478bd9Sstevel@tonic-gate aliasvec = (char **)ROUND_UP(buffer, sizeof (char *)); 2432*7c478bd9Sstevel@tonic-gate 2433*7c478bd9Sstevel@tonic-gate result->s_aliases = aliasvec; 2434*7c478bd9Sstevel@tonic-gate 2435*7c478bd9Sstevel@tonic-gate hs = addrs->h_hostservs; 2436*7c478bd9Sstevel@tonic-gate if (! hs) 2437*7c478bd9Sstevel@tonic-gate return (ND_NOHOST); 2438*7c478bd9Sstevel@tonic-gate host_cname = hs->h_host; 2439*7c478bd9Sstevel@tonic-gate 2440*7c478bd9Sstevel@tonic-gate leni = strlen(proto) + 1; 2441*7c478bd9Sstevel@tonic-gate lenj = strlen(hs->h_serv) + 1; 2442*7c478bd9Sstevel@tonic-gate if ((char *)(&aliasvec[2]) > (aliasp - leni - lenj)) 2443*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2444*7c478bd9Sstevel@tonic-gate 2445*7c478bd9Sstevel@tonic-gate aliasp -= leni; 2446*7c478bd9Sstevel@tonic-gate (void) memcpy(aliasp, proto, leni); 2447*7c478bd9Sstevel@tonic-gate result->s_proto = aliasp; 2448*7c478bd9Sstevel@tonic-gate 2449*7c478bd9Sstevel@tonic-gate aliasp -= lenj; 2450*7c478bd9Sstevel@tonic-gate (void) memcpy(aliasp, hs->h_serv, lenj); 2451*7c478bd9Sstevel@tonic-gate result->s_name = aliasp; 2452*7c478bd9Sstevel@tonic-gate 2453*7c478bd9Sstevel@tonic-gate /* 2454*7c478bd9Sstevel@tonic-gate * Assumption: the netdir nametoaddr_libs 2455*7c478bd9Sstevel@tonic-gate * do a host aliases first and serv aliases next 2456*7c478bd9Sstevel@tonic-gate * enumeration for creating the list of hostserv 2457*7c478bd9Sstevel@tonic-gate * structures. 2458*7c478bd9Sstevel@tonic-gate */ 2459*7c478bd9Sstevel@tonic-gate count = addrs->h_cnt; 2460*7c478bd9Sstevel@tonic-gate for (i = 0; 2461*7c478bd9Sstevel@tonic-gate i < count && hs->h_serv && strcmp(hs->h_host, host_cname) == 0; 2462*7c478bd9Sstevel@tonic-gate i++, hs++) { 2463*7c478bd9Sstevel@tonic-gate size_t len = strlen(hs->h_serv) + 1; 2464*7c478bd9Sstevel@tonic-gate 2465*7c478bd9Sstevel@tonic-gate aliasp -= len; 2466*7c478bd9Sstevel@tonic-gate if ((char *)(&aliasvec[2]) > aliasp) 2467*7c478bd9Sstevel@tonic-gate return (ND_NOMEM); 2468*7c478bd9Sstevel@tonic-gate (void) memcpy(aliasp, hs->h_serv, len); 2469*7c478bd9Sstevel@tonic-gate *aliasvec++ = aliasp; 2470*7c478bd9Sstevel@tonic-gate } 2471*7c478bd9Sstevel@tonic-gate *aliasvec = NULL; 2472*7c478bd9Sstevel@tonic-gate 2473*7c478bd9Sstevel@tonic-gate return (ND_OK); 2474*7c478bd9Sstevel@tonic-gate } 2475*7c478bd9Sstevel@tonic-gate 2476*7c478bd9Sstevel@tonic-gate 2477*7c478bd9Sstevel@tonic-gate static int 2478*7c478bd9Sstevel@tonic-gate nd2herrno(int nerr) 2479*7c478bd9Sstevel@tonic-gate { 2480*7c478bd9Sstevel@tonic-gate trace1(TR_nd2herrno, 0); 2481*7c478bd9Sstevel@tonic-gate switch (nerr) { 2482*7c478bd9Sstevel@tonic-gate case ND_OK: 2483*7c478bd9Sstevel@tonic-gate trace1(TR_nd2herrno, 1); 2484*7c478bd9Sstevel@tonic-gate return (0); 2485*7c478bd9Sstevel@tonic-gate case ND_TRY_AGAIN: 2486*7c478bd9Sstevel@tonic-gate trace1(TR_nd2herrno, 1); 2487*7c478bd9Sstevel@tonic-gate return (TRY_AGAIN); 2488*7c478bd9Sstevel@tonic-gate case ND_NO_RECOVERY: 2489*7c478bd9Sstevel@tonic-gate case ND_BADARG: 2490*7c478bd9Sstevel@tonic-gate case ND_NOMEM: 2491*7c478bd9Sstevel@tonic-gate trace1(TR_nd2herrno, 1); 2492*7c478bd9Sstevel@tonic-gate return (NO_RECOVERY); 2493*7c478bd9Sstevel@tonic-gate case ND_NO_DATA: 2494*7c478bd9Sstevel@tonic-gate trace1(TR_nd2herrno, 1); 2495*7c478bd9Sstevel@tonic-gate return (NO_DATA); 2496*7c478bd9Sstevel@tonic-gate case ND_NOHOST: 2497*7c478bd9Sstevel@tonic-gate case ND_NOSERV: 2498*7c478bd9Sstevel@tonic-gate trace1(TR_nd2herrno, 1); 2499*7c478bd9Sstevel@tonic-gate return (HOST_NOT_FOUND); 2500*7c478bd9Sstevel@tonic-gate default: 2501*7c478bd9Sstevel@tonic-gate trace1(TR_nd2herrno, 1); 2502*7c478bd9Sstevel@tonic-gate return (NO_RECOVERY); 2503*7c478bd9Sstevel@tonic-gate } 2504*7c478bd9Sstevel@tonic-gate } 2505*7c478bd9Sstevel@tonic-gate 2506*7c478bd9Sstevel@tonic-gate /* 2507*7c478bd9Sstevel@tonic-gate * This is a utility function so that various parts of libnsl can 2508*7c478bd9Sstevel@tonic-gate * easily send ioctls down to ip. 2509*7c478bd9Sstevel@tonic-gate * 2510*7c478bd9Sstevel@tonic-gate */ 2511*7c478bd9Sstevel@tonic-gate int 2512*7c478bd9Sstevel@tonic-gate nss_ioctl(int af, int cmd, void *arg) 2513*7c478bd9Sstevel@tonic-gate { 2514*7c478bd9Sstevel@tonic-gate int fd; 2515*7c478bd9Sstevel@tonic-gate char *devpath; 2516*7c478bd9Sstevel@tonic-gate int retv; 2517*7c478bd9Sstevel@tonic-gate 2518*7c478bd9Sstevel@tonic-gate switch (af) { 2519*7c478bd9Sstevel@tonic-gate case AF_INET6: 2520*7c478bd9Sstevel@tonic-gate devpath = UDP6DEV; 2521*7c478bd9Sstevel@tonic-gate break; 2522*7c478bd9Sstevel@tonic-gate case AF_INET: 2523*7c478bd9Sstevel@tonic-gate case AF_UNSPEC: 2524*7c478bd9Sstevel@tonic-gate default: 2525*7c478bd9Sstevel@tonic-gate devpath = UDPDEV; 2526*7c478bd9Sstevel@tonic-gate } 2527*7c478bd9Sstevel@tonic-gate if ((fd = open(devpath, O_RDONLY)) < 0) { 2528*7c478bd9Sstevel@tonic-gate return (-1); 2529*7c478bd9Sstevel@tonic-gate } 2530*7c478bd9Sstevel@tonic-gate while ((retv = ioctl(fd, cmd, arg)) == -1) { 2531*7c478bd9Sstevel@tonic-gate if (errno != EINTR) 2532*7c478bd9Sstevel@tonic-gate break; 2533*7c478bd9Sstevel@tonic-gate } 2534*7c478bd9Sstevel@tonic-gate close(fd); 2535*7c478bd9Sstevel@tonic-gate return (retv); 2536*7c478bd9Sstevel@tonic-gate } 2537*7c478bd9Sstevel@tonic-gate 2538*7c478bd9Sstevel@tonic-gate static int 2539*7c478bd9Sstevel@tonic-gate nss_strioctl(int af, int cmd, void *ptr, int ilen) 2540*7c478bd9Sstevel@tonic-gate { 2541*7c478bd9Sstevel@tonic-gate struct strioctl str; 2542*7c478bd9Sstevel@tonic-gate 2543*7c478bd9Sstevel@tonic-gate str.ic_cmd = cmd; 2544*7c478bd9Sstevel@tonic-gate str.ic_timout = 0; 2545*7c478bd9Sstevel@tonic-gate str.ic_len = ilen; 2546*7c478bd9Sstevel@tonic-gate str.ic_dp = ptr; 2547*7c478bd9Sstevel@tonic-gate 2548*7c478bd9Sstevel@tonic-gate return (nss_ioctl(af, I_STR, &str)); 2549*7c478bd9Sstevel@tonic-gate } 2550*7c478bd9Sstevel@tonic-gate 2551*7c478bd9Sstevel@tonic-gate static struct ifinfo * 2552*7c478bd9Sstevel@tonic-gate get_local_info(void) 2553*7c478bd9Sstevel@tonic-gate { 2554*7c478bd9Sstevel@tonic-gate int numifs; 2555*7c478bd9Sstevel@tonic-gate int n; 2556*7c478bd9Sstevel@tonic-gate char *buf = NULL; 2557*7c478bd9Sstevel@tonic-gate size_t needed; 2558*7c478bd9Sstevel@tonic-gate struct lifconf lifc; 2559*7c478bd9Sstevel@tonic-gate struct lifreq lifreq, *lifr; 2560*7c478bd9Sstevel@tonic-gate struct lifnum lifn; 2561*7c478bd9Sstevel@tonic-gate struct ifinfo *localinfo; 2562*7c478bd9Sstevel@tonic-gate 2563*7c478bd9Sstevel@tonic-gate lifn.lifn_family = AF_UNSPEC; 2564*7c478bd9Sstevel@tonic-gate lifn.lifn_flags = 0; 2565*7c478bd9Sstevel@tonic-gate 2566*7c478bd9Sstevel@tonic-gate getifnum: 2567*7c478bd9Sstevel@tonic-gate if (nss_ioctl(AF_UNSPEC, SIOCGLIFNUM, &lifn) == -1) { 2568*7c478bd9Sstevel@tonic-gate numifs = MAXIFS; 2569*7c478bd9Sstevel@tonic-gate } else { 2570*7c478bd9Sstevel@tonic-gate numifs = lifn.lifn_count; 2571*7c478bd9Sstevel@tonic-gate } 2572*7c478bd9Sstevel@tonic-gate 2573*7c478bd9Sstevel@tonic-gate /* 2574*7c478bd9Sstevel@tonic-gate * Add a small fudge factor in case interfaces get plumbed between 2575*7c478bd9Sstevel@tonic-gate * the call to SIOCGLIFNUM and SIOCGLIFCONF. 2576*7c478bd9Sstevel@tonic-gate */ 2577*7c478bd9Sstevel@tonic-gate needed = (numifs + 4) * sizeof (lifreq); 2578*7c478bd9Sstevel@tonic-gate if (buf == NULL) 2579*7c478bd9Sstevel@tonic-gate buf = malloc(needed); 2580*7c478bd9Sstevel@tonic-gate else 2581*7c478bd9Sstevel@tonic-gate buf = realloc(buf, needed); 2582*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 2583*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "n2a get_local_info: malloc failed: %m"); 2584*7c478bd9Sstevel@tonic-gate _nderror = ND_NOMEM; 2585*7c478bd9Sstevel@tonic-gate return (NULL); 2586*7c478bd9Sstevel@tonic-gate } 2587*7c478bd9Sstevel@tonic-gate lifc.lifc_family = AF_UNSPEC; 2588*7c478bd9Sstevel@tonic-gate lifc.lifc_flags = 0; 2589*7c478bd9Sstevel@tonic-gate lifc.lifc_len = needed; 2590*7c478bd9Sstevel@tonic-gate lifc.lifc_buf = buf; 2591*7c478bd9Sstevel@tonic-gate if (nss_ioctl(AF_UNSPEC, SIOCGLIFCONF, &lifc) == -1) { 2592*7c478bd9Sstevel@tonic-gate /* 2593*7c478bd9Sstevel@tonic-gate * IP returns EINVAL if the buffer was too small to fit 2594*7c478bd9Sstevel@tonic-gate * all of the entries. If that's the case, go back and 2595*7c478bd9Sstevel@tonic-gate * try again. 2596*7c478bd9Sstevel@tonic-gate */ 2597*7c478bd9Sstevel@tonic-gate if (errno == EINVAL) 2598*7c478bd9Sstevel@tonic-gate goto getifnum; 2599*7c478bd9Sstevel@tonic-gate 2600*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "n2a get_local_info: " 2601*7c478bd9Sstevel@tonic-gate "ioctl (get interface configuration): %m"); 2602*7c478bd9Sstevel@tonic-gate free(buf); 2603*7c478bd9Sstevel@tonic-gate _nderror = ND_SYSTEM; 2604*7c478bd9Sstevel@tonic-gate return (NULL); 2605*7c478bd9Sstevel@tonic-gate } 2606*7c478bd9Sstevel@tonic-gate lifr = (struct lifreq *)buf; 2607*7c478bd9Sstevel@tonic-gate numifs = lifc.lifc_len/sizeof (lifreq); 2608*7c478bd9Sstevel@tonic-gate localinfo = (struct ifinfo *)malloc(ifinfosize(numifs)); 2609*7c478bd9Sstevel@tonic-gate if (localinfo == NULL) { 2610*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "n2a get_local_info: malloc failed: %m"); 2611*7c478bd9Sstevel@tonic-gate free(buf); 2612*7c478bd9Sstevel@tonic-gate _nderror = ND_SYSTEM; 2613*7c478bd9Sstevel@tonic-gate return (NULL); 2614*7c478bd9Sstevel@tonic-gate } 2615*7c478bd9Sstevel@tonic-gate 2616*7c478bd9Sstevel@tonic-gate localinfo->addresses = (struct __ifaddr *) 2617*7c478bd9Sstevel@tonic-gate ((char *)localinfo + sizeof (struct ifinfo)); 2618*7c478bd9Sstevel@tonic-gate 2619*7c478bd9Sstevel@tonic-gate for (localinfo->count = 0, n = numifs; n > 0; n--, lifr++) { 2620*7c478bd9Sstevel@tonic-gate int af; 2621*7c478bd9Sstevel@tonic-gate 2622*7c478bd9Sstevel@tonic-gate lifreq = *lifr; 2623*7c478bd9Sstevel@tonic-gate af = lifreq.lifr_addr.ss_family; 2624*7c478bd9Sstevel@tonic-gate 2625*7c478bd9Sstevel@tonic-gate /* Squirrel away the address */ 2626*7c478bd9Sstevel@tonic-gate if (ifassign(lifreq, localinfo->count, IF_ADDR) == 0) 2627*7c478bd9Sstevel@tonic-gate continue; 2628*7c478bd9Sstevel@tonic-gate 2629*7c478bd9Sstevel@tonic-gate if (nss_ioctl(af, SIOCGLIFFLAGS, &lifreq) < 0) { 2630*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, 2631*7c478bd9Sstevel@tonic-gate "n2a get_local_info: " 2632*7c478bd9Sstevel@tonic-gate "ioctl (get interface flags): %m"); 2633*7c478bd9Sstevel@tonic-gate continue; 2634*7c478bd9Sstevel@tonic-gate } 2635*7c478bd9Sstevel@tonic-gate if (!(lifreq.lifr_flags & IFF_UP)) 2636*7c478bd9Sstevel@tonic-gate continue; 2637*7c478bd9Sstevel@tonic-gate 2638*7c478bd9Sstevel@tonic-gate if (nss_ioctl(af, SIOCGLIFNETMASK, &lifreq) < 0) { 2639*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, 2640*7c478bd9Sstevel@tonic-gate "n2a get_local_info: " 2641*7c478bd9Sstevel@tonic-gate "ioctl (get interface netmask): %m"); 2642*7c478bd9Sstevel@tonic-gate continue; 2643*7c478bd9Sstevel@tonic-gate } 2644*7c478bd9Sstevel@tonic-gate 2645*7c478bd9Sstevel@tonic-gate if (ifassign(lifreq, localinfo->count, IF_MASK) == 0) 2646*7c478bd9Sstevel@tonic-gate continue; 2647*7c478bd9Sstevel@tonic-gate 2648*7c478bd9Sstevel@tonic-gate localinfo->count++; 2649*7c478bd9Sstevel@tonic-gate } 2650*7c478bd9Sstevel@tonic-gate 2651*7c478bd9Sstevel@tonic-gate free(buf); 2652*7c478bd9Sstevel@tonic-gate return (localinfo); 2653*7c478bd9Sstevel@tonic-gate } 2654*7c478bd9Sstevel@tonic-gate 2655*7c478bd9Sstevel@tonic-gate static int 2656*7c478bd9Sstevel@tonic-gate __inet_ifassign(sa_family_t af, struct __ifaddr *ifa, __ifaddr_type type, 2657*7c478bd9Sstevel@tonic-gate void *addr) { 2658*7c478bd9Sstevel@tonic-gate switch (type) { 2659*7c478bd9Sstevel@tonic-gate case IF_ADDR: 2660*7c478bd9Sstevel@tonic-gate ifa->af = af; 2661*7c478bd9Sstevel@tonic-gate if (af == AF_INET6) { 2662*7c478bd9Sstevel@tonic-gate ifa->addr.in6 = *(struct in6_addr *)addr; 2663*7c478bd9Sstevel@tonic-gate } else { 2664*7c478bd9Sstevel@tonic-gate ifa->addr.in4 = *(struct in_addr *)addr; 2665*7c478bd9Sstevel@tonic-gate } 2666*7c478bd9Sstevel@tonic-gate break; 2667*7c478bd9Sstevel@tonic-gate case IF_MASK: 2668*7c478bd9Sstevel@tonic-gate if (ifa->af == af) { 2669*7c478bd9Sstevel@tonic-gate if (af == AF_INET6) { 2670*7c478bd9Sstevel@tonic-gate ifa->mask.in6 = *(struct in6_addr *)addr; 2671*7c478bd9Sstevel@tonic-gate } else { 2672*7c478bd9Sstevel@tonic-gate ifa->mask.in4 = *(struct in_addr *)addr; 2673*7c478bd9Sstevel@tonic-gate } 2674*7c478bd9Sstevel@tonic-gate } else { 2675*7c478bd9Sstevel@tonic-gate return (0); 2676*7c478bd9Sstevel@tonic-gate } 2677*7c478bd9Sstevel@tonic-gate break; 2678*7c478bd9Sstevel@tonic-gate default: 2679*7c478bd9Sstevel@tonic-gate return (0); 2680*7c478bd9Sstevel@tonic-gate } 2681*7c478bd9Sstevel@tonic-gate 2682*7c478bd9Sstevel@tonic-gate return (1); 2683*7c478bd9Sstevel@tonic-gate } 2684*7c478bd9Sstevel@tonic-gate 2685*7c478bd9Sstevel@tonic-gate static int 2686*7c478bd9Sstevel@tonic-gate islocal(struct ifinfo *localinfo, struct in_addr addr) 2687*7c478bd9Sstevel@tonic-gate { 2688*7c478bd9Sstevel@tonic-gate int i; 2689*7c478bd9Sstevel@tonic-gate 2690*7c478bd9Sstevel@tonic-gate if (!localinfo) 2691*7c478bd9Sstevel@tonic-gate return (0); 2692*7c478bd9Sstevel@tonic-gate 2693*7c478bd9Sstevel@tonic-gate for (i = 0; i < localinfo->count; i++) { 2694*7c478bd9Sstevel@tonic-gate if (ifaf(i) == AF_INET && 2695*7c478bd9Sstevel@tonic-gate ((addr.s_addr & ifmask4(i).s_addr) == 2696*7c478bd9Sstevel@tonic-gate (ifaddr4(i).s_addr & ifmask4(i).s_addr))) 2697*7c478bd9Sstevel@tonic-gate return (1); 2698*7c478bd9Sstevel@tonic-gate } 2699*7c478bd9Sstevel@tonic-gate return (0); 2700*7c478bd9Sstevel@tonic-gate } 2701*7c478bd9Sstevel@tonic-gate 2702*7c478bd9Sstevel@tonic-gate /* 2703*7c478bd9Sstevel@tonic-gate * Some higher-level routines for determining if an address is 2704*7c478bd9Sstevel@tonic-gate * on a local network. 2705*7c478bd9Sstevel@tonic-gate * 2706*7c478bd9Sstevel@tonic-gate * __inet_get_local_interfaces() - get an opaque handle with 2707*7c478bd9Sstevel@tonic-gate * with a list of local interfaces 2708*7c478bd9Sstevel@tonic-gate * __inet_address_is_local() - return 1 if an address is 2709*7c478bd9Sstevel@tonic-gate * on a local network; 0 otherwise 2710*7c478bd9Sstevel@tonic-gate * __inet_free_local_interfaces() - free handle that was 2711*7c478bd9Sstevel@tonic-gate * returned by __inet_get_local_interfaces() 2712*7c478bd9Sstevel@tonic-gate * 2713*7c478bd9Sstevel@tonic-gate * A typical calling sequence is: 2714*7c478bd9Sstevel@tonic-gate * 2715*7c478bd9Sstevel@tonic-gate * p = __inet_get_local_interfaces(); 2716*7c478bd9Sstevel@tonic-gate * if (__inet_address_is_local(p, inaddr)) { 2717*7c478bd9Sstevel@tonic-gate * ... 2718*7c478bd9Sstevel@tonic-gate * } 2719*7c478bd9Sstevel@tonic-gate * __inet_free_local_interfaces(p); 2720*7c478bd9Sstevel@tonic-gate */ 2721*7c478bd9Sstevel@tonic-gate 2722*7c478bd9Sstevel@tonic-gate /* 2723*7c478bd9Sstevel@tonic-gate * Return an opaque pointer to a list of configured interfaces. 2724*7c478bd9Sstevel@tonic-gate */ 2725*7c478bd9Sstevel@tonic-gate void * 2726*7c478bd9Sstevel@tonic-gate __inet_get_local_interfaces(void) 2727*7c478bd9Sstevel@tonic-gate { 2728*7c478bd9Sstevel@tonic-gate return (get_local_info()); 2729*7c478bd9Sstevel@tonic-gate } 2730*7c478bd9Sstevel@tonic-gate 2731*7c478bd9Sstevel@tonic-gate /* 2732*7c478bd9Sstevel@tonic-gate * Free memory allocated by inet_local_interfaces(). 2733*7c478bd9Sstevel@tonic-gate */ 2734*7c478bd9Sstevel@tonic-gate void 2735*7c478bd9Sstevel@tonic-gate __inet_free_local_interfaces(void *p) 2736*7c478bd9Sstevel@tonic-gate { 2737*7c478bd9Sstevel@tonic-gate free(p); 2738*7c478bd9Sstevel@tonic-gate } 2739*7c478bd9Sstevel@tonic-gate 2740*7c478bd9Sstevel@tonic-gate /* 2741*7c478bd9Sstevel@tonic-gate * Determine if an address is on a local network. 2742*7c478bd9Sstevel@tonic-gate * 2743*7c478bd9Sstevel@tonic-gate * Might have made sense to use SIOCTONLINK, except that it doesn't 2744*7c478bd9Sstevel@tonic-gate * handle matching on IPv4 network addresses. 2745*7c478bd9Sstevel@tonic-gate */ 2746*7c478bd9Sstevel@tonic-gate int 2747*7c478bd9Sstevel@tonic-gate __inet_address_is_local_af(void *p, sa_family_t af, void *addr) { 2748*7c478bd9Sstevel@tonic-gate 2749*7c478bd9Sstevel@tonic-gate struct ifinfo *localinfo = (struct ifinfo *)p; 2750*7c478bd9Sstevel@tonic-gate int i, a; 2751*7c478bd9Sstevel@tonic-gate struct in_addr v4addr; 2752*7c478bd9Sstevel@tonic-gate 2753*7c478bd9Sstevel@tonic-gate if (localinfo == 0) 2754*7c478bd9Sstevel@tonic-gate return (0); 2755*7c478bd9Sstevel@tonic-gate 2756*7c478bd9Sstevel@tonic-gate if (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr)) { 2757*7c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR((struct in6_addr *)addr, &v4addr); 2758*7c478bd9Sstevel@tonic-gate af = AF_INET; 2759*7c478bd9Sstevel@tonic-gate addr = (void *)&v4addr; 2760*7c478bd9Sstevel@tonic-gate } 2761*7c478bd9Sstevel@tonic-gate 2762*7c478bd9Sstevel@tonic-gate for (i = 0; i < localinfo->count; i++) { 2763*7c478bd9Sstevel@tonic-gate if (ifaf(i) == af) { 2764*7c478bd9Sstevel@tonic-gate if (af == AF_INET6) { 2765*7c478bd9Sstevel@tonic-gate struct in6_addr *a6 = (struct in6_addr *)addr; 2766*7c478bd9Sstevel@tonic-gate for (a = 0; a < sizeof (a6->s6_addr); a++) { 2767*7c478bd9Sstevel@tonic-gate if ((a6->s6_addr[a] & 2768*7c478bd9Sstevel@tonic-gate ifmask6(i).s6_addr[a]) != 2769*7c478bd9Sstevel@tonic-gate (ifaddr6(i).s6_addr[a] & 2770*7c478bd9Sstevel@tonic-gate ifmask6(i).s6_addr[a])) 2771*7c478bd9Sstevel@tonic-gate break; 2772*7c478bd9Sstevel@tonic-gate } 2773*7c478bd9Sstevel@tonic-gate if (a >= sizeof (a6->s6_addr)) 2774*7c478bd9Sstevel@tonic-gate return (1); 2775*7c478bd9Sstevel@tonic-gate } else { 2776*7c478bd9Sstevel@tonic-gate if ((((struct in_addr *)addr)->s_addr & 2777*7c478bd9Sstevel@tonic-gate ifmask4(i).s_addr) == 2778*7c478bd9Sstevel@tonic-gate (ifaddr4(i).s_addr & 2779*7c478bd9Sstevel@tonic-gate ifmask4(i).s_addr)) 2780*7c478bd9Sstevel@tonic-gate return (1); 2781*7c478bd9Sstevel@tonic-gate } 2782*7c478bd9Sstevel@tonic-gate } 2783*7c478bd9Sstevel@tonic-gate } 2784*7c478bd9Sstevel@tonic-gate 2785*7c478bd9Sstevel@tonic-gate return (0); 2786*7c478bd9Sstevel@tonic-gate } 2787*7c478bd9Sstevel@tonic-gate 2788*7c478bd9Sstevel@tonic-gate int 2789*7c478bd9Sstevel@tonic-gate __inet_address_is_local(void *p, struct in_addr addr) 2790*7c478bd9Sstevel@tonic-gate { 2791*7c478bd9Sstevel@tonic-gate return (__inet_address_is_local_af(p, AF_INET, &addr)); 2792*7c478bd9Sstevel@tonic-gate } 2793*7c478bd9Sstevel@tonic-gate 2794*7c478bd9Sstevel@tonic-gate int 2795*7c478bd9Sstevel@tonic-gate __inet_uaddr_is_local(void *p, struct netconfig *nc, char *uaddr) 2796*7c478bd9Sstevel@tonic-gate { 2797*7c478bd9Sstevel@tonic-gate struct netbuf *taddr; 2798*7c478bd9Sstevel@tonic-gate sa_family_t af; 2799*7c478bd9Sstevel@tonic-gate int ret; 2800*7c478bd9Sstevel@tonic-gate 2801*7c478bd9Sstevel@tonic-gate taddr = uaddr2taddr(nc, uaddr); 2802*7c478bd9Sstevel@tonic-gate if (taddr == 0) 2803*7c478bd9Sstevel@tonic-gate return (0); 2804*7c478bd9Sstevel@tonic-gate 2805*7c478bd9Sstevel@tonic-gate af = ((struct sockaddr *)taddr->buf)->sa_family; 2806*7c478bd9Sstevel@tonic-gate 2807*7c478bd9Sstevel@tonic-gate ret = __inet_address_is_local_af(p, af, 2808*7c478bd9Sstevel@tonic-gate (af == AF_INET6) ? 2809*7c478bd9Sstevel@tonic-gate (void *)&((struct sockaddr_in6 *)taddr->buf)->sin6_addr : 2810*7c478bd9Sstevel@tonic-gate (void *)&((struct sockaddr_in *)taddr->buf)->sin_addr); 2811*7c478bd9Sstevel@tonic-gate 2812*7c478bd9Sstevel@tonic-gate netdir_free(taddr, ND_ADDR); 2813*7c478bd9Sstevel@tonic-gate return (ret); 2814*7c478bd9Sstevel@tonic-gate } 2815*7c478bd9Sstevel@tonic-gate 2816*7c478bd9Sstevel@tonic-gate 2817*7c478bd9Sstevel@tonic-gate int 2818*7c478bd9Sstevel@tonic-gate __inet_address_count(void *p) 2819*7c478bd9Sstevel@tonic-gate { 2820*7c478bd9Sstevel@tonic-gate struct ifinfo *lp = (struct ifinfo *)p; 2821*7c478bd9Sstevel@tonic-gate 2822*7c478bd9Sstevel@tonic-gate if (lp != 0) { 2823*7c478bd9Sstevel@tonic-gate return (lp->count); 2824*7c478bd9Sstevel@tonic-gate } else { 2825*7c478bd9Sstevel@tonic-gate return (0); 2826*7c478bd9Sstevel@tonic-gate } 2827*7c478bd9Sstevel@tonic-gate } 2828*7c478bd9Sstevel@tonic-gate 2829*7c478bd9Sstevel@tonic-gate uint32_t 2830*7c478bd9Sstevel@tonic-gate __inet_get_addr(void *p, int n) 2831*7c478bd9Sstevel@tonic-gate { 2832*7c478bd9Sstevel@tonic-gate struct ifinfo *localinfo = (struct ifinfo *)p; 2833*7c478bd9Sstevel@tonic-gate 2834*7c478bd9Sstevel@tonic-gate if (localinfo == 0 || n >= localinfo->count || ifaf(n) != AF_INET) 2835*7c478bd9Sstevel@tonic-gate return (0); 2836*7c478bd9Sstevel@tonic-gate 2837*7c478bd9Sstevel@tonic-gate return (ifaddr4(n).s_addr); 2838*7c478bd9Sstevel@tonic-gate } 2839*7c478bd9Sstevel@tonic-gate 2840*7c478bd9Sstevel@tonic-gate uint32_t 2841*7c478bd9Sstevel@tonic-gate __inet_get_network(void *p, int n) 2842*7c478bd9Sstevel@tonic-gate { 2843*7c478bd9Sstevel@tonic-gate struct ifinfo *localinfo = (struct ifinfo *)p; 2844*7c478bd9Sstevel@tonic-gate 2845*7c478bd9Sstevel@tonic-gate if (localinfo == 0 || n >= localinfo->count || ifaf(n) != AF_INET) 2846*7c478bd9Sstevel@tonic-gate return (0); 2847*7c478bd9Sstevel@tonic-gate 2848*7c478bd9Sstevel@tonic-gate return (ifaddr4(n).s_addr & ifmask4(n).s_addr); 2849*7c478bd9Sstevel@tonic-gate } 2850*7c478bd9Sstevel@tonic-gate 2851*7c478bd9Sstevel@tonic-gate char * 2852*7c478bd9Sstevel@tonic-gate __inet_get_uaddr(void *p, struct netconfig *nc, int n) 2853*7c478bd9Sstevel@tonic-gate { 2854*7c478bd9Sstevel@tonic-gate struct ifinfo *localinfo = (struct ifinfo *)p; 2855*7c478bd9Sstevel@tonic-gate char *uaddr; 2856*7c478bd9Sstevel@tonic-gate struct sockaddr_in sin4; 2857*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 sin6; 2858*7c478bd9Sstevel@tonic-gate struct sockaddr *sin; 2859*7c478bd9Sstevel@tonic-gate struct netbuf nb; 2860*7c478bd9Sstevel@tonic-gate 2861*7c478bd9Sstevel@tonic-gate if (localinfo == 0 || nc == 0 || n >= localinfo->count) 2862*7c478bd9Sstevel@tonic-gate return (0); 2863*7c478bd9Sstevel@tonic-gate 2864*7c478bd9Sstevel@tonic-gate if (ifaf(n) == AF_INET6) { 2865*7c478bd9Sstevel@tonic-gate if (strcmp(NC_INET6, nc->nc_protofmly) != 0) 2866*7c478bd9Sstevel@tonic-gate return (0); 2867*7c478bd9Sstevel@tonic-gate memset(&sin6, 0, sizeof (sin6)); 2868*7c478bd9Sstevel@tonic-gate sin6.sin6_family = AF_INET6; 2869*7c478bd9Sstevel@tonic-gate sin6.sin6_addr = ifaddr6(n); 2870*7c478bd9Sstevel@tonic-gate nb.buf = (char *)&sin6; 2871*7c478bd9Sstevel@tonic-gate nb.len = sizeof (sin6); 2872*7c478bd9Sstevel@tonic-gate } else { 2873*7c478bd9Sstevel@tonic-gate if (strcmp(NC_INET, nc->nc_protofmly) != 0) 2874*7c478bd9Sstevel@tonic-gate return (0); 2875*7c478bd9Sstevel@tonic-gate memset(&sin4, 0, sizeof (sin4)); 2876*7c478bd9Sstevel@tonic-gate sin4.sin_family = AF_INET; 2877*7c478bd9Sstevel@tonic-gate sin4.sin_addr = ifaddr4(n); 2878*7c478bd9Sstevel@tonic-gate nb.buf = (char *)&sin4; 2879*7c478bd9Sstevel@tonic-gate nb.len = sizeof (sin4); 2880*7c478bd9Sstevel@tonic-gate } 2881*7c478bd9Sstevel@tonic-gate 2882*7c478bd9Sstevel@tonic-gate nb.maxlen = nb.len; 2883*7c478bd9Sstevel@tonic-gate 2884*7c478bd9Sstevel@tonic-gate uaddr = taddr2uaddr(nc, &nb); 2885*7c478bd9Sstevel@tonic-gate return (uaddr); 2886*7c478bd9Sstevel@tonic-gate } 2887*7c478bd9Sstevel@tonic-gate 2888*7c478bd9Sstevel@tonic-gate char * 2889*7c478bd9Sstevel@tonic-gate __inet_get_networka(void *p, int n) 2890*7c478bd9Sstevel@tonic-gate { 2891*7c478bd9Sstevel@tonic-gate struct ifinfo *localinfo = (struct ifinfo *)p; 2892*7c478bd9Sstevel@tonic-gate 2893*7c478bd9Sstevel@tonic-gate if (localinfo == 0 || n >= localinfo->count) 2894*7c478bd9Sstevel@tonic-gate return (0); 2895*7c478bd9Sstevel@tonic-gate 2896*7c478bd9Sstevel@tonic-gate if (ifaf(n) == AF_INET6) { 2897*7c478bd9Sstevel@tonic-gate char buf[INET6_ADDRSTRLEN]; 2898*7c478bd9Sstevel@tonic-gate struct in6_addr in6; 2899*7c478bd9Sstevel@tonic-gate int i; 2900*7c478bd9Sstevel@tonic-gate 2901*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (in6.s6_addr); i++) { 2902*7c478bd9Sstevel@tonic-gate in6.s6_addr[i] = ifaddr6(n).s6_addr[i] & 2903*7c478bd9Sstevel@tonic-gate ifmask6(n).s6_addr[i]; 2904*7c478bd9Sstevel@tonic-gate } 2905*7c478bd9Sstevel@tonic-gate return (strdup(inet_ntop(AF_INET6, &in6, buf, sizeof (buf)))); 2906*7c478bd9Sstevel@tonic-gate } else { 2907*7c478bd9Sstevel@tonic-gate struct in_addr in4; 2908*7c478bd9Sstevel@tonic-gate 2909*7c478bd9Sstevel@tonic-gate in4.s_addr = ifaddr4(n).s_addr & ifmask4(n).s_addr; 2910*7c478bd9Sstevel@tonic-gate return (strdup(inet_ntoa(in4))); 2911*7c478bd9Sstevel@tonic-gate } 2912*7c478bd9Sstevel@tonic-gate } 2913*7c478bd9Sstevel@tonic-gate 2914*7c478bd9Sstevel@tonic-gate static int 2915*7c478bd9Sstevel@tonic-gate in_list(struct in_addr *addrs, int n, struct in_addr a) 2916*7c478bd9Sstevel@tonic-gate { 2917*7c478bd9Sstevel@tonic-gate int i; 2918*7c478bd9Sstevel@tonic-gate 2919*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 2920*7c478bd9Sstevel@tonic-gate if (addrs[i].s_addr == a.s_addr) 2921*7c478bd9Sstevel@tonic-gate return (1); 2922*7c478bd9Sstevel@tonic-gate } 2923*7c478bd9Sstevel@tonic-gate return (0); 2924*7c478bd9Sstevel@tonic-gate } 2925*7c478bd9Sstevel@tonic-gate 2926*7c478bd9Sstevel@tonic-gate static int 2927*7c478bd9Sstevel@tonic-gate getbroadcastnets(struct netconfig *tp, struct in_addr **addrs) 2928*7c478bd9Sstevel@tonic-gate { 2929*7c478bd9Sstevel@tonic-gate struct ifconf ifc; 2930*7c478bd9Sstevel@tonic-gate struct ifreq ifreq, *ifr; 2931*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 2932*7c478bd9Sstevel@tonic-gate struct in_addr a; 2933*7c478bd9Sstevel@tonic-gate int fd; 2934*7c478bd9Sstevel@tonic-gate int n, i, numifs; 2935*7c478bd9Sstevel@tonic-gate char *buf; 2936*7c478bd9Sstevel@tonic-gate int use_loopback = 0; 2937*7c478bd9Sstevel@tonic-gate 2938*7c478bd9Sstevel@tonic-gate _nderror = ND_SYSTEM; 2939*7c478bd9Sstevel@tonic-gate fd = open(tp->nc_device, O_RDONLY); 2940*7c478bd9Sstevel@tonic-gate if (fd < 0) { 2941*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, 2942*7c478bd9Sstevel@tonic-gate "broadcast: open to get interface configuration: %m"); 2943*7c478bd9Sstevel@tonic-gate return (0); 2944*7c478bd9Sstevel@tonic-gate } 2945*7c478bd9Sstevel@tonic-gate if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) 2946*7c478bd9Sstevel@tonic-gate numifs = MAXIFS; 2947*7c478bd9Sstevel@tonic-gate buf = (char *)malloc(numifs * sizeof (struct ifreq)); 2948*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 2949*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "broadcast: malloc failed: %m"); 2950*7c478bd9Sstevel@tonic-gate (void) close(fd); 2951*7c478bd9Sstevel@tonic-gate return (0); 2952*7c478bd9Sstevel@tonic-gate } 2953*7c478bd9Sstevel@tonic-gate *addrs = (struct in_addr *)malloc(numifs * sizeof (struct in_addr)); 2954*7c478bd9Sstevel@tonic-gate if (*addrs == NULL) { 2955*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, "broadcast: malloc failed: %m"); 2956*7c478bd9Sstevel@tonic-gate free(buf); 2957*7c478bd9Sstevel@tonic-gate (void) close(fd); 2958*7c478bd9Sstevel@tonic-gate return (0); 2959*7c478bd9Sstevel@tonic-gate } 2960*7c478bd9Sstevel@tonic-gate ifc.ifc_len = numifs * (int)sizeof (struct ifreq); 2961*7c478bd9Sstevel@tonic-gate ifc.ifc_buf = buf; 2962*7c478bd9Sstevel@tonic-gate /* 2963*7c478bd9Sstevel@tonic-gate * Ideally, this ioctl should also tell me, how many bytes were 2964*7c478bd9Sstevel@tonic-gate * finally allocated, but it doesnt. 2965*7c478bd9Sstevel@tonic-gate */ 2966*7c478bd9Sstevel@tonic-gate if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) { 2967*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, 2968*7c478bd9Sstevel@tonic-gate "broadcast: ioctl (get interface configuration): %m"); 2969*7c478bd9Sstevel@tonic-gate free(buf); 2970*7c478bd9Sstevel@tonic-gate free(*addrs); 2971*7c478bd9Sstevel@tonic-gate (void) close(fd); 2972*7c478bd9Sstevel@tonic-gate return (0); 2973*7c478bd9Sstevel@tonic-gate } 2974*7c478bd9Sstevel@tonic-gate 2975*7c478bd9Sstevel@tonic-gate retry: 2976*7c478bd9Sstevel@tonic-gate ifr = (struct ifreq *)buf; 2977*7c478bd9Sstevel@tonic-gate for (i = 0, n = ifc.ifc_len / (int)sizeof (struct ifreq); 2978*7c478bd9Sstevel@tonic-gate n > 0; n--, ifr++) { 2979*7c478bd9Sstevel@tonic-gate ifreq = *ifr; 2980*7c478bd9Sstevel@tonic-gate if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifreq) < 0) { 2981*7c478bd9Sstevel@tonic-gate (void) syslog(LOG_ERR, 2982*7c478bd9Sstevel@tonic-gate "broadcast: ioctl (get interface flags): %m"); 2983*7c478bd9Sstevel@tonic-gate continue; 2984*7c478bd9Sstevel@tonic-gate } 2985*7c478bd9Sstevel@tonic-gate if (!(ifreq.ifr_flags & IFF_UP) || 2986*7c478bd9Sstevel@tonic-gate (ifr->ifr_addr.sa_family != AF_INET)) 2987*7c478bd9Sstevel@tonic-gate continue; 2988*7c478bd9Sstevel@tonic-gate if (ifreq.ifr_flags & IFF_BROADCAST) { 2989*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&ifr->ifr_addr; 2990*7c478bd9Sstevel@tonic-gate if (ioctl(fd, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { 2991*7c478bd9Sstevel@tonic-gate /* May not work with other implementation */ 2992*7c478bd9Sstevel@tonic-gate a = _inet_makeaddr( 2993*7c478bd9Sstevel@tonic-gate inet_netof(sin->sin_addr), 2994*7c478bd9Sstevel@tonic-gate INADDR_ANY); 2995*7c478bd9Sstevel@tonic-gate if (!in_list(*addrs, i, a)) 2996*7c478bd9Sstevel@tonic-gate (*addrs)[i++] = a; 2997*7c478bd9Sstevel@tonic-gate } else { 2998*7c478bd9Sstevel@tonic-gate a = ((struct sockaddr_in *) 2999*7c478bd9Sstevel@tonic-gate &ifreq.ifr_addr)->sin_addr; 3000*7c478bd9Sstevel@tonic-gate if (!in_list(*addrs, i, a)) 3001*7c478bd9Sstevel@tonic-gate (*addrs)[i++] = a; 3002*7c478bd9Sstevel@tonic-gate } 3003*7c478bd9Sstevel@tonic-gate continue; 3004*7c478bd9Sstevel@tonic-gate } 3005*7c478bd9Sstevel@tonic-gate if (use_loopback && (ifreq.ifr_flags & IFF_LOOPBACK)) { 3006*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&ifr->ifr_addr; 3007*7c478bd9Sstevel@tonic-gate a = sin->sin_addr; 3008*7c478bd9Sstevel@tonic-gate if (!in_list(*addrs, i, a)) 3009*7c478bd9Sstevel@tonic-gate (*addrs)[i++] = a; 3010*7c478bd9Sstevel@tonic-gate continue; 3011*7c478bd9Sstevel@tonic-gate } 3012*7c478bd9Sstevel@tonic-gate if (ifreq.ifr_flags & IFF_POINTOPOINT) { 3013*7c478bd9Sstevel@tonic-gate if (ioctl(fd, SIOCGIFDSTADDR, (char *)&ifreq) < 0) 3014*7c478bd9Sstevel@tonic-gate continue; 3015*7c478bd9Sstevel@tonic-gate a = ((struct sockaddr_in *) 3016*7c478bd9Sstevel@tonic-gate &ifreq.ifr_addr)->sin_addr; 3017*7c478bd9Sstevel@tonic-gate if (!in_list(*addrs, i, a)) 3018*7c478bd9Sstevel@tonic-gate (*addrs)[i++] = a; 3019*7c478bd9Sstevel@tonic-gate continue; 3020*7c478bd9Sstevel@tonic-gate } 3021*7c478bd9Sstevel@tonic-gate } 3022*7c478bd9Sstevel@tonic-gate if (i == 0 && !use_loopback) { 3023*7c478bd9Sstevel@tonic-gate use_loopback = 1; 3024*7c478bd9Sstevel@tonic-gate goto retry; 3025*7c478bd9Sstevel@tonic-gate } 3026*7c478bd9Sstevel@tonic-gate free(buf); 3027*7c478bd9Sstevel@tonic-gate (void) close(fd); 3028*7c478bd9Sstevel@tonic-gate if (i) 3029*7c478bd9Sstevel@tonic-gate _nderror = ND_OK; 3030*7c478bd9Sstevel@tonic-gate else 3031*7c478bd9Sstevel@tonic-gate free(*addrs); 3032*7c478bd9Sstevel@tonic-gate return (i); 3033*7c478bd9Sstevel@tonic-gate } 3034*7c478bd9Sstevel@tonic-gate 3035*7c478bd9Sstevel@tonic-gate /* 3036*7c478bd9Sstevel@tonic-gate * This is lifted straight from libsocket/inet/inet_mkaddr.c. 3037*7c478bd9Sstevel@tonic-gate * Copied here to avoid our dependency on libsocket. More importantly, 3038*7c478bd9Sstevel@tonic-gate * to make sure partially static apps that use libnsl, but not 3039*7c478bd9Sstevel@tonic-gate * libsocket, don't get screwed up. 3040*7c478bd9Sstevel@tonic-gate * If you understand the above paragraph, try to get rid of 3041*7c478bd9Sstevel@tonic-gate * this copy of inet_makeaddr; if you don;t, leave it alone. 3042*7c478bd9Sstevel@tonic-gate * 3043*7c478bd9Sstevel@tonic-gate * Formulate an Internet address from network + host. Used in 3044*7c478bd9Sstevel@tonic-gate * building addresses stored in the ifnet structure. 3045*7c478bd9Sstevel@tonic-gate */ 3046*7c478bd9Sstevel@tonic-gate static struct in_addr 3047*7c478bd9Sstevel@tonic-gate _inet_makeaddr(in_addr_t net, in_addr_t host) 3048*7c478bd9Sstevel@tonic-gate { 3049*7c478bd9Sstevel@tonic-gate in_addr_t addr; 3050*7c478bd9Sstevel@tonic-gate struct in_addr inaddr; 3051*7c478bd9Sstevel@tonic-gate 3052*7c478bd9Sstevel@tonic-gate if (net < 128) 3053*7c478bd9Sstevel@tonic-gate addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); 3054*7c478bd9Sstevel@tonic-gate else if (net < 65536) 3055*7c478bd9Sstevel@tonic-gate addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); 3056*7c478bd9Sstevel@tonic-gate else if (net < 16777216L) 3057*7c478bd9Sstevel@tonic-gate addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); 3058*7c478bd9Sstevel@tonic-gate else 3059*7c478bd9Sstevel@tonic-gate addr = net | host; 3060*7c478bd9Sstevel@tonic-gate inaddr.s_addr = htonl(addr); 3061*7c478bd9Sstevel@tonic-gate return (inaddr); 3062*7c478bd9Sstevel@tonic-gate } 3063*7c478bd9Sstevel@tonic-gate 3064*7c478bd9Sstevel@tonic-gate /* 3065*7c478bd9Sstevel@tonic-gate * Routine to read the default configuration file and check if SORT_ADDRS 3066*7c478bd9Sstevel@tonic-gate * is set to NO or FALSE. This routine is called by order_haddrlist_af() 3067*7c478bd9Sstevel@tonic-gate * to determine if the addresses need to be sorted. 3068*7c478bd9Sstevel@tonic-gate */ 3069*7c478bd9Sstevel@tonic-gate static boolean_t 3070*7c478bd9Sstevel@tonic-gate _read_nsw_file(void) 3071*7c478bd9Sstevel@tonic-gate { 3072*7c478bd9Sstevel@tonic-gate char defval[LINESIZE]; 3073*7c478bd9Sstevel@tonic-gate __NSL_FILE *defl; 3074*7c478bd9Sstevel@tonic-gate boolean_t nosort = B_FALSE; 3075*7c478bd9Sstevel@tonic-gate 3076*7c478bd9Sstevel@tonic-gate 3077*7c478bd9Sstevel@tonic-gate do { 3078*7c478bd9Sstevel@tonic-gate defl = __nsl_fopen(__NSW_DEFAULT_FILE, "r"); 3079*7c478bd9Sstevel@tonic-gate } while ((defl == NULL) && (errno == EINTR)); 3080*7c478bd9Sstevel@tonic-gate 3081*7c478bd9Sstevel@tonic-gate if (defl == NULL) 3082*7c478bd9Sstevel@tonic-gate return (B_FALSE); 3083*7c478bd9Sstevel@tonic-gate 3084*7c478bd9Sstevel@tonic-gate while (__nsl_fgets(defval, sizeof (defval), defl) != NULL) { 3085*7c478bd9Sstevel@tonic-gate if ((strncmp(DONT_SORT, defval, sizeof (DONT_SORT) - 1) == 0) || 3086*7c478bd9Sstevel@tonic-gate (strncmp(DONT_SORT2, defval, 3087*7c478bd9Sstevel@tonic-gate sizeof (DONT_SORT2) - 1) == 0)) { 3088*7c478bd9Sstevel@tonic-gate nosort = B_TRUE; 3089*7c478bd9Sstevel@tonic-gate break; 3090*7c478bd9Sstevel@tonic-gate } 3091*7c478bd9Sstevel@tonic-gate } 3092*7c478bd9Sstevel@tonic-gate __nsl_fclose(defl); 3093*7c478bd9Sstevel@tonic-gate return (nosort); 3094*7c478bd9Sstevel@tonic-gate } 3095