17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57257d1b4Sraf * Common Development and Distribution License (the "License"). 67257d1b4Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 23*d2b5b2d3SAnders Persson * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 317c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <sys/socket.h> 367c478bd9Sstevel@tonic-gate #include <sys/stat.h> 377c478bd9Sstevel@tonic-gate #include <netinet/in.h> 387c478bd9Sstevel@tonic-gate #include <errno.h> 397c478bd9Sstevel@tonic-gate #include <unistd.h> 407c478bd9Sstevel@tonic-gate #include <stdlib.h> 417c478bd9Sstevel@tonic-gate #include <string.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* 447c478bd9Sstevel@tonic-gate * XXX The functions in this file are only needed to support transport 45*d2b5b2d3SAnders Persson * providers that have not yet been converted to use /etc/sock2path.d. 467c478bd9Sstevel@tonic-gate * Once all transport providers have been converted this file can be 477c478bd9Sstevel@tonic-gate * removed. 487c478bd9Sstevel@tonic-gate */ 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate static struct netconfig *_s_match_netconf(int family, int type, int proto, 517c478bd9Sstevel@tonic-gate void **nethandle); 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* 547c478bd9Sstevel@tonic-gate * The following two string arrays map a number as specified 557c478bd9Sstevel@tonic-gate * by a user of sockets, to the string as would be returned 567c478bd9Sstevel@tonic-gate * by a call to getnetconfig(). 577c478bd9Sstevel@tonic-gate * 587c478bd9Sstevel@tonic-gate * They are used by _s_match_netconf(); 597c478bd9Sstevel@tonic-gate * 607c478bd9Sstevel@tonic-gate * proto_sw contains protocol entries for which there is a corresponding 617c478bd9Sstevel@tonic-gate * /dev device. All others would presumably use raw IP and download the 627c478bd9Sstevel@tonic-gate * desired protocol. 637c478bd9Sstevel@tonic-gate */ 647c478bd9Sstevel@tonic-gate static char *proto_sw[] = { 657c478bd9Sstevel@tonic-gate "", 667c478bd9Sstevel@tonic-gate "icmp", /* 1 = ICMP */ 677c478bd9Sstevel@tonic-gate "", 687c478bd9Sstevel@tonic-gate "", 697c478bd9Sstevel@tonic-gate "", 707c478bd9Sstevel@tonic-gate "", 717c478bd9Sstevel@tonic-gate "tcp", /* 6 = TCP */ 727c478bd9Sstevel@tonic-gate "", 737c478bd9Sstevel@tonic-gate "", 747c478bd9Sstevel@tonic-gate "", 757c478bd9Sstevel@tonic-gate "", 767c478bd9Sstevel@tonic-gate "", 777c478bd9Sstevel@tonic-gate "", 787c478bd9Sstevel@tonic-gate "", 797c478bd9Sstevel@tonic-gate "", 807c478bd9Sstevel@tonic-gate "", 817c478bd9Sstevel@tonic-gate "", 827c478bd9Sstevel@tonic-gate "udp", /* 17 = UDP */ 837c478bd9Sstevel@tonic-gate }; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate static char *family_sw[] = { 867c478bd9Sstevel@tonic-gate "-", /* 0 = AF_UNSPEC */ 877c478bd9Sstevel@tonic-gate "loopback", /* 1 = AF_UNIX */ 887c478bd9Sstevel@tonic-gate "inet", /* 2 = AF_INET */ 897c478bd9Sstevel@tonic-gate "implink", /* 3 = AF_IMPLINK */ 907c478bd9Sstevel@tonic-gate "pup", /* 4 = AF_PUP */ 917c478bd9Sstevel@tonic-gate "chaos", /* 5 = AF_CHAOS */ 927c478bd9Sstevel@tonic-gate "ns", /* 6 = AF_NS */ 937c478bd9Sstevel@tonic-gate "nbs", /* 7 = AF_NBS */ 947c478bd9Sstevel@tonic-gate "ecma", /* 8 = AF_ECMA */ 957c478bd9Sstevel@tonic-gate "datakit", /* 9 = AF_DATAKIT */ 967c478bd9Sstevel@tonic-gate "ccitt", /* 10 = AF_CCITT */ 977c478bd9Sstevel@tonic-gate "sna", /* 11 = AF_SNA */ 987c478bd9Sstevel@tonic-gate "decnet", /* 12 = AF_DECnet */ 997c478bd9Sstevel@tonic-gate "dli", /* 13 = AF_DLI */ 1007c478bd9Sstevel@tonic-gate "lat", /* 14 = AF_LAT */ 1017c478bd9Sstevel@tonic-gate "hylink", /* 15 = AF_HYLINK */ 1027c478bd9Sstevel@tonic-gate "appletalk", /* 16 = AF_APPLETALK */ 1037c478bd9Sstevel@tonic-gate "nit", /* 17 = AF_NIT */ 1047c478bd9Sstevel@tonic-gate "ieee802", /* 18 = AF_802 */ 1057c478bd9Sstevel@tonic-gate "osi", /* 19 = AF_OSI */ 1067c478bd9Sstevel@tonic-gate "x25", /* 20 = AF_X25 */ 1077c478bd9Sstevel@tonic-gate "osinet", /* 21 = AF_OSINET */ 1087c478bd9Sstevel@tonic-gate "gosip", /* 22 = AF_GOSIP */ 1097c478bd9Sstevel@tonic-gate "ipx", /* 23 = AF_IPX */ 1107c478bd9Sstevel@tonic-gate "route", /* 24 = AF_ROUTE */ 1117c478bd9Sstevel@tonic-gate "link", /* 25 = AF_LINK */ 1127c478bd9Sstevel@tonic-gate "inet6", /* 26 = AF_INET6 */ 1137c478bd9Sstevel@tonic-gate "key", /* 27 = AF_KEY */ 1147c478bd9Sstevel@tonic-gate }; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* 1177c478bd9Sstevel@tonic-gate * Lookup family/type/protocol in /etc/netconfig. 1187c478bd9Sstevel@tonic-gate * Returns the pathname and a prototype value (to be passed into SO_PROTOTYPE) 1197c478bd9Sstevel@tonic-gate * The path is malloc'ed and has to be freed by the caller. 1207c478bd9Sstevel@tonic-gate */ 1217c478bd9Sstevel@tonic-gate int 1227c478bd9Sstevel@tonic-gate _s_netconfig_path(int family, int type, int protocol, 1237c478bd9Sstevel@tonic-gate char **pathp, int *prototype) 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate struct netconfig *net; 1267c478bd9Sstevel@tonic-gate void *nethandle; 1277c478bd9Sstevel@tonic-gate struct stat stats; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate net = _s_match_netconf(family, type, protocol, &nethandle); 1307c478bd9Sstevel@tonic-gate if (net == NULL) 1317c478bd9Sstevel@tonic-gate return (-1); 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if (strcmp(net->nc_proto, NC_NOPROTO) != 0) 1347c478bd9Sstevel@tonic-gate *prototype = 0; 1357c478bd9Sstevel@tonic-gate else 1367c478bd9Sstevel@tonic-gate *prototype = protocol; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate retry: 1397257d1b4Sraf if (stat(net->nc_device, &stats) < 0) { 1407c478bd9Sstevel@tonic-gate switch (errno) { 1417c478bd9Sstevel@tonic-gate case EINTR: 1427c478bd9Sstevel@tonic-gate goto retry; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate case ENOENT: 1457c478bd9Sstevel@tonic-gate case ENOLINK: 1467c478bd9Sstevel@tonic-gate case ELOOP: 1477c478bd9Sstevel@tonic-gate case EMULTIHOP: 1487c478bd9Sstevel@tonic-gate case ENOTDIR: 1497c478bd9Sstevel@tonic-gate errno = EPFNOSUPPORT; 1507c478bd9Sstevel@tonic-gate break; 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate endnetconfig(nethandle); /* finished with netconfig struct */ 1537c478bd9Sstevel@tonic-gate return (-1); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate if (!S_ISCHR(stats.st_mode)) { 1567c478bd9Sstevel@tonic-gate errno = EPFNOSUPPORT; 1577c478bd9Sstevel@tonic-gate endnetconfig(nethandle); /* finished with netconfig struct */ 1587c478bd9Sstevel@tonic-gate return (-1); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate *pathp = malloc(strlen(net->nc_device) + 1); 1617c478bd9Sstevel@tonic-gate if (*pathp == NULL) { 1627c478bd9Sstevel@tonic-gate endnetconfig(nethandle); 1637c478bd9Sstevel@tonic-gate errno = ENOMEM; 1647c478bd9Sstevel@tonic-gate return (-1); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate (void) strcpy(*pathp, net->nc_device); 1677c478bd9Sstevel@tonic-gate endnetconfig(nethandle); /* finished with netconfig struct */ 1687c478bd9Sstevel@tonic-gate return (0); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * Match config entry for protocol 1737c478bd9Sstevel@tonic-gate * requested. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate static struct netconfig * 1767c478bd9Sstevel@tonic-gate _s_match_netconf(int family, int type, int proto, void **nethandle) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate struct netconfig *net; 1797c478bd9Sstevel@tonic-gate struct netconfig *maybe; 1807c478bd9Sstevel@tonic-gate char *oproto; 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate if (family < 0 || 1837c478bd9Sstevel@tonic-gate family >= (int)sizeof (family_sw) / (int)sizeof (char *) || 1847c478bd9Sstevel@tonic-gate proto < 0 || proto >= IPPROTO_MAX) { 1857c478bd9Sstevel@tonic-gate errno = EPROTONOSUPPORT; 1867c478bd9Sstevel@tonic-gate return (NULL); 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate if (proto) { 1897c478bd9Sstevel@tonic-gate if (proto >= (int)sizeof (proto_sw) / (int)sizeof (char *)) 1907c478bd9Sstevel@tonic-gate oproto = ""; 1917257d1b4Sraf else 1927257d1b4Sraf oproto = proto_sw[proto]; 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * Loop through each entry in netconfig 1977c478bd9Sstevel@tonic-gate * until one matches or we reach the end. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate if ((*nethandle = setnetconfig()) == NULL) { 2007c478bd9Sstevel@tonic-gate return (NULL); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate maybe = NULL; 2047c478bd9Sstevel@tonic-gate while ((net = getnetconfig(*nethandle)) != NULL) { 2057c478bd9Sstevel@tonic-gate /* 2067c478bd9Sstevel@tonic-gate * We make a copy of net->nc_semantics rather than modifying 2077c478bd9Sstevel@tonic-gate * it in place because the network selection code shares the 2087c478bd9Sstevel@tonic-gate * structures returned by getnetconfig() among all its callers. 2097c478bd9Sstevel@tonic-gate * See bug #1160886 for more details. 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate unsigned int semantics = net->nc_semantics; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate if (semantics == NC_TPI_COTS_ORD) 2147c478bd9Sstevel@tonic-gate semantics = NC_TPI_COTS; 2157c478bd9Sstevel@tonic-gate if (proto) { 2167c478bd9Sstevel@tonic-gate if (strcmp(net->nc_protofmly, family_sw[family]) == 0 && 2177c478bd9Sstevel@tonic-gate semantics == type && 2187c478bd9Sstevel@tonic-gate strcmp(net->nc_proto, oproto) == 0) 2197c478bd9Sstevel@tonic-gate break; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (strcmp(net->nc_protofmly, family_sw[family]) == 0 && 2227c478bd9Sstevel@tonic-gate type == SOCK_RAW && 2237c478bd9Sstevel@tonic-gate semantics == SOCK_RAW && 2247c478bd9Sstevel@tonic-gate strcmp(net->nc_proto, NC_NOPROTO) == 0 && 2257c478bd9Sstevel@tonic-gate maybe == NULL) 2267c478bd9Sstevel@tonic-gate maybe = net; /* in case no exact match */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate continue; 2297c478bd9Sstevel@tonic-gate } else { 2307c478bd9Sstevel@tonic-gate if (strcmp(net->nc_protofmly, family_sw[family]) == 0 && 2317c478bd9Sstevel@tonic-gate semantics == type) { 2327c478bd9Sstevel@tonic-gate break; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate if (net == NULL && maybe) 2377c478bd9Sstevel@tonic-gate net = maybe; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate if (net == NULL) { 2407c478bd9Sstevel@tonic-gate endnetconfig(*nethandle); 2417c478bd9Sstevel@tonic-gate errno = EPROTONOSUPPORT; 2427c478bd9Sstevel@tonic-gate return (NULL); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate return (net); 2467c478bd9Sstevel@tonic-gate } 247