dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libc / port / socket / _soutil.c
blob0cb377e492b60527ee288f204c7d4bec3ff410d8
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
34 #include <sys/netconfig.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #include <netinet/in.h>
39 #include <errno.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <string.h>
45 * XXX The functions in this file are only needed to support transport
46 * providers that have not yet been converted to use /etc/sock2path.d.
47 * Once all transport providers have been converted this file can be
48 * removed.
51 static struct netconfig *_s_match_netconf(int family, int type, int proto,
52 void **nethandle);
55 * The following two string arrays map a number as specified
56 * by a user of sockets, to the string as would be returned
57 * by a call to getnetconfig().
59 * They are used by _s_match_netconf();
61 * proto_sw contains protocol entries for which there is a corresponding
62 * /dev device. All others would presumably use raw IP and download the
63 * desired protocol.
65 static char *proto_sw[] = {
66 "",
67 "icmp", /* 1 = ICMP */
68 "",
69 "",
70 "",
71 "",
72 "tcp", /* 6 = TCP */
73 "",
74 "",
75 "",
76 "",
77 "",
78 "",
79 "",
80 "",
81 "",
82 "",
83 "udp", /* 17 = UDP */
86 static char *family_sw[] = {
87 "-", /* 0 = AF_UNSPEC */
88 "loopback", /* 1 = AF_UNIX */
89 "inet", /* 2 = AF_INET */
90 "implink", /* 3 = AF_IMPLINK */
91 "pup", /* 4 = AF_PUP */
92 "chaos", /* 5 = AF_CHAOS */
93 "ns", /* 6 = AF_NS */
94 "nbs", /* 7 = AF_NBS */
95 "ecma", /* 8 = AF_ECMA */
96 "datakit", /* 9 = AF_DATAKIT */
97 "ccitt", /* 10 = AF_CCITT */
98 "sna", /* 11 = AF_SNA */
99 "decnet", /* 12 = AF_DECnet */
100 "dli", /* 13 = AF_DLI */
101 "lat", /* 14 = AF_LAT */
102 "hylink", /* 15 = AF_HYLINK */
103 "appletalk", /* 16 = AF_APPLETALK */
104 "nit", /* 17 = AF_NIT */
105 "ieee802", /* 18 = AF_802 */
106 "osi", /* 19 = AF_OSI */
107 "x25", /* 20 = AF_X25 */
108 "osinet", /* 21 = AF_OSINET */
109 "gosip", /* 22 = AF_GOSIP */
110 "ipx", /* 23 = AF_IPX */
111 "route", /* 24 = AF_ROUTE */
112 "link", /* 25 = AF_LINK */
113 "inet6", /* 26 = AF_INET6 */
114 "key", /* 27 = AF_KEY */
118 * Lookup family/type/protocol in /etc/netconfig.
119 * Returns the pathname and a prototype value (to be passed into SO_PROTOTYPE)
120 * The path is malloc'ed and has to be freed by the caller.
123 _s_netconfig_path(int family, int type, int protocol,
124 char **pathp, int *prototype)
126 struct netconfig *net;
127 void *nethandle;
128 struct stat stats;
130 net = _s_match_netconf(family, type, protocol, &nethandle);
131 if (net == NULL)
132 return (-1);
134 if (strcmp(net->nc_proto, NC_NOPROTO) != 0)
135 *prototype = 0;
136 else
137 *prototype = protocol;
139 retry:
140 if (stat(net->nc_device, &stats) < 0) {
141 switch (errno) {
142 case EINTR:
143 goto retry;
145 case ENOENT:
146 case ENOLINK:
147 case ELOOP:
148 case EMULTIHOP:
149 case ENOTDIR:
150 errno = EPFNOSUPPORT;
151 break;
153 endnetconfig(nethandle); /* finished with netconfig struct */
154 return (-1);
156 if (!S_ISCHR(stats.st_mode)) {
157 errno = EPFNOSUPPORT;
158 endnetconfig(nethandle); /* finished with netconfig struct */
159 return (-1);
161 *pathp = malloc(strlen(net->nc_device) + 1);
162 if (*pathp == NULL) {
163 endnetconfig(nethandle);
164 errno = ENOMEM;
165 return (-1);
167 (void) strcpy(*pathp, net->nc_device);
168 endnetconfig(nethandle); /* finished with netconfig struct */
169 return (0);
173 * Match config entry for protocol
174 * requested.
176 static struct netconfig *
177 _s_match_netconf(int family, int type, int proto, void **nethandle)
179 struct netconfig *net;
180 struct netconfig *maybe;
181 char *oproto;
183 if (family < 0 ||
184 family >= (int)sizeof (family_sw) / (int)sizeof (char *) ||
185 proto < 0 || proto >= IPPROTO_MAX) {
186 errno = EPROTONOSUPPORT;
187 return (NULL);
189 if (proto) {
190 if (proto >= (int)sizeof (proto_sw) / (int)sizeof (char *))
191 oproto = "";
192 else
193 oproto = proto_sw[proto];
197 * Loop through each entry in netconfig
198 * until one matches or we reach the end.
200 if ((*nethandle = setnetconfig()) == NULL) {
201 return (NULL);
204 maybe = NULL;
205 while ((net = getnetconfig(*nethandle)) != NULL) {
207 * We make a copy of net->nc_semantics rather than modifying
208 * it in place because the network selection code shares the
209 * structures returned by getnetconfig() among all its callers.
210 * See bug #1160886 for more details.
212 unsigned int semantics = net->nc_semantics;
214 if (semantics == NC_TPI_COTS_ORD)
215 semantics = NC_TPI_COTS;
216 if (proto) {
217 if (strcmp(net->nc_protofmly, family_sw[family]) == 0 &&
218 semantics == type &&
219 strcmp(net->nc_proto, oproto) == 0)
220 break;
222 if (strcmp(net->nc_protofmly, family_sw[family]) == 0 &&
223 type == SOCK_RAW &&
224 semantics == SOCK_RAW &&
225 strcmp(net->nc_proto, NC_NOPROTO) == 0 &&
226 maybe == NULL)
227 maybe = net; /* in case no exact match */
229 continue;
230 } else {
231 if (strcmp(net->nc_protofmly, family_sw[family]) == 0 &&
232 semantics == type) {
233 break;
237 if (net == NULL && maybe)
238 net = maybe;
240 if (net == NULL) {
241 endnetconfig(*nethandle);
242 errno = EPROTONOSUPPORT;
243 return (NULL);
246 return (net);