1 1.30 christos /* $NetBSD: rpc_generic.c,v 1.30 2017/05/03 21:39:27 christos Exp $ */ 2 1.1 fvdl 3 1.1 fvdl /* 4 1.28 tron * Copyright (c) 2010, Oracle America, Inc. 5 1.28 tron * 6 1.28 tron * Redistribution and use in source and binary forms, with or without 7 1.28 tron * modification, are permitted provided that the following conditions are 8 1.28 tron * met: 9 1.28 tron * 10 1.28 tron * * Redistributions of source code must retain the above copyright 11 1.28 tron * notice, this list of conditions and the following disclaimer. 12 1.28 tron * * Redistributions in binary form must reproduce the above 13 1.28 tron * copyright notice, this list of conditions and the following 14 1.28 tron * disclaimer in the documentation and/or other materials 15 1.28 tron * provided with the distribution. 16 1.28 tron * * Neither the name of the "Oracle America, Inc." nor the names of its 17 1.28 tron * contributors may be used to endorse or promote products derived 18 1.28 tron * from this software without specific prior written permission. 19 1.28 tron * 20 1.28 tron * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 1.28 tron * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 1.28 tron * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 1.28 tron * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 1.28 tron * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 25 1.28 tron * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 1.28 tron * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 27 1.28 tron * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 1.28 tron * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 1.28 tron * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 1.28 tron * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 1.28 tron * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 fvdl */ 33 1.1 fvdl /* 34 1.1 fvdl * Copyright (c) 1986-1991 by Sun Microsystems Inc. 35 1.1 fvdl */ 36 1.1 fvdl 37 1.1 fvdl /* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */ 38 1.1 fvdl 39 1.1 fvdl /* 40 1.1 fvdl * rpc_generic.c, Miscl routines for RPC. 41 1.1 fvdl * 42 1.1 fvdl */ 43 1.1 fvdl 44 1.15 itojun #include <sys/cdefs.h> 45 1.15 itojun #if defined(LIBC_SCCS) && !defined(lint) 46 1.30 christos __RCSID("$NetBSD: rpc_generic.c,v 1.30 2017/05/03 21:39:27 christos Exp $"); 47 1.15 itojun #endif 48 1.15 itojun 49 1.4 kleink #include "namespace.h" 50 1.12 thorpej #include "reentrant.h" 51 1.1 fvdl #include <sys/types.h> 52 1.1 fvdl #include <sys/param.h> 53 1.1 fvdl #include <sys/socket.h> 54 1.1 fvdl #include <sys/un.h> 55 1.1 fvdl #include <sys/resource.h> 56 1.1 fvdl #include <netinet/in.h> 57 1.22 christos #include <netinet/tcp.h> 58 1.1 fvdl #include <arpa/inet.h> 59 1.1 fvdl #include <rpc/rpc.h> 60 1.5 lukem #include <assert.h> 61 1.1 fvdl #include <ctype.h> 62 1.1 fvdl #include <stdio.h> 63 1.1 fvdl #include <netdb.h> 64 1.1 fvdl #include <netconfig.h> 65 1.29 dholland #include <stdlib.h> 66 1.1 fvdl #include <string.h> 67 1.2 assar #include <syslog.h> 68 1.1 fvdl #include <rpc/nettype.h> 69 1.27 christos 70 1.27 christos #include "svc_fdset.h" 71 1.10 fvdl #include "rpc_internal.h" 72 1.1 fvdl 73 1.18 kleink #ifdef __weak_alias 74 1.18 kleink __weak_alias(taddr2uaddr,_taddr2uaddr) 75 1.18 kleink __weak_alias(uaddr2taddr,_uaddr2taddr) 76 1.18 kleink #endif 77 1.18 kleink 78 1.1 fvdl struct handle { 79 1.1 fvdl NCONF_HANDLE *nhandle; 80 1.1 fvdl int nflag; /* Whether NETPATH or NETCONFIG */ 81 1.1 fvdl int nettype; 82 1.1 fvdl }; 83 1.1 fvdl 84 1.6 jdolecek static const struct _rpcnettype { 85 1.1 fvdl const char *name; 86 1.1 fvdl const int type; 87 1.1 fvdl } _rpctypelist[] = { 88 1.1 fvdl { "netpath", _RPC_NETPATH }, 89 1.1 fvdl { "visible", _RPC_VISIBLE }, 90 1.1 fvdl { "circuit_v", _RPC_CIRCUIT_V }, 91 1.1 fvdl { "datagram_v", _RPC_DATAGRAM_V }, 92 1.1 fvdl { "circuit_n", _RPC_CIRCUIT_N }, 93 1.1 fvdl { "datagram_n", _RPC_DATAGRAM_N }, 94 1.1 fvdl { "tcp", _RPC_TCP }, 95 1.1 fvdl { "udp", _RPC_UDP }, 96 1.1 fvdl { 0, _RPC_NONE } 97 1.1 fvdl }; 98 1.1 fvdl 99 1.1 fvdl struct netid_af { 100 1.1 fvdl const char *netid; 101 1.1 fvdl int af; 102 1.1 fvdl int protocol; 103 1.1 fvdl }; 104 1.1 fvdl 105 1.6 jdolecek static const struct netid_af na_cvt[] = { 106 1.1 fvdl { "udp", AF_INET, IPPROTO_UDP }, 107 1.1 fvdl { "tcp", AF_INET, IPPROTO_TCP }, 108 1.1 fvdl #ifdef INET6 109 1.1 fvdl { "udp6", AF_INET6, IPPROTO_UDP }, 110 1.1 fvdl { "tcp6", AF_INET6, IPPROTO_TCP }, 111 1.1 fvdl #endif 112 1.1 fvdl { "local", AF_LOCAL, 0 } 113 1.1 fvdl }; 114 1.1 fvdl 115 1.3 christos #if 0 116 1.26 matt static char *strlocase(char *); 117 1.3 christos #endif 118 1.26 matt static int getnettype(const char *); 119 1.1 fvdl 120 1.1 fvdl /* 121 1.1 fvdl * Cache the result of getrlimit(), so we don't have to do an 122 1.1 fvdl * expensive call every time. 123 1.1 fvdl */ 124 1.1 fvdl int 125 1.26 matt __rpc_dtbsize(void) 126 1.1 fvdl { 127 1.1 fvdl static int tbsize; 128 1.1 fvdl struct rlimit rl; 129 1.1 fvdl 130 1.1 fvdl if (tbsize) { 131 1.1 fvdl return (tbsize); 132 1.1 fvdl } 133 1.1 fvdl if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 134 1.3 christos return (tbsize = (int)rl.rlim_max); 135 1.1 fvdl } 136 1.1 fvdl /* 137 1.1 fvdl * Something wrong. I'll try to save face by returning a 138 1.1 fvdl * pessimistic number. 139 1.1 fvdl */ 140 1.1 fvdl return (32); 141 1.1 fvdl } 142 1.1 fvdl 143 1.1 fvdl 144 1.1 fvdl /* 145 1.1 fvdl * Find the appropriate buffer size 146 1.1 fvdl */ 147 1.1 fvdl u_int 148 1.3 christos /*ARGSUSED*/ 149 1.26 matt __rpc_get_t_size( 150 1.26 matt int af, 151 1.26 matt int proto, 152 1.26 matt int size) /* Size requested */ 153 1.1 fvdl { 154 1.13 yamt int maxsize, defsize; 155 1.1 fvdl 156 1.13 yamt maxsize = 256 * 1024; /* XXX */ 157 1.1 fvdl switch (proto) { 158 1.1 fvdl case IPPROTO_TCP: 159 1.13 yamt defsize = 64 * 1024; /* XXX */ 160 1.1 fvdl break; 161 1.1 fvdl case IPPROTO_UDP: 162 1.13 yamt defsize = UDPMSGSIZE; 163 1.1 fvdl break; 164 1.1 fvdl default: 165 1.13 yamt defsize = RPC_MAXDATASIZE; 166 1.1 fvdl break; 167 1.1 fvdl } 168 1.1 fvdl if (size == 0) 169 1.13 yamt return defsize; 170 1.1 fvdl 171 1.1 fvdl /* Check whether the value is within the upper max limit */ 172 1.1 fvdl return (size > maxsize ? (u_int)maxsize : (u_int)size); 173 1.1 fvdl } 174 1.1 fvdl 175 1.1 fvdl /* 176 1.1 fvdl * Find the appropriate address buffer size 177 1.1 fvdl */ 178 1.1 fvdl u_int 179 1.26 matt __rpc_get_a_size(int af) 180 1.1 fvdl { 181 1.1 fvdl switch (af) { 182 1.1 fvdl case AF_INET: 183 1.1 fvdl return sizeof (struct sockaddr_in); 184 1.1 fvdl #ifdef INET6 185 1.1 fvdl case AF_INET6: 186 1.1 fvdl return sizeof (struct sockaddr_in6); 187 1.1 fvdl #endif 188 1.1 fvdl case AF_LOCAL: 189 1.1 fvdl return sizeof (struct sockaddr_un); 190 1.1 fvdl default: 191 1.1 fvdl break; 192 1.1 fvdl } 193 1.1 fvdl return ((u_int)RPC_MAXADDRSIZE); 194 1.1 fvdl } 195 1.1 fvdl 196 1.3 christos #if 0 197 1.1 fvdl static char * 198 1.26 matt strlocase(char *p) 199 1.1 fvdl { 200 1.1 fvdl char *t = p; 201 1.1 fvdl 202 1.5 lukem _DIAGASSERT(p != NULL); 203 1.5 lukem 204 1.1 fvdl for (; *p; p++) 205 1.1 fvdl if (isupper(*p)) 206 1.1 fvdl *p = tolower(*p); 207 1.1 fvdl return (t); 208 1.1 fvdl } 209 1.3 christos #endif 210 1.1 fvdl 211 1.1 fvdl /* 212 1.1 fvdl * Returns the type of the network as defined in <rpc/nettype.h> 213 1.1 fvdl * If nettype is NULL, it defaults to NETPATH. 214 1.1 fvdl */ 215 1.1 fvdl static int 216 1.26 matt getnettype(const char *nettype) 217 1.1 fvdl { 218 1.1 fvdl int i; 219 1.1 fvdl 220 1.16 fvdl if ((nettype == NULL) || (nettype[0] == 0)) { 221 1.1 fvdl return (_RPC_NETPATH); /* Default */ 222 1.1 fvdl } 223 1.1 fvdl 224 1.3 christos #if 0 225 1.1 fvdl nettype = strlocase(nettype); 226 1.3 christos #endif 227 1.1 fvdl for (i = 0; _rpctypelist[i].name; i++) 228 1.3 christos if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 229 1.1 fvdl return (_rpctypelist[i].type); 230 1.1 fvdl } 231 1.1 fvdl return (_rpctypelist[i].type); 232 1.1 fvdl } 233 1.1 fvdl 234 1.1 fvdl /* 235 1.1 fvdl * For the given nettype (tcp or udp only), return the first structure found. 236 1.1 fvdl * This should be freed by calling freenetconfigent() 237 1.1 fvdl */ 238 1.12 thorpej 239 1.12 thorpej #ifdef _REENTRANT 240 1.12 thorpej static thread_key_t tcp_key, udp_key; 241 1.12 thorpej static once_t __rpc_getconfigp_once = ONCE_INITIALIZER; 242 1.12 thorpej 243 1.12 thorpej static void 244 1.12 thorpej __rpc_getconfigp_setup(void) 245 1.12 thorpej { 246 1.12 thorpej 247 1.12 thorpej thr_keycreate(&tcp_key, free); 248 1.12 thorpej thr_keycreate(&udp_key, free); 249 1.12 thorpej } 250 1.12 thorpej #endif 251 1.12 thorpej 252 1.1 fvdl struct netconfig * 253 1.26 matt __rpc_getconfip(const char *nettype) 254 1.1 fvdl { 255 1.1 fvdl char *netid; 256 1.23 christos char *netid_tcp = NULL; 257 1.23 christos char *netid_udp = NULL; 258 1.1 fvdl static char *netid_tcp_main; 259 1.1 fvdl static char *netid_udp_main; 260 1.1 fvdl struct netconfig *dummy; 261 1.12 thorpej #ifdef _REENTRANT 262 1.12 thorpej if (__isthreaded == 0) { 263 1.1 fvdl netid_udp = netid_udp_main; 264 1.1 fvdl netid_tcp = netid_tcp_main; 265 1.1 fvdl } else { 266 1.12 thorpej thr_once(&__rpc_getconfigp_once, __rpc_getconfigp_setup); 267 1.12 thorpej netid_tcp = thr_getspecific(tcp_key); 268 1.12 thorpej netid_udp = thr_getspecific(udp_key); 269 1.1 fvdl } 270 1.1 fvdl #else 271 1.1 fvdl netid_udp = netid_udp_main; 272 1.1 fvdl netid_tcp = netid_tcp_main; 273 1.1 fvdl #endif 274 1.5 lukem 275 1.5 lukem _DIAGASSERT(nettype != NULL); 276 1.5 lukem 277 1.1 fvdl if (!netid_udp && !netid_tcp) { 278 1.1 fvdl struct netconfig *nconf; 279 1.1 fvdl void *confighandle; 280 1.1 fvdl 281 1.1 fvdl if (!(confighandle = setnetconfig())) { 282 1.2 assar syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 283 1.1 fvdl return (NULL); 284 1.1 fvdl } 285 1.3 christos while ((nconf = getnetconfig(confighandle)) != NULL) { 286 1.1 fvdl if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 287 1.1 fvdl if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 288 1.1 fvdl netid_tcp = strdup(nconf->nc_netid); 289 1.23 christos if (netid_tcp == NULL) 290 1.23 christos return NULL; 291 1.12 thorpej #ifdef _REENTRANT 292 1.12 thorpej if (__isthreaded == 0) 293 1.1 fvdl netid_tcp_main = netid_tcp; 294 1.1 fvdl else 295 1.1 fvdl thr_setspecific(tcp_key, 296 1.1 fvdl (void *) netid_tcp); 297 1.1 fvdl #else 298 1.1 fvdl netid_tcp_main = netid_tcp; 299 1.1 fvdl #endif 300 1.1 fvdl } else 301 1.1 fvdl if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 302 1.1 fvdl netid_udp = strdup(nconf->nc_netid); 303 1.23 christos if (netid_udp == NULL) 304 1.23 christos return NULL; 305 1.12 thorpej #ifdef _REENTRANT 306 1.12 thorpej if (__isthreaded == 0) 307 1.1 fvdl netid_udp_main = netid_udp; 308 1.1 fvdl else 309 1.1 fvdl thr_setspecific(udp_key, 310 1.1 fvdl (void *) netid_udp); 311 1.1 fvdl #else 312 1.1 fvdl netid_udp_main = netid_udp; 313 1.1 fvdl #endif 314 1.1 fvdl } 315 1.1 fvdl } 316 1.1 fvdl } 317 1.1 fvdl endnetconfig(confighandle); 318 1.1 fvdl } 319 1.1 fvdl if (strcmp(nettype, "udp") == 0) 320 1.1 fvdl netid = netid_udp; 321 1.1 fvdl else if (strcmp(nettype, "tcp") == 0) 322 1.1 fvdl netid = netid_tcp; 323 1.1 fvdl else { 324 1.3 christos return (NULL); 325 1.1 fvdl } 326 1.16 fvdl if ((netid == NULL) || (netid[0] == 0)) { 327 1.3 christos return (NULL); 328 1.1 fvdl } 329 1.1 fvdl dummy = getnetconfigent(netid); 330 1.1 fvdl return (dummy); 331 1.1 fvdl } 332 1.1 fvdl 333 1.1 fvdl /* 334 1.1 fvdl * Returns the type of the nettype, which should then be used with 335 1.1 fvdl * __rpc_getconf(). 336 1.1 fvdl */ 337 1.1 fvdl void * 338 1.26 matt __rpc_setconf(const char *nettype) 339 1.1 fvdl { 340 1.1 fvdl struct handle *handle; 341 1.1 fvdl 342 1.5 lukem /* nettype may be NULL; getnettype() supports that */ 343 1.5 lukem 344 1.23 christos handle = malloc(sizeof(*handle)); 345 1.1 fvdl if (handle == NULL) { 346 1.1 fvdl return (NULL); 347 1.1 fvdl } 348 1.1 fvdl switch (handle->nettype = getnettype(nettype)) { 349 1.1 fvdl case _RPC_NETPATH: 350 1.1 fvdl case _RPC_CIRCUIT_N: 351 1.1 fvdl case _RPC_DATAGRAM_N: 352 1.1 fvdl if (!(handle->nhandle = setnetpath())) { 353 1.1 fvdl free(handle); 354 1.1 fvdl return (NULL); 355 1.1 fvdl } 356 1.1 fvdl handle->nflag = TRUE; 357 1.1 fvdl break; 358 1.1 fvdl case _RPC_VISIBLE: 359 1.1 fvdl case _RPC_CIRCUIT_V: 360 1.1 fvdl case _RPC_DATAGRAM_V: 361 1.1 fvdl case _RPC_TCP: 362 1.1 fvdl case _RPC_UDP: 363 1.1 fvdl if (!(handle->nhandle = setnetconfig())) { 364 1.2 assar syslog (LOG_ERR, "rpc: failed to open " NETCONFIG); 365 1.1 fvdl free(handle); 366 1.1 fvdl return (NULL); 367 1.1 fvdl } 368 1.1 fvdl handle->nflag = FALSE; 369 1.1 fvdl break; 370 1.1 fvdl default: 371 1.21 christos free(handle); 372 1.1 fvdl return (NULL); 373 1.1 fvdl } 374 1.1 fvdl 375 1.1 fvdl return (handle); 376 1.1 fvdl } 377 1.1 fvdl 378 1.1 fvdl /* 379 1.1 fvdl * Returns the next netconfig struct for the given "net" type. 380 1.1 fvdl * __rpc_setconf() should have been called previously. 381 1.1 fvdl */ 382 1.1 fvdl struct netconfig * 383 1.26 matt __rpc_getconf(void *vhandle) 384 1.1 fvdl { 385 1.1 fvdl struct handle *handle; 386 1.1 fvdl struct netconfig *nconf; 387 1.1 fvdl 388 1.1 fvdl handle = (struct handle *)vhandle; 389 1.1 fvdl if (handle == NULL) { 390 1.1 fvdl return (NULL); 391 1.1 fvdl } 392 1.3 christos for (;;) { 393 1.1 fvdl if (handle->nflag) 394 1.1 fvdl nconf = getnetpath(handle->nhandle); 395 1.1 fvdl else 396 1.1 fvdl nconf = getnetconfig(handle->nhandle); 397 1.3 christos if (nconf == NULL) 398 1.1 fvdl break; 399 1.1 fvdl if ((nconf->nc_semantics != NC_TPI_CLTS) && 400 1.1 fvdl (nconf->nc_semantics != NC_TPI_COTS) && 401 1.1 fvdl (nconf->nc_semantics != NC_TPI_COTS_ORD)) 402 1.1 fvdl continue; 403 1.1 fvdl switch (handle->nettype) { 404 1.1 fvdl case _RPC_VISIBLE: 405 1.1 fvdl if (!(nconf->nc_flag & NC_VISIBLE)) 406 1.1 fvdl continue; 407 1.1 fvdl /* FALLTHROUGH */ 408 1.1 fvdl case _RPC_NETPATH: /* Be happy */ 409 1.1 fvdl break; 410 1.1 fvdl case _RPC_CIRCUIT_V: 411 1.1 fvdl if (!(nconf->nc_flag & NC_VISIBLE)) 412 1.1 fvdl continue; 413 1.1 fvdl /* FALLTHROUGH */ 414 1.1 fvdl case _RPC_CIRCUIT_N: 415 1.1 fvdl if ((nconf->nc_semantics != NC_TPI_COTS) && 416 1.1 fvdl (nconf->nc_semantics != NC_TPI_COTS_ORD)) 417 1.1 fvdl continue; 418 1.1 fvdl break; 419 1.1 fvdl case _RPC_DATAGRAM_V: 420 1.1 fvdl if (!(nconf->nc_flag & NC_VISIBLE)) 421 1.1 fvdl continue; 422 1.1 fvdl /* FALLTHROUGH */ 423 1.1 fvdl case _RPC_DATAGRAM_N: 424 1.1 fvdl if (nconf->nc_semantics != NC_TPI_CLTS) 425 1.1 fvdl continue; 426 1.1 fvdl break; 427 1.1 fvdl case _RPC_TCP: 428 1.1 fvdl if (((nconf->nc_semantics != NC_TPI_COTS) && 429 1.1 fvdl (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 430 1.1 fvdl (strcmp(nconf->nc_protofmly, NC_INET) 431 1.1 fvdl #ifdef INET6 432 1.1 fvdl && strcmp(nconf->nc_protofmly, NC_INET6)) 433 1.1 fvdl #else 434 1.1 fvdl ) 435 1.1 fvdl #endif 436 1.1 fvdl || 437 1.1 fvdl strcmp(nconf->nc_proto, NC_TCP)) 438 1.1 fvdl continue; 439 1.1 fvdl break; 440 1.1 fvdl case _RPC_UDP: 441 1.1 fvdl if ((nconf->nc_semantics != NC_TPI_CLTS) || 442 1.1 fvdl (strcmp(nconf->nc_protofmly, NC_INET) 443 1.1 fvdl #ifdef INET6 444 1.1 fvdl && strcmp(nconf->nc_protofmly, NC_INET6)) 445 1.1 fvdl #else 446 1.1 fvdl ) 447 1.1 fvdl #endif 448 1.1 fvdl || 449 1.1 fvdl strcmp(nconf->nc_proto, NC_UDP)) 450 1.1 fvdl continue; 451 1.1 fvdl break; 452 1.1 fvdl } 453 1.1 fvdl break; 454 1.1 fvdl } 455 1.1 fvdl return (nconf); 456 1.1 fvdl } 457 1.1 fvdl 458 1.1 fvdl void 459 1.26 matt __rpc_endconf(void *vhandle) 460 1.1 fvdl { 461 1.1 fvdl struct handle *handle; 462 1.1 fvdl 463 1.1 fvdl handle = (struct handle *) vhandle; 464 1.1 fvdl if (handle == NULL) { 465 1.1 fvdl return; 466 1.1 fvdl } 467 1.1 fvdl if (handle->nflag) { 468 1.1 fvdl endnetpath(handle->nhandle); 469 1.1 fvdl } else { 470 1.1 fvdl endnetconfig(handle->nhandle); 471 1.1 fvdl } 472 1.1 fvdl free(handle); 473 1.1 fvdl } 474 1.1 fvdl 475 1.1 fvdl /* 476 1.1 fvdl * Used to ping the NULL procedure for clnt handle. 477 1.1 fvdl * Returns NULL if fails, else a non-NULL pointer. 478 1.1 fvdl */ 479 1.1 fvdl void * 480 1.26 matt rpc_nullproc(CLIENT *clnt) 481 1.1 fvdl { 482 1.1 fvdl struct timeval TIMEOUT = {25, 0}; 483 1.1 fvdl 484 1.3 christos if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 485 1.3 christos (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 486 1.3 christos return (NULL); 487 1.1 fvdl } 488 1.1 fvdl return ((void *) clnt); 489 1.1 fvdl } 490 1.1 fvdl 491 1.1 fvdl /* 492 1.1 fvdl * Try all possible transports until 493 1.1 fvdl * one succeeds in finding the netconf for the given fd. 494 1.1 fvdl */ 495 1.1 fvdl struct netconfig * 496 1.26 matt __rpcgettp(int fd) 497 1.1 fvdl { 498 1.1 fvdl const char *netid; 499 1.1 fvdl struct __rpc_sockinfo si; 500 1.1 fvdl 501 1.1 fvdl if (!__rpc_fd2sockinfo(fd, &si)) 502 1.1 fvdl return NULL; 503 1.1 fvdl 504 1.1 fvdl if (!__rpc_sockinfo2netid(&si, &netid)) 505 1.1 fvdl return NULL; 506 1.1 fvdl 507 1.20 christos return getnetconfigent(__UNCONST(netid)); 508 1.1 fvdl } 509 1.1 fvdl 510 1.1 fvdl int 511 1.1 fvdl __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip) 512 1.1 fvdl { 513 1.1 fvdl socklen_t len; 514 1.1 fvdl int type, proto; 515 1.1 fvdl struct sockaddr_storage ss; 516 1.1 fvdl 517 1.5 lukem _DIAGASSERT(sip != NULL); 518 1.5 lukem 519 1.1 fvdl len = sizeof ss; 520 1.3 christos if (getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0) 521 1.1 fvdl return 0; 522 1.1 fvdl sip->si_alen = len; 523 1.1 fvdl 524 1.1 fvdl len = sizeof type; 525 1.1 fvdl if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) 526 1.1 fvdl return 0; 527 1.1 fvdl 528 1.1 fvdl /* XXX */ 529 1.1 fvdl if (ss.ss_family != AF_LOCAL) { 530 1.1 fvdl if (type == SOCK_STREAM) 531 1.1 fvdl proto = IPPROTO_TCP; 532 1.1 fvdl else if (type == SOCK_DGRAM) 533 1.1 fvdl proto = IPPROTO_UDP; 534 1.1 fvdl else 535 1.1 fvdl return 0; 536 1.1 fvdl } else 537 1.1 fvdl proto = 0; 538 1.1 fvdl 539 1.1 fvdl sip->si_af = ss.ss_family; 540 1.1 fvdl sip->si_proto = proto; 541 1.1 fvdl sip->si_socktype = type; 542 1.1 fvdl 543 1.1 fvdl return 1; 544 1.1 fvdl } 545 1.1 fvdl 546 1.1 fvdl /* 547 1.1 fvdl * Linear search, but the number of entries is small. 548 1.1 fvdl */ 549 1.1 fvdl int 550 1.1 fvdl __rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 551 1.1 fvdl { 552 1.11 thorpej size_t i; 553 1.1 fvdl 554 1.5 lukem _DIAGASSERT(nconf != NULL); 555 1.5 lukem _DIAGASSERT(sip != NULL); 556 1.5 lukem 557 1.1 fvdl for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 558 1.1 fvdl if (!strcmp(na_cvt[i].netid, nconf->nc_netid)) { 559 1.1 fvdl sip->si_af = na_cvt[i].af; 560 1.1 fvdl sip->si_proto = na_cvt[i].protocol; 561 1.1 fvdl sip->si_socktype = 562 1.3 christos __rpc_seman2socktype((int)nconf->nc_semantics); 563 1.1 fvdl if (sip->si_socktype == -1) 564 1.1 fvdl return 0; 565 1.1 fvdl sip->si_alen = __rpc_get_a_size(sip->si_af); 566 1.1 fvdl return 1; 567 1.1 fvdl } 568 1.1 fvdl 569 1.1 fvdl return 0; 570 1.1 fvdl } 571 1.1 fvdl 572 1.1 fvdl int 573 1.1 fvdl __rpc_nconf2fd(const struct netconfig *nconf) 574 1.1 fvdl { 575 1.1 fvdl struct __rpc_sockinfo si; 576 1.1 fvdl 577 1.5 lukem _DIAGASSERT(nconf != NULL); 578 1.5 lukem 579 1.1 fvdl if (!__rpc_nconf2sockinfo(nconf, &si)) 580 1.1 fvdl return 0; 581 1.1 fvdl 582 1.1 fvdl return socket(si.si_af, si.si_socktype, si.si_proto); 583 1.1 fvdl } 584 1.1 fvdl 585 1.1 fvdl int 586 1.1 fvdl __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid) 587 1.1 fvdl { 588 1.11 thorpej size_t i; 589 1.1 fvdl 590 1.5 lukem _DIAGASSERT(sip != NULL); 591 1.5 lukem /* netid may be NULL */ 592 1.5 lukem 593 1.1 fvdl for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 594 1.1 fvdl if (na_cvt[i].af == sip->si_af && 595 1.1 fvdl na_cvt[i].protocol == sip->si_proto) { 596 1.1 fvdl if (netid) 597 1.1 fvdl *netid = na_cvt[i].netid; 598 1.1 fvdl return 1; 599 1.1 fvdl } 600 1.1 fvdl 601 1.1 fvdl return 0; 602 1.1 fvdl } 603 1.1 fvdl 604 1.1 fvdl char * 605 1.1 fvdl taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 606 1.1 fvdl { 607 1.1 fvdl struct __rpc_sockinfo si; 608 1.1 fvdl 609 1.5 lukem _DIAGASSERT(nconf != NULL); 610 1.5 lukem _DIAGASSERT(nbuf != NULL); 611 1.5 lukem 612 1.1 fvdl if (!__rpc_nconf2sockinfo(nconf, &si)) 613 1.1 fvdl return NULL; 614 1.1 fvdl return __rpc_taddr2uaddr_af(si.si_af, nbuf); 615 1.1 fvdl } 616 1.1 fvdl 617 1.1 fvdl struct netbuf * 618 1.1 fvdl uaddr2taddr(const struct netconfig *nconf, const char *uaddr) 619 1.1 fvdl { 620 1.1 fvdl struct __rpc_sockinfo si; 621 1.5 lukem 622 1.5 lukem _DIAGASSERT(nconf != NULL); 623 1.5 lukem _DIAGASSERT(uaddr != NULL); 624 1.1 fvdl 625 1.1 fvdl if (!__rpc_nconf2sockinfo(nconf, &si)) 626 1.1 fvdl return NULL; 627 1.1 fvdl return __rpc_uaddr2taddr_af(si.si_af, uaddr); 628 1.1 fvdl } 629 1.1 fvdl 630 1.1 fvdl char * 631 1.1 fvdl __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 632 1.1 fvdl { 633 1.1 fvdl char *ret; 634 1.9 lukem struct sockaddr_in *sinp; 635 1.1 fvdl struct sockaddr_un *sun; 636 1.1 fvdl char namebuf[INET_ADDRSTRLEN]; 637 1.1 fvdl #ifdef INET6 638 1.1 fvdl struct sockaddr_in6 *sin6; 639 1.1 fvdl char namebuf6[INET6_ADDRSTRLEN]; 640 1.1 fvdl #endif 641 1.1 fvdl u_int16_t port; 642 1.1 fvdl 643 1.5 lukem _DIAGASSERT(nbuf != NULL); 644 1.5 lukem 645 1.1 fvdl switch (af) { 646 1.1 fvdl case AF_INET: 647 1.30 christos if (nbuf->len < sizeof(*sinp)) { 648 1.30 christos return NULL; 649 1.30 christos } 650 1.9 lukem sinp = nbuf->buf; 651 1.25 christos if (inet_ntop(af, &sinp->sin_addr, namebuf, 652 1.25 christos (socklen_t)sizeof namebuf) == NULL) 653 1.1 fvdl return NULL; 654 1.9 lukem port = ntohs(sinp->sin_port); 655 1.3 christos if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8, 656 1.3 christos port & 0xff) < 0) 657 1.1 fvdl return NULL; 658 1.1 fvdl break; 659 1.1 fvdl #ifdef INET6 660 1.1 fvdl case AF_INET6: 661 1.30 christos if (nbuf->len < sizeof(*sin6)) { 662 1.30 christos return NULL; 663 1.30 christos } 664 1.1 fvdl sin6 = nbuf->buf; 665 1.25 christos if (inet_ntop(af, &sin6->sin6_addr, namebuf6, 666 1.25 christos (socklen_t)sizeof namebuf6) == NULL) 667 1.1 fvdl return NULL; 668 1.1 fvdl port = ntohs(sin6->sin6_port); 669 1.3 christos if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8, 670 1.3 christos port & 0xff) < 0) 671 1.1 fvdl return NULL; 672 1.1 fvdl break; 673 1.1 fvdl #endif 674 1.1 fvdl case AF_LOCAL: 675 1.1 fvdl sun = nbuf->buf; 676 1.1 fvdl sun->sun_path[sizeof(sun->sun_path) - 1] = '\0'; /* safety */ 677 1.1 fvdl ret = strdup(sun->sun_path); 678 1.1 fvdl break; 679 1.1 fvdl default: 680 1.1 fvdl return NULL; 681 1.1 fvdl } 682 1.1 fvdl 683 1.1 fvdl return ret; 684 1.1 fvdl } 685 1.1 fvdl 686 1.1 fvdl struct netbuf * 687 1.1 fvdl __rpc_uaddr2taddr_af(int af, const char *uaddr) 688 1.1 fvdl { 689 1.1 fvdl struct netbuf *ret = NULL; 690 1.1 fvdl char *addrstr, *p; 691 1.1 fvdl unsigned port, portlo, porthi; 692 1.25 christos size_t len; 693 1.9 lukem struct sockaddr_in *sinp; 694 1.1 fvdl #ifdef INET6 695 1.1 fvdl struct sockaddr_in6 *sin6; 696 1.1 fvdl #endif 697 1.1 fvdl struct sockaddr_un *sun; 698 1.1 fvdl 699 1.30 christos if (uaddr == NULL) 700 1.30 christos return NULL; 701 1.5 lukem 702 1.1 fvdl addrstr = strdup(uaddr); 703 1.1 fvdl if (addrstr == NULL) 704 1.1 fvdl return NULL; 705 1.1 fvdl 706 1.1 fvdl /* 707 1.1 fvdl * AF_LOCAL addresses are expected to be absolute 708 1.1 fvdl * pathnames, anything else will be AF_INET or AF_INET6. 709 1.1 fvdl */ 710 1.19 lukem port = 0; 711 1.1 fvdl if (*addrstr != '/') { 712 1.1 fvdl p = strrchr(addrstr, '.'); 713 1.1 fvdl if (p == NULL) 714 1.1 fvdl goto out; 715 1.1 fvdl portlo = (unsigned)atoi(p + 1); 716 1.1 fvdl *p = '\0'; 717 1.1 fvdl 718 1.1 fvdl p = strrchr(addrstr, '.'); 719 1.1 fvdl if (p == NULL) 720 1.1 fvdl goto out; 721 1.1 fvdl porthi = (unsigned)atoi(p + 1); 722 1.1 fvdl *p = '\0'; 723 1.1 fvdl port = (porthi << 8) | portlo; 724 1.1 fvdl } 725 1.1 fvdl 726 1.23 christos ret = malloc(sizeof(*ret)); 727 1.8 kristerw if (ret == NULL) 728 1.8 kristerw goto out; 729 1.1 fvdl 730 1.1 fvdl switch (af) { 731 1.1 fvdl case AF_INET: 732 1.23 christos sinp = malloc(sizeof(*sinp)); 733 1.9 lukem if (sinp == NULL) 734 1.1 fvdl goto out; 735 1.9 lukem memset(sinp, 0, sizeof *sinp); 736 1.9 lukem sinp->sin_family = AF_INET; 737 1.9 lukem sinp->sin_port = htons(port); 738 1.9 lukem if (inet_pton(AF_INET, addrstr, &sinp->sin_addr) <= 0) { 739 1.9 lukem free(sinp); 740 1.1 fvdl free(ret); 741 1.1 fvdl ret = NULL; 742 1.1 fvdl goto out; 743 1.1 fvdl } 744 1.9 lukem sinp->sin_len = ret->maxlen = ret->len = sizeof *sinp; 745 1.9 lukem ret->buf = sinp; 746 1.1 fvdl break; 747 1.1 fvdl #ifdef INET6 748 1.1 fvdl case AF_INET6: 749 1.23 christos sin6 = malloc(sizeof(*sin6)); 750 1.1 fvdl if (sin6 == NULL) 751 1.1 fvdl goto out; 752 1.1 fvdl memset(sin6, 0, sizeof *sin6); 753 1.1 fvdl sin6->sin6_family = AF_INET6; 754 1.1 fvdl sin6->sin6_port = htons(port); 755 1.1 fvdl if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 756 1.8 kristerw free(sin6); 757 1.1 fvdl free(ret); 758 1.1 fvdl ret = NULL; 759 1.1 fvdl goto out; 760 1.1 fvdl } 761 1.1 fvdl sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 762 1.1 fvdl ret->buf = sin6; 763 1.1 fvdl break; 764 1.1 fvdl #endif 765 1.1 fvdl case AF_LOCAL: 766 1.23 christos sun = malloc(sizeof(*sun)); 767 1.1 fvdl if (sun == NULL) 768 1.1 fvdl goto out; 769 1.1 fvdl memset(sun, 0, sizeof *sun); 770 1.1 fvdl sun->sun_family = AF_LOCAL; 771 1.1 fvdl strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 772 1.25 christos len = SUN_LEN(sun); 773 1.25 christos _DIAGASSERT(__type_fit(uint8_t, len)); 774 1.25 christos ret->len = ret->maxlen = sun->sun_len = (uint8_t)len; 775 1.7 fvdl ret->buf = sun; 776 1.3 christos break; 777 1.1 fvdl default: 778 1.1 fvdl break; 779 1.1 fvdl } 780 1.1 fvdl out: 781 1.1 fvdl free(addrstr); 782 1.1 fvdl return ret; 783 1.1 fvdl } 784 1.1 fvdl 785 1.1 fvdl int 786 1.1 fvdl __rpc_seman2socktype(int semantics) 787 1.1 fvdl { 788 1.1 fvdl switch (semantics) { 789 1.1 fvdl case NC_TPI_CLTS: 790 1.1 fvdl return SOCK_DGRAM; 791 1.1 fvdl case NC_TPI_COTS_ORD: 792 1.1 fvdl return SOCK_STREAM; 793 1.1 fvdl case NC_TPI_RAW: 794 1.1 fvdl return SOCK_RAW; 795 1.1 fvdl default: 796 1.1 fvdl break; 797 1.1 fvdl } 798 1.1 fvdl 799 1.1 fvdl return -1; 800 1.1 fvdl } 801 1.1 fvdl 802 1.1 fvdl int 803 1.1 fvdl __rpc_socktype2seman(int socktype) 804 1.1 fvdl { 805 1.1 fvdl switch (socktype) { 806 1.1 fvdl case SOCK_DGRAM: 807 1.1 fvdl return NC_TPI_CLTS; 808 1.1 fvdl case SOCK_STREAM: 809 1.1 fvdl return NC_TPI_COTS_ORD; 810 1.1 fvdl case SOCK_RAW: 811 1.1 fvdl return NC_TPI_RAW; 812 1.1 fvdl default: 813 1.1 fvdl break; 814 1.1 fvdl } 815 1.1 fvdl 816 1.1 fvdl return -1; 817 1.1 fvdl } 818 1.1 fvdl 819 1.1 fvdl /* 820 1.1 fvdl * XXXX - IPv6 scope IDs can't be handled in universal addresses. 821 1.1 fvdl * Here, we compare the original server address to that of the RPC 822 1.1 fvdl * service we just received back from a call to rpcbind on the remote 823 1.1 fvdl * machine. If they are both "link local" or "site local", copy 824 1.1 fvdl * the scope id of the server address over to the service address. 825 1.1 fvdl */ 826 1.17 lukem /* ARGSUSED */ 827 1.1 fvdl int 828 1.1 fvdl __rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc) 829 1.1 fvdl { 830 1.1 fvdl #ifdef INET6 831 1.1 fvdl struct sockaddr *sa_new, *sa_svc; 832 1.1 fvdl struct sockaddr_in6 *sin6_new, *sin6_svc; 833 1.5 lukem 834 1.5 lukem _DIAGASSERT(new != NULL); 835 1.5 lukem _DIAGASSERT(svc != NULL); 836 1.1 fvdl 837 1.1 fvdl sa_svc = (struct sockaddr *)svc->buf; 838 1.1 fvdl sa_new = (struct sockaddr *)new->buf; 839 1.1 fvdl 840 1.1 fvdl if (sa_new->sa_family == sa_svc->sa_family && 841 1.1 fvdl sa_new->sa_family == AF_INET6) { 842 1.1 fvdl sin6_new = (struct sockaddr_in6 *)new->buf; 843 1.1 fvdl sin6_svc = (struct sockaddr_in6 *)svc->buf; 844 1.1 fvdl 845 1.1 fvdl if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) && 846 1.1 fvdl IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) || 847 1.1 fvdl (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) && 848 1.1 fvdl IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) { 849 1.1 fvdl sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id; 850 1.1 fvdl } 851 1.1 fvdl } 852 1.1 fvdl #endif 853 1.1 fvdl return 1; 854 1.1 fvdl } 855 1.1 fvdl 856 1.1 fvdl int 857 1.1 fvdl __rpc_sockisbound(int fd) 858 1.1 fvdl { 859 1.1 fvdl struct sockaddr_storage ss; 860 1.1 fvdl socklen_t slen; 861 1.1 fvdl 862 1.1 fvdl slen = sizeof (struct sockaddr_storage); 863 1.3 christos if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) 864 1.1 fvdl return 0; 865 1.1 fvdl 866 1.1 fvdl switch (ss.ss_family) { 867 1.1 fvdl case AF_INET: 868 1.3 christos return (((struct sockaddr_in *) 869 1.3 christos (void *)&ss)->sin_port != 0); 870 1.1 fvdl #ifdef INET6 871 1.1 fvdl case AF_INET6: 872 1.3 christos return (((struct sockaddr_in6 *) 873 1.3 christos (void *)&ss)->sin6_port != 0); 874 1.1 fvdl #endif 875 1.1 fvdl case AF_LOCAL: 876 1.1 fvdl /* XXX check this */ 877 1.3 christos return (((struct sockaddr_un *) 878 1.3 christos (void *)&ss)->sun_path[0] != '\0'); 879 1.1 fvdl default: 880 1.1 fvdl break; 881 1.1 fvdl } 882 1.1 fvdl 883 1.1 fvdl return 0; 884 1.1 fvdl } 885 1.22 christos 886 1.22 christos /* 887 1.22 christos * For TCP transport, Host Requirements RFCs mandate 888 1.22 christos * Nagle (RFC-896) processing. But for RPC, Nagle 889 1.22 christos * processing adds adds unwanted latency to the last, 890 1.22 christos * partial TCP segment of each RPC message. See: 891 1.22 christos * R. W. Scheifler and J. Gettys, The X Window System, 892 1.22 christos * ACM Transactions on Graphics 16:8 (Aug. 1983), pp. 57-69. 893 1.22 christos * So for TCP transport, disable Nagle via TCP_NODELAY. 894 1.22 christos * XXX: moral equivalent for non-TCP protocols? 895 1.22 christos */ 896 1.22 christos int 897 1.22 christos __rpc_setnodelay(int fd, const struct __rpc_sockinfo *si) 898 1.22 christos { 899 1.22 christos int one = 1; 900 1.22 christos if (si->si_proto != IPPROTO_TCP) 901 1.22 christos return 0; 902 1.25 christos return setsockopt(fd, si->si_proto, TCP_NODELAY, &one, 903 1.25 christos (socklen_t)sizeof(one)); 904 1.22 christos } 905