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