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