1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1989 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*0Sstevel@tonic-gate /* All Rights Reserved */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate /* 31*0Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 32*0Sstevel@tonic-gate * under license from the Regents of the University of California. 33*0Sstevel@tonic-gate */ 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #include <sys/types.h> 38*0Sstevel@tonic-gate #include <sys/socket.h> 39*0Sstevel@tonic-gate #include <sys/stat.h> 40*0Sstevel@tonic-gate #include <netinet/in.h> 41*0Sstevel@tonic-gate #include <errno.h> 42*0Sstevel@tonic-gate #include <unistd.h> 43*0Sstevel@tonic-gate #include <stdlib.h> 44*0Sstevel@tonic-gate #include <string.h> 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate extern int _stat(); 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate /* 49*0Sstevel@tonic-gate * XXX The functions in this file are only needed to support transport 50*0Sstevel@tonic-gate * providers that have not yet been converted to use /etc/sock2path. 51*0Sstevel@tonic-gate * Once all transport providers have been converted this file can be 52*0Sstevel@tonic-gate * removed. 53*0Sstevel@tonic-gate */ 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate static struct netconfig *_s_match_netconf(int family, int type, int proto, 56*0Sstevel@tonic-gate void **nethandle); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* 59*0Sstevel@tonic-gate * The following two string arrays map a number as specified 60*0Sstevel@tonic-gate * by a user of sockets, to the string as would be returned 61*0Sstevel@tonic-gate * by a call to getnetconfig(). 62*0Sstevel@tonic-gate * 63*0Sstevel@tonic-gate * They are used by _s_match_netconf(); 64*0Sstevel@tonic-gate * 65*0Sstevel@tonic-gate * proto_sw contains protocol entries for which there is a corresponding 66*0Sstevel@tonic-gate * /dev device. All others would presumably use raw IP and download the 67*0Sstevel@tonic-gate * desired protocol. 68*0Sstevel@tonic-gate */ 69*0Sstevel@tonic-gate static char *proto_sw[] = { 70*0Sstevel@tonic-gate "", 71*0Sstevel@tonic-gate "icmp", /* 1 = ICMP */ 72*0Sstevel@tonic-gate "", 73*0Sstevel@tonic-gate "", 74*0Sstevel@tonic-gate "", 75*0Sstevel@tonic-gate "", 76*0Sstevel@tonic-gate "tcp", /* 6 = TCP */ 77*0Sstevel@tonic-gate "", 78*0Sstevel@tonic-gate "", 79*0Sstevel@tonic-gate "", 80*0Sstevel@tonic-gate "", 81*0Sstevel@tonic-gate "", 82*0Sstevel@tonic-gate "", 83*0Sstevel@tonic-gate "", 84*0Sstevel@tonic-gate "", 85*0Sstevel@tonic-gate "", 86*0Sstevel@tonic-gate "", 87*0Sstevel@tonic-gate "udp", /* 17 = UDP */ 88*0Sstevel@tonic-gate }; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate static char *family_sw[] = { 91*0Sstevel@tonic-gate "-", /* 0 = AF_UNSPEC */ 92*0Sstevel@tonic-gate "loopback", /* 1 = AF_UNIX */ 93*0Sstevel@tonic-gate "inet", /* 2 = AF_INET */ 94*0Sstevel@tonic-gate "implink", /* 3 = AF_IMPLINK */ 95*0Sstevel@tonic-gate "pup", /* 4 = AF_PUP */ 96*0Sstevel@tonic-gate "chaos", /* 5 = AF_CHAOS */ 97*0Sstevel@tonic-gate "ns", /* 6 = AF_NS */ 98*0Sstevel@tonic-gate "nbs", /* 7 = AF_NBS */ 99*0Sstevel@tonic-gate "ecma", /* 8 = AF_ECMA */ 100*0Sstevel@tonic-gate "datakit", /* 9 = AF_DATAKIT */ 101*0Sstevel@tonic-gate "ccitt", /* 10 = AF_CCITT */ 102*0Sstevel@tonic-gate "sna", /* 11 = AF_SNA */ 103*0Sstevel@tonic-gate "decnet", /* 12 = AF_DECnet */ 104*0Sstevel@tonic-gate "dli", /* 13 = AF_DLI */ 105*0Sstevel@tonic-gate "lat", /* 14 = AF_LAT */ 106*0Sstevel@tonic-gate "hylink", /* 15 = AF_HYLINK */ 107*0Sstevel@tonic-gate "appletalk", /* 16 = AF_APPLETALK */ 108*0Sstevel@tonic-gate "nit", /* 17 = AF_NIT */ 109*0Sstevel@tonic-gate "ieee802", /* 18 = AF_802 */ 110*0Sstevel@tonic-gate "osi", /* 19 = AF_OSI */ 111*0Sstevel@tonic-gate "x25", /* 20 = AF_X25 */ 112*0Sstevel@tonic-gate "osinet", /* 21 = AF_OSINET */ 113*0Sstevel@tonic-gate "gosip", /* 22 = AF_GOSIP */ 114*0Sstevel@tonic-gate "ipx", /* 23 = AF_IPX */ 115*0Sstevel@tonic-gate "route", /* 24 = AF_ROUTE */ 116*0Sstevel@tonic-gate "link", /* 25 = AF_LINK */ 117*0Sstevel@tonic-gate "inet6", /* 26 = AF_INET6 */ 118*0Sstevel@tonic-gate "key", /* 27 = AF_KEY */ 119*0Sstevel@tonic-gate }; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate /* 122*0Sstevel@tonic-gate * Lookup family/type/protocol in /etc/netconfig. 123*0Sstevel@tonic-gate * Returns the pathname and a prototype value (to be passed into SO_PROTOTYPE) 124*0Sstevel@tonic-gate * The path is malloc'ed and has to be freed by the caller. 125*0Sstevel@tonic-gate */ 126*0Sstevel@tonic-gate int 127*0Sstevel@tonic-gate _s_netconfig_path(int family, int type, int protocol, 128*0Sstevel@tonic-gate char **pathp, int *prototype) 129*0Sstevel@tonic-gate { 130*0Sstevel@tonic-gate struct netconfig *net; 131*0Sstevel@tonic-gate void *nethandle; 132*0Sstevel@tonic-gate struct stat stats; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate net = _s_match_netconf(family, type, protocol, &nethandle); 135*0Sstevel@tonic-gate if (net == NULL) 136*0Sstevel@tonic-gate return (-1); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate if (strcmp(net->nc_proto, NC_NOPROTO) != 0) 139*0Sstevel@tonic-gate *prototype = 0; 140*0Sstevel@tonic-gate else 141*0Sstevel@tonic-gate *prototype = protocol; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate retry: 144*0Sstevel@tonic-gate #if defined(i386) 145*0Sstevel@tonic-gate if (_xstat(_STAT_VER, net->nc_device, &stats) < 0) { 146*0Sstevel@tonic-gate #else 147*0Sstevel@tonic-gate if (_stat(net->nc_device, &stats) < 0) { 148*0Sstevel@tonic-gate #endif 149*0Sstevel@tonic-gate switch (errno) { 150*0Sstevel@tonic-gate case EINTR: 151*0Sstevel@tonic-gate goto retry; 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate case ENOENT: 154*0Sstevel@tonic-gate case ENOLINK: 155*0Sstevel@tonic-gate case ELOOP: 156*0Sstevel@tonic-gate case EMULTIHOP: 157*0Sstevel@tonic-gate case ENOTDIR: 158*0Sstevel@tonic-gate errno = EPFNOSUPPORT; 159*0Sstevel@tonic-gate break; 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate endnetconfig(nethandle); /* finished with netconfig struct */ 162*0Sstevel@tonic-gate return (-1); 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate if (!S_ISCHR(stats.st_mode)) { 165*0Sstevel@tonic-gate errno = EPFNOSUPPORT; 166*0Sstevel@tonic-gate endnetconfig(nethandle); /* finished with netconfig struct */ 167*0Sstevel@tonic-gate return (-1); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate *pathp = malloc(strlen(net->nc_device) + 1); 170*0Sstevel@tonic-gate if (*pathp == NULL) { 171*0Sstevel@tonic-gate endnetconfig(nethandle); 172*0Sstevel@tonic-gate errno = ENOMEM; 173*0Sstevel@tonic-gate return (-1); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate (void) strcpy(*pathp, net->nc_device); 176*0Sstevel@tonic-gate endnetconfig(nethandle); /* finished with netconfig struct */ 177*0Sstevel@tonic-gate return (0); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* 181*0Sstevel@tonic-gate * Match config entry for protocol 182*0Sstevel@tonic-gate * requested. 183*0Sstevel@tonic-gate */ 184*0Sstevel@tonic-gate static struct netconfig * 185*0Sstevel@tonic-gate _s_match_netconf(int family, int type, int proto, void **nethandle) 186*0Sstevel@tonic-gate { 187*0Sstevel@tonic-gate struct netconfig *net; 188*0Sstevel@tonic-gate struct netconfig *maybe; 189*0Sstevel@tonic-gate char *oproto; 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate if (family < 0 || 192*0Sstevel@tonic-gate family >= (int)sizeof (family_sw) / (int)sizeof (char *) || 193*0Sstevel@tonic-gate proto < 0 || proto >= IPPROTO_MAX) { 194*0Sstevel@tonic-gate errno = EPROTONOSUPPORT; 195*0Sstevel@tonic-gate return (NULL); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate if (proto) { 198*0Sstevel@tonic-gate if (proto >= (int)sizeof (proto_sw) / (int)sizeof (char *)) 199*0Sstevel@tonic-gate oproto = ""; 200*0Sstevel@tonic-gate else oproto = proto_sw[proto]; 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate /* 204*0Sstevel@tonic-gate * Loop through each entry in netconfig 205*0Sstevel@tonic-gate * until one matches or we reach the end. 206*0Sstevel@tonic-gate */ 207*0Sstevel@tonic-gate if ((*nethandle = setnetconfig()) == NULL) { 208*0Sstevel@tonic-gate return (NULL); 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate maybe = NULL; 212*0Sstevel@tonic-gate while ((net = getnetconfig(*nethandle)) != NULL) { 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * We make a copy of net->nc_semantics rather than modifying 215*0Sstevel@tonic-gate * it in place because the network selection code shares the 216*0Sstevel@tonic-gate * structures returned by getnetconfig() among all its callers. 217*0Sstevel@tonic-gate * See bug #1160886 for more details. 218*0Sstevel@tonic-gate */ 219*0Sstevel@tonic-gate unsigned int semantics = net->nc_semantics; 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate if (semantics == NC_TPI_COTS_ORD) 222*0Sstevel@tonic-gate semantics = NC_TPI_COTS; 223*0Sstevel@tonic-gate if (proto) { 224*0Sstevel@tonic-gate if (strcmp(net->nc_protofmly, family_sw[family]) == 0 && 225*0Sstevel@tonic-gate semantics == type && 226*0Sstevel@tonic-gate strcmp(net->nc_proto, oproto) == 0) 227*0Sstevel@tonic-gate break; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate if (strcmp(net->nc_protofmly, family_sw[family]) == 0 && 230*0Sstevel@tonic-gate type == SOCK_RAW && 231*0Sstevel@tonic-gate semantics == SOCK_RAW && 232*0Sstevel@tonic-gate strcmp(net->nc_proto, NC_NOPROTO) == 0 && 233*0Sstevel@tonic-gate maybe == NULL) 234*0Sstevel@tonic-gate maybe = net; /* in case no exact match */ 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate continue; 237*0Sstevel@tonic-gate } else { 238*0Sstevel@tonic-gate if (strcmp(net->nc_protofmly, family_sw[family]) == 0 && 239*0Sstevel@tonic-gate semantics == type) { 240*0Sstevel@tonic-gate break; 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate if (net == NULL && maybe) 245*0Sstevel@tonic-gate net = maybe; 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate if (net == NULL) { 248*0Sstevel@tonic-gate endnetconfig(*nethandle); 249*0Sstevel@tonic-gate errno = EPROTONOSUPPORT; 250*0Sstevel@tonic-gate return (NULL); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate return (net); 254*0Sstevel@tonic-gate } 255