rpc_generic.c revision 177633
1177633Sdfr/* $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ */ 2177633Sdfr 3177633Sdfr/* 4177633Sdfr * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5177633Sdfr * unrestricted use provided that this legend is included on all tape 6177633Sdfr * media and as a part of the software program in whole or part. Users 7177633Sdfr * may copy or modify Sun RPC without charge, but are not authorized 8177633Sdfr * to license or distribute it to anyone else except as part of a product or 9177633Sdfr * program developed by the user. 10177633Sdfr * 11177633Sdfr * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12177633Sdfr * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13177633Sdfr * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14177633Sdfr * 15177633Sdfr * Sun RPC is provided with no support and without any obligation on the 16177633Sdfr * part of Sun Microsystems, Inc. to assist in its use, correction, 17177633Sdfr * modification or enhancement. 18177633Sdfr * 19177633Sdfr * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20177633Sdfr * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21177633Sdfr * OR ANY PART THEREOF. 22177633Sdfr * 23177633Sdfr * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24177633Sdfr * or profits or other special, indirect and consequential damages, even if 25177633Sdfr * Sun has been advised of the possibility of such damages. 26177633Sdfr * 27177633Sdfr * Sun Microsystems, Inc. 28177633Sdfr * 2550 Garcia Avenue 29177633Sdfr * Mountain View, California 94043 30177633Sdfr */ 31177633Sdfr/* 32177633Sdfr * Copyright (c) 1986-1991 by Sun Microsystems Inc. 33177633Sdfr */ 34177633Sdfr 35177633Sdfr/* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */ 36177633Sdfr#include <sys/cdefs.h> 37177633Sdfr__FBSDID("$FreeBSD: head/sys/rpc/rpc_generic.c 177633 2008-03-26 15:23:12Z dfr $"); 38177633Sdfr 39177633Sdfr/* 40177633Sdfr * rpc_generic.c, Miscl routines for RPC. 41177633Sdfr * 42177633Sdfr */ 43177633Sdfr 44177633Sdfr#include "opt_inet6.h" 45177633Sdfr 46177633Sdfr#include <sys/param.h> 47177633Sdfr#include <sys/malloc.h> 48177633Sdfr#include <sys/proc.h> 49177633Sdfr#include <sys/protosw.h> 50177633Sdfr#include <sys/sbuf.h> 51177633Sdfr#include <sys/systm.h> 52177633Sdfr#include <sys/socket.h> 53177633Sdfr#include <sys/socketvar.h> 54177633Sdfr#include <sys/syslog.h> 55177633Sdfr 56177633Sdfr#include <rpc/rpc.h> 57177633Sdfr#include <rpc/nettype.h> 58177633Sdfr 59177633Sdfr#include "rpc_com.h" 60177633Sdfr 61177633Sdfrstruct handle { 62177633Sdfr NCONF_HANDLE *nhandle; 63177633Sdfr int nflag; /* Whether NETPATH or NETCONFIG */ 64177633Sdfr int nettype; 65177633Sdfr}; 66177633Sdfr 67177633Sdfrstatic const struct _rpcnettype { 68177633Sdfr const char *name; 69177633Sdfr const int type; 70177633Sdfr} _rpctypelist[] = { 71177633Sdfr { "netpath", _RPC_NETPATH }, 72177633Sdfr { "visible", _RPC_VISIBLE }, 73177633Sdfr { "circuit_v", _RPC_CIRCUIT_V }, 74177633Sdfr { "datagram_v", _RPC_DATAGRAM_V }, 75177633Sdfr { "circuit_n", _RPC_CIRCUIT_N }, 76177633Sdfr { "datagram_n", _RPC_DATAGRAM_N }, 77177633Sdfr { "tcp", _RPC_TCP }, 78177633Sdfr { "udp", _RPC_UDP }, 79177633Sdfr { 0, _RPC_NONE } 80177633Sdfr}; 81177633Sdfr 82177633Sdfrstruct netid_af { 83177633Sdfr const char *netid; 84177633Sdfr int af; 85177633Sdfr int protocol; 86177633Sdfr}; 87177633Sdfr 88177633Sdfrstatic const struct netid_af na_cvt[] = { 89177633Sdfr { "udp", AF_INET, IPPROTO_UDP }, 90177633Sdfr { "tcp", AF_INET, IPPROTO_TCP }, 91177633Sdfr#ifdef INET6 92177633Sdfr { "udp6", AF_INET6, IPPROTO_UDP }, 93177633Sdfr { "tcp6", AF_INET6, IPPROTO_TCP }, 94177633Sdfr#endif 95177633Sdfr { "local", AF_LOCAL, 0 } 96177633Sdfr}; 97177633Sdfr 98177633Sdfrstruct rpc_createerr rpc_createerr; 99177633Sdfr 100177633Sdfr/* 101177633Sdfr * Find the appropriate buffer size 102177633Sdfr */ 103177633Sdfru_int 104177633Sdfr/*ARGSUSED*/ 105177633Sdfr__rpc_get_t_size(int af, int proto, int size) 106177633Sdfr{ 107177633Sdfr int maxsize, defsize; 108177633Sdfr 109177633Sdfr maxsize = 256 * 1024; /* XXX */ 110177633Sdfr switch (proto) { 111177633Sdfr case IPPROTO_TCP: 112177633Sdfr defsize = 64 * 1024; /* XXX */ 113177633Sdfr break; 114177633Sdfr case IPPROTO_UDP: 115177633Sdfr defsize = UDPMSGSIZE; 116177633Sdfr break; 117177633Sdfr default: 118177633Sdfr defsize = RPC_MAXDATASIZE; 119177633Sdfr break; 120177633Sdfr } 121177633Sdfr if (size == 0) 122177633Sdfr return defsize; 123177633Sdfr 124177633Sdfr /* Check whether the value is within the upper max limit */ 125177633Sdfr return (size > maxsize ? (u_int)maxsize : (u_int)size); 126177633Sdfr} 127177633Sdfr 128177633Sdfr/* 129177633Sdfr * Find the appropriate address buffer size 130177633Sdfr */ 131177633Sdfru_int 132177633Sdfr__rpc_get_a_size(af) 133177633Sdfr int af; 134177633Sdfr{ 135177633Sdfr switch (af) { 136177633Sdfr case AF_INET: 137177633Sdfr return sizeof (struct sockaddr_in); 138177633Sdfr#ifdef INET6 139177633Sdfr case AF_INET6: 140177633Sdfr return sizeof (struct sockaddr_in6); 141177633Sdfr#endif 142177633Sdfr case AF_LOCAL: 143177633Sdfr return sizeof (struct sockaddr_un); 144177633Sdfr default: 145177633Sdfr break; 146177633Sdfr } 147177633Sdfr return ((u_int)RPC_MAXADDRSIZE); 148177633Sdfr} 149177633Sdfr 150177633Sdfr#if 0 151177633Sdfr 152177633Sdfr/* 153177633Sdfr * Used to ping the NULL procedure for clnt handle. 154177633Sdfr * Returns NULL if fails, else a non-NULL pointer. 155177633Sdfr */ 156177633Sdfrvoid * 157177633Sdfrrpc_nullproc(clnt) 158177633Sdfr CLIENT *clnt; 159177633Sdfr{ 160177633Sdfr struct timeval TIMEOUT = {25, 0}; 161177633Sdfr 162177633Sdfr if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 163177633Sdfr (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 164177633Sdfr return (NULL); 165177633Sdfr } 166177633Sdfr return ((void *) clnt); 167177633Sdfr} 168177633Sdfr 169177633Sdfr#endif 170177633Sdfr 171177633Sdfrint 172177633Sdfr__rpc_socket2sockinfo(struct socket *so, struct __rpc_sockinfo *sip) 173177633Sdfr{ 174177633Sdfr int type, proto; 175177633Sdfr struct sockaddr *sa; 176177633Sdfr sa_family_t family; 177177633Sdfr struct sockopt opt; 178177633Sdfr int error; 179177633Sdfr 180177633Sdfr error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); 181177633Sdfr if (error) 182177633Sdfr return 0; 183177633Sdfr 184177633Sdfr sip->si_alen = sa->sa_len; 185177633Sdfr family = sa->sa_family; 186177633Sdfr free(sa, M_SONAME); 187177633Sdfr 188177633Sdfr opt.sopt_dir = SOPT_GET; 189177633Sdfr opt.sopt_level = SOL_SOCKET; 190177633Sdfr opt.sopt_name = SO_TYPE; 191177633Sdfr opt.sopt_val = &type; 192177633Sdfr opt.sopt_valsize = sizeof type; 193177633Sdfr opt.sopt_td = NULL; 194177633Sdfr error = sogetopt(so, &opt); 195177633Sdfr if (error) 196177633Sdfr return 0; 197177633Sdfr 198177633Sdfr /* XXX */ 199177633Sdfr if (family != AF_LOCAL) { 200177633Sdfr if (type == SOCK_STREAM) 201177633Sdfr proto = IPPROTO_TCP; 202177633Sdfr else if (type == SOCK_DGRAM) 203177633Sdfr proto = IPPROTO_UDP; 204177633Sdfr else 205177633Sdfr return 0; 206177633Sdfr } else 207177633Sdfr proto = 0; 208177633Sdfr 209177633Sdfr sip->si_af = family; 210177633Sdfr sip->si_proto = proto; 211177633Sdfr sip->si_socktype = type; 212177633Sdfr 213177633Sdfr return 1; 214177633Sdfr} 215177633Sdfr 216177633Sdfr/* 217177633Sdfr * Linear search, but the number of entries is small. 218177633Sdfr */ 219177633Sdfrint 220177633Sdfr__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 221177633Sdfr{ 222177633Sdfr int i; 223177633Sdfr 224177633Sdfr for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 225177633Sdfr if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 226177633Sdfr strcmp(nconf->nc_netid, "unix") == 0 && 227177633Sdfr strcmp(na_cvt[i].netid, "local") == 0)) { 228177633Sdfr sip->si_af = na_cvt[i].af; 229177633Sdfr sip->si_proto = na_cvt[i].protocol; 230177633Sdfr sip->si_socktype = 231177633Sdfr __rpc_seman2socktype((int)nconf->nc_semantics); 232177633Sdfr if (sip->si_socktype == -1) 233177633Sdfr return 0; 234177633Sdfr sip->si_alen = __rpc_get_a_size(sip->si_af); 235177633Sdfr return 1; 236177633Sdfr } 237177633Sdfr 238177633Sdfr return 0; 239177633Sdfr} 240177633Sdfr 241177633Sdfrstruct socket * 242177633Sdfr__rpc_nconf2socket(const struct netconfig *nconf) 243177633Sdfr{ 244177633Sdfr struct __rpc_sockinfo si; 245177633Sdfr struct socket *so; 246177633Sdfr int error; 247177633Sdfr 248177633Sdfr if (!__rpc_nconf2sockinfo(nconf, &si)) 249177633Sdfr return 0; 250177633Sdfr 251177633Sdfr so = NULL; 252177633Sdfr error = socreate(si.si_af, &so, si.si_socktype, si.si_proto, 253177633Sdfr curthread->td_ucred, curthread); 254177633Sdfr 255177633Sdfr if (error) 256177633Sdfr return NULL; 257177633Sdfr else 258177633Sdfr return so; 259177633Sdfr} 260177633Sdfr 261177633Sdfrchar * 262177633Sdfrtaddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 263177633Sdfr{ 264177633Sdfr struct __rpc_sockinfo si; 265177633Sdfr 266177633Sdfr if (!__rpc_nconf2sockinfo(nconf, &si)) 267177633Sdfr return NULL; 268177633Sdfr return __rpc_taddr2uaddr_af(si.si_af, nbuf); 269177633Sdfr} 270177633Sdfr 271177633Sdfrstruct netbuf * 272177633Sdfruaddr2taddr(const struct netconfig *nconf, const char *uaddr) 273177633Sdfr{ 274177633Sdfr struct __rpc_sockinfo si; 275177633Sdfr 276177633Sdfr if (!__rpc_nconf2sockinfo(nconf, &si)) 277177633Sdfr return NULL; 278177633Sdfr return __rpc_uaddr2taddr_af(si.si_af, uaddr); 279177633Sdfr} 280177633Sdfr 281177633Sdfrchar * 282177633Sdfr__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 283177633Sdfr{ 284177633Sdfr char *ret; 285177633Sdfr struct sbuf sb; 286177633Sdfr struct sockaddr_in *sin; 287177633Sdfr struct sockaddr_un *sun; 288177633Sdfr char namebuf[INET_ADDRSTRLEN]; 289177633Sdfr#ifdef INET6 290177633Sdfr struct sockaddr_in6 *sin6; 291177633Sdfr char namebuf6[INET6_ADDRSTRLEN]; 292177633Sdfr#endif 293177633Sdfr u_int16_t port; 294177633Sdfr 295177633Sdfr sbuf_new(&sb, NULL, 0, SBUF_AUTOEXTEND); 296177633Sdfr 297177633Sdfr switch (af) { 298177633Sdfr case AF_INET: 299177633Sdfr sin = nbuf->buf; 300177633Sdfr if (__rpc_inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) 301177633Sdfr == NULL) 302177633Sdfr return NULL; 303177633Sdfr port = ntohs(sin->sin_port); 304177633Sdfr if (sbuf_printf(&sb, "%s.%u.%u", namebuf, 305177633Sdfr ((uint32_t)port) >> 8, 306177633Sdfr port & 0xff) < 0) 307177633Sdfr return NULL; 308177633Sdfr break; 309177633Sdfr#ifdef INET6 310177633Sdfr case AF_INET6: 311177633Sdfr sin6 = nbuf->buf; 312177633Sdfr if (__rpc_inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 313177633Sdfr == NULL) 314177633Sdfr return NULL; 315177633Sdfr port = ntohs(sin6->sin6_port); 316177633Sdfr if (sbuf_printf(&sb, "%s.%u.%u", namebuf6, 317177633Sdfr ((uint32_t)port) >> 8, 318177633Sdfr port & 0xff) < 0) 319177633Sdfr return NULL; 320177633Sdfr break; 321177633Sdfr#endif 322177633Sdfr case AF_LOCAL: 323177633Sdfr sun = nbuf->buf; 324177633Sdfr if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len - 325177633Sdfr offsetof(struct sockaddr_un, sun_path)), 326177633Sdfr sun->sun_path) < 0) 327177633Sdfr return (NULL); 328177633Sdfr break; 329177633Sdfr default: 330177633Sdfr return NULL; 331177633Sdfr } 332177633Sdfr 333177633Sdfr sbuf_finish(&sb); 334177633Sdfr ret = strdup(sbuf_data(&sb), M_RPC); 335177633Sdfr sbuf_delete(&sb); 336177633Sdfr 337177633Sdfr return ret; 338177633Sdfr} 339177633Sdfr 340177633Sdfrstruct netbuf * 341177633Sdfr__rpc_uaddr2taddr_af(int af, const char *uaddr) 342177633Sdfr{ 343177633Sdfr struct netbuf *ret = NULL; 344177633Sdfr char *addrstr, *p; 345177633Sdfr unsigned port, portlo, porthi; 346177633Sdfr struct sockaddr_in *sin; 347177633Sdfr#ifdef INET6 348177633Sdfr struct sockaddr_in6 *sin6; 349177633Sdfr#endif 350177633Sdfr struct sockaddr_un *sun; 351177633Sdfr 352177633Sdfr port = 0; 353177633Sdfr sin = NULL; 354177633Sdfr addrstr = strdup(uaddr, M_RPC); 355177633Sdfr if (addrstr == NULL) 356177633Sdfr return NULL; 357177633Sdfr 358177633Sdfr /* 359177633Sdfr * AF_LOCAL addresses are expected to be absolute 360177633Sdfr * pathnames, anything else will be AF_INET or AF_INET6. 361177633Sdfr */ 362177633Sdfr if (*addrstr != '/') { 363177633Sdfr p = strrchr(addrstr, '.'); 364177633Sdfr if (p == NULL) 365177633Sdfr goto out; 366177633Sdfr portlo = (unsigned)strtol(p + 1, NULL, 10); 367177633Sdfr *p = '\0'; 368177633Sdfr 369177633Sdfr p = strrchr(addrstr, '.'); 370177633Sdfr if (p == NULL) 371177633Sdfr goto out; 372177633Sdfr porthi = (unsigned)strtol(p + 1, NULL, 10); 373177633Sdfr *p = '\0'; 374177633Sdfr port = (porthi << 8) | portlo; 375177633Sdfr } 376177633Sdfr 377177633Sdfr ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK); 378177633Sdfr if (ret == NULL) 379177633Sdfr goto out; 380177633Sdfr 381177633Sdfr switch (af) { 382177633Sdfr case AF_INET: 383177633Sdfr sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC, 384177633Sdfr M_WAITOK); 385177633Sdfr if (sin == NULL) 386177633Sdfr goto out; 387177633Sdfr memset(sin, 0, sizeof *sin); 388177633Sdfr sin->sin_family = AF_INET; 389177633Sdfr sin->sin_port = htons(port); 390177633Sdfr if (__rpc_inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 391177633Sdfr free(sin, M_RPC); 392177633Sdfr free(ret, M_RPC); 393177633Sdfr ret = NULL; 394177633Sdfr goto out; 395177633Sdfr } 396177633Sdfr sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 397177633Sdfr ret->buf = sin; 398177633Sdfr break; 399177633Sdfr#ifdef INET6 400177633Sdfr case AF_INET6: 401177633Sdfr sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC, 402177633Sdfr M_WAITOK); 403177633Sdfr if (sin6 == NULL) 404177633Sdfr goto out; 405177633Sdfr memset(sin6, 0, sizeof *sin6); 406177633Sdfr sin6->sin6_family = AF_INET6; 407177633Sdfr sin6->sin6_port = htons(port); 408177633Sdfr if (__rpc_inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 409177633Sdfr free(sin6, M_RPC); 410177633Sdfr free(ret, M_RPC); 411177633Sdfr ret = NULL; 412177633Sdfr goto out; 413177633Sdfr } 414177633Sdfr sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 415177633Sdfr ret->buf = sin6; 416177633Sdfr break; 417177633Sdfr#endif 418177633Sdfr case AF_LOCAL: 419177633Sdfr sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC, 420177633Sdfr M_WAITOK); 421177633Sdfr if (sun == NULL) 422177633Sdfr goto out; 423177633Sdfr memset(sun, 0, sizeof *sun); 424177633Sdfr sun->sun_family = AF_LOCAL; 425177633Sdfr strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 426177633Sdfr ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 427177633Sdfr ret->buf = sun; 428177633Sdfr break; 429177633Sdfr default: 430177633Sdfr break; 431177633Sdfr } 432177633Sdfrout: 433177633Sdfr free(addrstr, M_RPC); 434177633Sdfr return ret; 435177633Sdfr} 436177633Sdfr 437177633Sdfrint 438177633Sdfr__rpc_seman2socktype(int semantics) 439177633Sdfr{ 440177633Sdfr switch (semantics) { 441177633Sdfr case NC_TPI_CLTS: 442177633Sdfr return SOCK_DGRAM; 443177633Sdfr case NC_TPI_COTS_ORD: 444177633Sdfr return SOCK_STREAM; 445177633Sdfr case NC_TPI_RAW: 446177633Sdfr return SOCK_RAW; 447177633Sdfr default: 448177633Sdfr break; 449177633Sdfr } 450177633Sdfr 451177633Sdfr return -1; 452177633Sdfr} 453177633Sdfr 454177633Sdfrint 455177633Sdfr__rpc_socktype2seman(int socktype) 456177633Sdfr{ 457177633Sdfr switch (socktype) { 458177633Sdfr case SOCK_DGRAM: 459177633Sdfr return NC_TPI_CLTS; 460177633Sdfr case SOCK_STREAM: 461177633Sdfr return NC_TPI_COTS_ORD; 462177633Sdfr case SOCK_RAW: 463177633Sdfr return NC_TPI_RAW; 464177633Sdfr default: 465177633Sdfr break; 466177633Sdfr } 467177633Sdfr 468177633Sdfr return -1; 469177633Sdfr} 470177633Sdfr 471177633Sdfr/* 472177633Sdfr * Returns the type of the network as defined in <rpc/nettype.h> 473177633Sdfr * If nettype is NULL, it defaults to NETPATH. 474177633Sdfr */ 475177633Sdfrstatic int 476177633Sdfrgetnettype(const char *nettype) 477177633Sdfr{ 478177633Sdfr int i; 479177633Sdfr 480177633Sdfr if ((nettype == NULL) || (nettype[0] == 0)) { 481177633Sdfr return (_RPC_NETPATH); /* Default */ 482177633Sdfr } 483177633Sdfr 484177633Sdfr#if 0 485177633Sdfr nettype = strlocase(nettype); 486177633Sdfr#endif 487177633Sdfr for (i = 0; _rpctypelist[i].name; i++) 488177633Sdfr if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 489177633Sdfr return (_rpctypelist[i].type); 490177633Sdfr } 491177633Sdfr return (_rpctypelist[i].type); 492177633Sdfr} 493177633Sdfr 494177633Sdfr/* 495177633Sdfr * For the given nettype (tcp or udp only), return the first structure found. 496177633Sdfr * This should be freed by calling freenetconfigent() 497177633Sdfr */ 498177633Sdfrstruct netconfig * 499177633Sdfr__rpc_getconfip(const char *nettype) 500177633Sdfr{ 501177633Sdfr char *netid; 502177633Sdfr static char *netid_tcp = (char *) NULL; 503177633Sdfr static char *netid_udp = (char *) NULL; 504177633Sdfr struct netconfig *dummy; 505177633Sdfr 506177633Sdfr if (!netid_udp && !netid_tcp) { 507177633Sdfr struct netconfig *nconf; 508177633Sdfr void *confighandle; 509177633Sdfr 510177633Sdfr if (!(confighandle = setnetconfig())) { 511177633Sdfr log(LOG_ERR, "rpc: failed to open " NETCONFIG); 512177633Sdfr return (NULL); 513177633Sdfr } 514177633Sdfr while ((nconf = getnetconfig(confighandle)) != NULL) { 515177633Sdfr if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 516177633Sdfr if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 517177633Sdfr netid_tcp = strdup(nconf->nc_netid, 518177633Sdfr M_RPC); 519177633Sdfr } else 520177633Sdfr if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 521177633Sdfr netid_udp = strdup(nconf->nc_netid, 522177633Sdfr M_RPC); 523177633Sdfr } 524177633Sdfr } 525177633Sdfr } 526177633Sdfr endnetconfig(confighandle); 527177633Sdfr } 528177633Sdfr if (strcmp(nettype, "udp") == 0) 529177633Sdfr netid = netid_udp; 530177633Sdfr else if (strcmp(nettype, "tcp") == 0) 531177633Sdfr netid = netid_tcp; 532177633Sdfr else { 533177633Sdfr return (NULL); 534177633Sdfr } 535177633Sdfr if ((netid == NULL) || (netid[0] == 0)) { 536177633Sdfr return (NULL); 537177633Sdfr } 538177633Sdfr dummy = getnetconfigent(netid); 539177633Sdfr return (dummy); 540177633Sdfr} 541177633Sdfr 542177633Sdfr/* 543177633Sdfr * Returns the type of the nettype, which should then be used with 544177633Sdfr * __rpc_getconf(). 545177633Sdfr * 546177633Sdfr * For simplicity in the kernel, we don't support the NETPATH 547177633Sdfr * environment variable. We behave as userland would then NETPATH is 548177633Sdfr * unset, i.e. iterate over all visible entries in netconfig. 549177633Sdfr */ 550177633Sdfrvoid * 551177633Sdfr__rpc_setconf(nettype) 552177633Sdfr const char *nettype; 553177633Sdfr{ 554177633Sdfr struct handle *handle; 555177633Sdfr 556177633Sdfr handle = (struct handle *) malloc(sizeof (struct handle), 557177633Sdfr M_RPC, M_WAITOK); 558177633Sdfr switch (handle->nettype = getnettype(nettype)) { 559177633Sdfr case _RPC_NETPATH: 560177633Sdfr case _RPC_CIRCUIT_N: 561177633Sdfr case _RPC_DATAGRAM_N: 562177633Sdfr if (!(handle->nhandle = setnetconfig())) 563177633Sdfr goto failed; 564177633Sdfr handle->nflag = TRUE; 565177633Sdfr break; 566177633Sdfr case _RPC_VISIBLE: 567177633Sdfr case _RPC_CIRCUIT_V: 568177633Sdfr case _RPC_DATAGRAM_V: 569177633Sdfr case _RPC_TCP: 570177633Sdfr case _RPC_UDP: 571177633Sdfr if (!(handle->nhandle = setnetconfig())) { 572177633Sdfr log(LOG_ERR, "rpc: failed to open " NETCONFIG); 573177633Sdfr goto failed; 574177633Sdfr } 575177633Sdfr handle->nflag = FALSE; 576177633Sdfr break; 577177633Sdfr default: 578177633Sdfr goto failed; 579177633Sdfr } 580177633Sdfr 581177633Sdfr return (handle); 582177633Sdfr 583177633Sdfrfailed: 584177633Sdfr free(handle, M_RPC); 585177633Sdfr return (NULL); 586177633Sdfr} 587177633Sdfr 588177633Sdfr/* 589177633Sdfr * Returns the next netconfig struct for the given "net" type. 590177633Sdfr * __rpc_setconf() should have been called previously. 591177633Sdfr */ 592177633Sdfrstruct netconfig * 593177633Sdfr__rpc_getconf(void *vhandle) 594177633Sdfr{ 595177633Sdfr struct handle *handle; 596177633Sdfr struct netconfig *nconf; 597177633Sdfr 598177633Sdfr handle = (struct handle *)vhandle; 599177633Sdfr if (handle == NULL) { 600177633Sdfr return (NULL); 601177633Sdfr } 602177633Sdfr for (;;) { 603177633Sdfr if (handle->nflag) { 604177633Sdfr nconf = getnetconfig(handle->nhandle); 605177633Sdfr if (nconf && !(nconf->nc_flag & NC_VISIBLE)) 606177633Sdfr continue; 607177633Sdfr } else { 608177633Sdfr nconf = getnetconfig(handle->nhandle); 609177633Sdfr } 610177633Sdfr if (nconf == NULL) 611177633Sdfr break; 612177633Sdfr if ((nconf->nc_semantics != NC_TPI_CLTS) && 613177633Sdfr (nconf->nc_semantics != NC_TPI_COTS) && 614177633Sdfr (nconf->nc_semantics != NC_TPI_COTS_ORD)) 615177633Sdfr continue; 616177633Sdfr switch (handle->nettype) { 617177633Sdfr case _RPC_VISIBLE: 618177633Sdfr if (!(nconf->nc_flag & NC_VISIBLE)) 619177633Sdfr continue; 620177633Sdfr /* FALLTHROUGH */ 621177633Sdfr case _RPC_NETPATH: /* Be happy */ 622177633Sdfr break; 623177633Sdfr case _RPC_CIRCUIT_V: 624177633Sdfr if (!(nconf->nc_flag & NC_VISIBLE)) 625177633Sdfr continue; 626177633Sdfr /* FALLTHROUGH */ 627177633Sdfr case _RPC_CIRCUIT_N: 628177633Sdfr if ((nconf->nc_semantics != NC_TPI_COTS) && 629177633Sdfr (nconf->nc_semantics != NC_TPI_COTS_ORD)) 630177633Sdfr continue; 631177633Sdfr break; 632177633Sdfr case _RPC_DATAGRAM_V: 633177633Sdfr if (!(nconf->nc_flag & NC_VISIBLE)) 634177633Sdfr continue; 635177633Sdfr /* FALLTHROUGH */ 636177633Sdfr case _RPC_DATAGRAM_N: 637177633Sdfr if (nconf->nc_semantics != NC_TPI_CLTS) 638177633Sdfr continue; 639177633Sdfr break; 640177633Sdfr case _RPC_TCP: 641177633Sdfr if (((nconf->nc_semantics != NC_TPI_COTS) && 642177633Sdfr (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 643177633Sdfr (strcmp(nconf->nc_protofmly, NC_INET) 644177633Sdfr#ifdef INET6 645177633Sdfr && strcmp(nconf->nc_protofmly, NC_INET6)) 646177633Sdfr#else 647177633Sdfr ) 648177633Sdfr#endif 649177633Sdfr || 650177633Sdfr strcmp(nconf->nc_proto, NC_TCP)) 651177633Sdfr continue; 652177633Sdfr break; 653177633Sdfr case _RPC_UDP: 654177633Sdfr if ((nconf->nc_semantics != NC_TPI_CLTS) || 655177633Sdfr (strcmp(nconf->nc_protofmly, NC_INET) 656177633Sdfr#ifdef INET6 657177633Sdfr && strcmp(nconf->nc_protofmly, NC_INET6)) 658177633Sdfr#else 659177633Sdfr ) 660177633Sdfr#endif 661177633Sdfr || 662177633Sdfr strcmp(nconf->nc_proto, NC_UDP)) 663177633Sdfr continue; 664177633Sdfr break; 665177633Sdfr } 666177633Sdfr break; 667177633Sdfr } 668177633Sdfr return (nconf); 669177633Sdfr} 670177633Sdfr 671177633Sdfrvoid 672177633Sdfr__rpc_endconf(vhandle) 673177633Sdfr void * vhandle; 674177633Sdfr{ 675177633Sdfr struct handle *handle; 676177633Sdfr 677177633Sdfr handle = (struct handle *) vhandle; 678177633Sdfr if (handle == NULL) { 679177633Sdfr return; 680177633Sdfr } 681177633Sdfr endnetconfig(handle->nhandle); 682177633Sdfr free(handle, M_RPC); 683177633Sdfr} 684177633Sdfr 685177633Sdfrint 686177633Sdfr__rpc_sockisbound(struct socket *so) 687177633Sdfr{ 688177633Sdfr struct sockaddr *sa; 689177633Sdfr int error, bound; 690177633Sdfr 691177633Sdfr error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); 692177633Sdfr if (error) 693177633Sdfr return (0); 694177633Sdfr 695177633Sdfr switch (sa->sa_family) { 696177633Sdfr case AF_INET: 697177633Sdfr bound = (((struct sockaddr_in *) sa)->sin_port != 0); 698177633Sdfr break; 699177633Sdfr#ifdef INET6 700177633Sdfr case AF_INET6: 701177633Sdfr bound = (((struct sockaddr_in6 *) sa)->sin6_port != 0); 702177633Sdfr break; 703177633Sdfr#endif 704177633Sdfr case AF_LOCAL: 705177633Sdfr /* XXX check this */ 706177633Sdfr bound = (((struct sockaddr_un *) sa)->sun_path[0] != '\0'); 707177633Sdfr break; 708177633Sdfr default: 709177633Sdfr bound = FALSE; 710177633Sdfr break; 711177633Sdfr } 712177633Sdfr 713177633Sdfr free(sa, M_SONAME); 714177633Sdfr 715177633Sdfr return bound; 716177633Sdfr} 717