rpc_generic.c revision 196503
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 196503 2009-08-24 10:09:30Z zec $"); 38177633Sdfr 39177633Sdfr/* 40177633Sdfr * rpc_generic.c, Miscl routines for RPC. 41177633Sdfr * 42177633Sdfr */ 43177633Sdfr 44177633Sdfr#include "opt_inet6.h" 45177633Sdfr 46177633Sdfr#include <sys/param.h> 47177662Sdfr#include <sys/kernel.h> 48177633Sdfr#include <sys/malloc.h> 49184588Sdfr#include <sys/mbuf.h> 50177662Sdfr#include <sys/module.h> 51177633Sdfr#include <sys/proc.h> 52177633Sdfr#include <sys/protosw.h> 53177633Sdfr#include <sys/sbuf.h> 54177633Sdfr#include <sys/systm.h> 55177633Sdfr#include <sys/socket.h> 56177633Sdfr#include <sys/socketvar.h> 57177633Sdfr#include <sys/syslog.h> 58177633Sdfr 59196503Szec#include <net/vnet.h> 60196503Szec 61177633Sdfr#include <rpc/rpc.h> 62177633Sdfr#include <rpc/nettype.h> 63177633Sdfr 64177685Sdfr#include <rpc/rpc_com.h> 65177633Sdfr 66177685Sdfr#if __FreeBSD_version < 700000 67177685Sdfr#define strrchr rindex 68177685Sdfr#endif 69177685Sdfr 70177633Sdfrstruct handle { 71177633Sdfr NCONF_HANDLE *nhandle; 72177633Sdfr int nflag; /* Whether NETPATH or NETCONFIG */ 73177633Sdfr int nettype; 74177633Sdfr}; 75177633Sdfr 76177633Sdfrstatic const struct _rpcnettype { 77177633Sdfr const char *name; 78177633Sdfr const int type; 79177633Sdfr} _rpctypelist[] = { 80177633Sdfr { "netpath", _RPC_NETPATH }, 81177633Sdfr { "visible", _RPC_VISIBLE }, 82177633Sdfr { "circuit_v", _RPC_CIRCUIT_V }, 83177633Sdfr { "datagram_v", _RPC_DATAGRAM_V }, 84177633Sdfr { "circuit_n", _RPC_CIRCUIT_N }, 85177633Sdfr { "datagram_n", _RPC_DATAGRAM_N }, 86177633Sdfr { "tcp", _RPC_TCP }, 87177633Sdfr { "udp", _RPC_UDP }, 88177633Sdfr { 0, _RPC_NONE } 89177633Sdfr}; 90177633Sdfr 91177633Sdfrstruct netid_af { 92177633Sdfr const char *netid; 93177633Sdfr int af; 94177633Sdfr int protocol; 95177633Sdfr}; 96177633Sdfr 97177633Sdfrstatic const struct netid_af na_cvt[] = { 98177633Sdfr { "udp", AF_INET, IPPROTO_UDP }, 99177633Sdfr { "tcp", AF_INET, IPPROTO_TCP }, 100177633Sdfr#ifdef INET6 101177633Sdfr { "udp6", AF_INET6, IPPROTO_UDP }, 102177633Sdfr { "tcp6", AF_INET6, IPPROTO_TCP }, 103177633Sdfr#endif 104177633Sdfr { "local", AF_LOCAL, 0 } 105177633Sdfr}; 106177633Sdfr 107177633Sdfrstruct rpc_createerr rpc_createerr; 108177633Sdfr 109177633Sdfr/* 110177633Sdfr * Find the appropriate buffer size 111177633Sdfr */ 112177633Sdfru_int 113177633Sdfr/*ARGSUSED*/ 114177633Sdfr__rpc_get_t_size(int af, int proto, int size) 115177633Sdfr{ 116177633Sdfr int maxsize, defsize; 117177633Sdfr 118177633Sdfr maxsize = 256 * 1024; /* XXX */ 119177633Sdfr switch (proto) { 120177633Sdfr case IPPROTO_TCP: 121177633Sdfr defsize = 64 * 1024; /* XXX */ 122177633Sdfr break; 123177633Sdfr case IPPROTO_UDP: 124177633Sdfr defsize = UDPMSGSIZE; 125177633Sdfr break; 126177633Sdfr default: 127177633Sdfr defsize = RPC_MAXDATASIZE; 128177633Sdfr break; 129177633Sdfr } 130177633Sdfr if (size == 0) 131177633Sdfr return defsize; 132177633Sdfr 133177633Sdfr /* Check whether the value is within the upper max limit */ 134177633Sdfr return (size > maxsize ? (u_int)maxsize : (u_int)size); 135177633Sdfr} 136177633Sdfr 137177633Sdfr/* 138177633Sdfr * Find the appropriate address buffer size 139177633Sdfr */ 140177633Sdfru_int 141177633Sdfr__rpc_get_a_size(af) 142177633Sdfr int af; 143177633Sdfr{ 144177633Sdfr switch (af) { 145177633Sdfr case AF_INET: 146177633Sdfr return sizeof (struct sockaddr_in); 147177633Sdfr#ifdef INET6 148177633Sdfr case AF_INET6: 149177633Sdfr return sizeof (struct sockaddr_in6); 150177633Sdfr#endif 151177633Sdfr case AF_LOCAL: 152177633Sdfr return sizeof (struct sockaddr_un); 153177633Sdfr default: 154177633Sdfr break; 155177633Sdfr } 156177633Sdfr return ((u_int)RPC_MAXADDRSIZE); 157177633Sdfr} 158177633Sdfr 159177633Sdfr#if 0 160177633Sdfr 161177633Sdfr/* 162177633Sdfr * Used to ping the NULL procedure for clnt handle. 163177633Sdfr * Returns NULL if fails, else a non-NULL pointer. 164177633Sdfr */ 165177633Sdfrvoid * 166177633Sdfrrpc_nullproc(clnt) 167177633Sdfr CLIENT *clnt; 168177633Sdfr{ 169177633Sdfr struct timeval TIMEOUT = {25, 0}; 170177633Sdfr 171177633Sdfr if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL, 172177633Sdfr (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { 173177633Sdfr return (NULL); 174177633Sdfr } 175177633Sdfr return ((void *) clnt); 176177633Sdfr} 177177633Sdfr 178177633Sdfr#endif 179177633Sdfr 180177633Sdfrint 181177633Sdfr__rpc_socket2sockinfo(struct socket *so, struct __rpc_sockinfo *sip) 182177633Sdfr{ 183177633Sdfr int type, proto; 184177633Sdfr struct sockaddr *sa; 185177633Sdfr sa_family_t family; 186177633Sdfr struct sockopt opt; 187177633Sdfr int error; 188177633Sdfr 189177633Sdfr error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); 190177633Sdfr if (error) 191177633Sdfr return 0; 192177633Sdfr 193177633Sdfr sip->si_alen = sa->sa_len; 194177633Sdfr family = sa->sa_family; 195177633Sdfr free(sa, M_SONAME); 196177633Sdfr 197177633Sdfr opt.sopt_dir = SOPT_GET; 198177633Sdfr opt.sopt_level = SOL_SOCKET; 199177633Sdfr opt.sopt_name = SO_TYPE; 200177633Sdfr opt.sopt_val = &type; 201177633Sdfr opt.sopt_valsize = sizeof type; 202177633Sdfr opt.sopt_td = NULL; 203177633Sdfr error = sogetopt(so, &opt); 204177633Sdfr if (error) 205177633Sdfr return 0; 206177633Sdfr 207177633Sdfr /* XXX */ 208177633Sdfr if (family != AF_LOCAL) { 209177633Sdfr if (type == SOCK_STREAM) 210177633Sdfr proto = IPPROTO_TCP; 211177633Sdfr else if (type == SOCK_DGRAM) 212177633Sdfr proto = IPPROTO_UDP; 213177633Sdfr else 214177633Sdfr return 0; 215177633Sdfr } else 216177633Sdfr proto = 0; 217177633Sdfr 218177633Sdfr sip->si_af = family; 219177633Sdfr sip->si_proto = proto; 220177633Sdfr sip->si_socktype = type; 221177633Sdfr 222177633Sdfr return 1; 223177633Sdfr} 224177633Sdfr 225177633Sdfr/* 226177633Sdfr * Linear search, but the number of entries is small. 227177633Sdfr */ 228177633Sdfrint 229177633Sdfr__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip) 230177633Sdfr{ 231177633Sdfr int i; 232177633Sdfr 233177633Sdfr for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) 234177633Sdfr if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || ( 235177633Sdfr strcmp(nconf->nc_netid, "unix") == 0 && 236177633Sdfr strcmp(na_cvt[i].netid, "local") == 0)) { 237177633Sdfr sip->si_af = na_cvt[i].af; 238177633Sdfr sip->si_proto = na_cvt[i].protocol; 239177633Sdfr sip->si_socktype = 240177633Sdfr __rpc_seman2socktype((int)nconf->nc_semantics); 241177633Sdfr if (sip->si_socktype == -1) 242177633Sdfr return 0; 243177633Sdfr sip->si_alen = __rpc_get_a_size(sip->si_af); 244177633Sdfr return 1; 245177633Sdfr } 246177633Sdfr 247177633Sdfr return 0; 248177633Sdfr} 249177633Sdfr 250177633Sdfrstruct socket * 251177633Sdfr__rpc_nconf2socket(const struct netconfig *nconf) 252177633Sdfr{ 253177633Sdfr struct __rpc_sockinfo si; 254177633Sdfr struct socket *so; 255177633Sdfr int error; 256177633Sdfr 257177633Sdfr if (!__rpc_nconf2sockinfo(nconf, &si)) 258177633Sdfr return 0; 259177633Sdfr 260177633Sdfr so = NULL; 261177633Sdfr error = socreate(si.si_af, &so, si.si_socktype, si.si_proto, 262177633Sdfr curthread->td_ucred, curthread); 263177633Sdfr 264177633Sdfr if (error) 265177633Sdfr return NULL; 266177633Sdfr else 267177633Sdfr return so; 268177633Sdfr} 269177633Sdfr 270177633Sdfrchar * 271177633Sdfrtaddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) 272177633Sdfr{ 273177633Sdfr struct __rpc_sockinfo si; 274177633Sdfr 275177633Sdfr if (!__rpc_nconf2sockinfo(nconf, &si)) 276177633Sdfr return NULL; 277177633Sdfr return __rpc_taddr2uaddr_af(si.si_af, nbuf); 278177633Sdfr} 279177633Sdfr 280177633Sdfrstruct netbuf * 281177633Sdfruaddr2taddr(const struct netconfig *nconf, const char *uaddr) 282177633Sdfr{ 283177633Sdfr struct __rpc_sockinfo si; 284177633Sdfr 285177633Sdfr if (!__rpc_nconf2sockinfo(nconf, &si)) 286177633Sdfr return NULL; 287177633Sdfr return __rpc_uaddr2taddr_af(si.si_af, uaddr); 288177633Sdfr} 289177633Sdfr 290177633Sdfrchar * 291177633Sdfr__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) 292177633Sdfr{ 293177633Sdfr char *ret; 294177633Sdfr struct sbuf sb; 295177633Sdfr struct sockaddr_in *sin; 296177633Sdfr struct sockaddr_un *sun; 297177633Sdfr char namebuf[INET_ADDRSTRLEN]; 298177633Sdfr#ifdef INET6 299177633Sdfr struct sockaddr_in6 *sin6; 300177633Sdfr char namebuf6[INET6_ADDRSTRLEN]; 301177633Sdfr#endif 302177633Sdfr u_int16_t port; 303177633Sdfr 304177633Sdfr sbuf_new(&sb, NULL, 0, SBUF_AUTOEXTEND); 305177633Sdfr 306177633Sdfr switch (af) { 307177633Sdfr case AF_INET: 308177633Sdfr sin = nbuf->buf; 309177633Sdfr if (__rpc_inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) 310177633Sdfr == NULL) 311177633Sdfr return NULL; 312177633Sdfr port = ntohs(sin->sin_port); 313177633Sdfr if (sbuf_printf(&sb, "%s.%u.%u", namebuf, 314177633Sdfr ((uint32_t)port) >> 8, 315177633Sdfr port & 0xff) < 0) 316177633Sdfr return NULL; 317177633Sdfr break; 318177633Sdfr#ifdef INET6 319177633Sdfr case AF_INET6: 320177633Sdfr sin6 = nbuf->buf; 321177633Sdfr if (__rpc_inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) 322177633Sdfr == NULL) 323177633Sdfr return NULL; 324177633Sdfr port = ntohs(sin6->sin6_port); 325177633Sdfr if (sbuf_printf(&sb, "%s.%u.%u", namebuf6, 326177633Sdfr ((uint32_t)port) >> 8, 327177633Sdfr port & 0xff) < 0) 328177633Sdfr return NULL; 329177633Sdfr break; 330177633Sdfr#endif 331177633Sdfr case AF_LOCAL: 332177633Sdfr sun = nbuf->buf; 333177633Sdfr if (sbuf_printf(&sb, "%.*s", (int)(sun->sun_len - 334177633Sdfr offsetof(struct sockaddr_un, sun_path)), 335177633Sdfr sun->sun_path) < 0) 336177633Sdfr return (NULL); 337177633Sdfr break; 338177633Sdfr default: 339177633Sdfr return NULL; 340177633Sdfr } 341177633Sdfr 342177633Sdfr sbuf_finish(&sb); 343177633Sdfr ret = strdup(sbuf_data(&sb), M_RPC); 344177633Sdfr sbuf_delete(&sb); 345177633Sdfr 346177633Sdfr return ret; 347177633Sdfr} 348177633Sdfr 349177633Sdfrstruct netbuf * 350177633Sdfr__rpc_uaddr2taddr_af(int af, const char *uaddr) 351177633Sdfr{ 352177633Sdfr struct netbuf *ret = NULL; 353177633Sdfr char *addrstr, *p; 354177633Sdfr unsigned port, portlo, porthi; 355177633Sdfr struct sockaddr_in *sin; 356177633Sdfr#ifdef INET6 357177633Sdfr struct sockaddr_in6 *sin6; 358177633Sdfr#endif 359177633Sdfr struct sockaddr_un *sun; 360177633Sdfr 361177633Sdfr port = 0; 362177633Sdfr sin = NULL; 363177633Sdfr addrstr = strdup(uaddr, M_RPC); 364177633Sdfr if (addrstr == NULL) 365177633Sdfr return NULL; 366177633Sdfr 367177633Sdfr /* 368177633Sdfr * AF_LOCAL addresses are expected to be absolute 369177633Sdfr * pathnames, anything else will be AF_INET or AF_INET6. 370177633Sdfr */ 371177633Sdfr if (*addrstr != '/') { 372177633Sdfr p = strrchr(addrstr, '.'); 373177633Sdfr if (p == NULL) 374177633Sdfr goto out; 375177633Sdfr portlo = (unsigned)strtol(p + 1, NULL, 10); 376177633Sdfr *p = '\0'; 377177633Sdfr 378177633Sdfr p = strrchr(addrstr, '.'); 379177633Sdfr if (p == NULL) 380177633Sdfr goto out; 381177633Sdfr porthi = (unsigned)strtol(p + 1, NULL, 10); 382177633Sdfr *p = '\0'; 383177633Sdfr port = (porthi << 8) | portlo; 384177633Sdfr } 385177633Sdfr 386177633Sdfr ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK); 387177633Sdfr if (ret == NULL) 388177633Sdfr goto out; 389177633Sdfr 390177633Sdfr switch (af) { 391177633Sdfr case AF_INET: 392177633Sdfr sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC, 393177633Sdfr M_WAITOK); 394177633Sdfr if (sin == NULL) 395177633Sdfr goto out; 396177633Sdfr memset(sin, 0, sizeof *sin); 397177633Sdfr sin->sin_family = AF_INET; 398177633Sdfr sin->sin_port = htons(port); 399177633Sdfr if (__rpc_inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { 400177633Sdfr free(sin, M_RPC); 401177633Sdfr free(ret, M_RPC); 402177633Sdfr ret = NULL; 403177633Sdfr goto out; 404177633Sdfr } 405177633Sdfr sin->sin_len = ret->maxlen = ret->len = sizeof *sin; 406177633Sdfr ret->buf = sin; 407177633Sdfr break; 408177633Sdfr#ifdef INET6 409177633Sdfr case AF_INET6: 410177633Sdfr sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC, 411177633Sdfr M_WAITOK); 412177633Sdfr if (sin6 == NULL) 413177633Sdfr goto out; 414177633Sdfr memset(sin6, 0, sizeof *sin6); 415177633Sdfr sin6->sin6_family = AF_INET6; 416177633Sdfr sin6->sin6_port = htons(port); 417177633Sdfr if (__rpc_inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) { 418177633Sdfr free(sin6, M_RPC); 419177633Sdfr free(ret, M_RPC); 420177633Sdfr ret = NULL; 421177633Sdfr goto out; 422177633Sdfr } 423177633Sdfr sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6; 424177633Sdfr ret->buf = sin6; 425177633Sdfr break; 426177633Sdfr#endif 427177633Sdfr case AF_LOCAL: 428177633Sdfr sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC, 429177633Sdfr M_WAITOK); 430177633Sdfr if (sun == NULL) 431177633Sdfr goto out; 432177633Sdfr memset(sun, 0, sizeof *sun); 433177633Sdfr sun->sun_family = AF_LOCAL; 434177633Sdfr strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1); 435177633Sdfr ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun); 436177633Sdfr ret->buf = sun; 437177633Sdfr break; 438177633Sdfr default: 439177633Sdfr break; 440177633Sdfr } 441177633Sdfrout: 442177633Sdfr free(addrstr, M_RPC); 443177633Sdfr return ret; 444177633Sdfr} 445177633Sdfr 446177633Sdfrint 447177633Sdfr__rpc_seman2socktype(int semantics) 448177633Sdfr{ 449177633Sdfr switch (semantics) { 450177633Sdfr case NC_TPI_CLTS: 451177633Sdfr return SOCK_DGRAM; 452177633Sdfr case NC_TPI_COTS_ORD: 453177633Sdfr return SOCK_STREAM; 454177633Sdfr case NC_TPI_RAW: 455177633Sdfr return SOCK_RAW; 456177633Sdfr default: 457177633Sdfr break; 458177633Sdfr } 459177633Sdfr 460177633Sdfr return -1; 461177633Sdfr} 462177633Sdfr 463177633Sdfrint 464177633Sdfr__rpc_socktype2seman(int socktype) 465177633Sdfr{ 466177633Sdfr switch (socktype) { 467177633Sdfr case SOCK_DGRAM: 468177633Sdfr return NC_TPI_CLTS; 469177633Sdfr case SOCK_STREAM: 470177633Sdfr return NC_TPI_COTS_ORD; 471177633Sdfr case SOCK_RAW: 472177633Sdfr return NC_TPI_RAW; 473177633Sdfr default: 474177633Sdfr break; 475177633Sdfr } 476177633Sdfr 477177633Sdfr return -1; 478177633Sdfr} 479177633Sdfr 480177633Sdfr/* 481177633Sdfr * Returns the type of the network as defined in <rpc/nettype.h> 482177633Sdfr * If nettype is NULL, it defaults to NETPATH. 483177633Sdfr */ 484177633Sdfrstatic int 485177633Sdfrgetnettype(const char *nettype) 486177633Sdfr{ 487177633Sdfr int i; 488177633Sdfr 489177633Sdfr if ((nettype == NULL) || (nettype[0] == 0)) { 490177633Sdfr return (_RPC_NETPATH); /* Default */ 491177633Sdfr } 492177633Sdfr 493177633Sdfr#if 0 494177633Sdfr nettype = strlocase(nettype); 495177633Sdfr#endif 496177633Sdfr for (i = 0; _rpctypelist[i].name; i++) 497177633Sdfr if (strcasecmp(nettype, _rpctypelist[i].name) == 0) { 498177633Sdfr return (_rpctypelist[i].type); 499177633Sdfr } 500177633Sdfr return (_rpctypelist[i].type); 501177633Sdfr} 502177633Sdfr 503177633Sdfr/* 504177633Sdfr * For the given nettype (tcp or udp only), return the first structure found. 505177633Sdfr * This should be freed by calling freenetconfigent() 506177633Sdfr */ 507177633Sdfrstruct netconfig * 508177633Sdfr__rpc_getconfip(const char *nettype) 509177633Sdfr{ 510177633Sdfr char *netid; 511177633Sdfr static char *netid_tcp = (char *) NULL; 512177633Sdfr static char *netid_udp = (char *) NULL; 513177633Sdfr struct netconfig *dummy; 514177633Sdfr 515177633Sdfr if (!netid_udp && !netid_tcp) { 516177633Sdfr struct netconfig *nconf; 517177633Sdfr void *confighandle; 518177633Sdfr 519177633Sdfr if (!(confighandle = setnetconfig())) { 520177633Sdfr log(LOG_ERR, "rpc: failed to open " NETCONFIG); 521177633Sdfr return (NULL); 522177633Sdfr } 523177633Sdfr while ((nconf = getnetconfig(confighandle)) != NULL) { 524177633Sdfr if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { 525177633Sdfr if (strcmp(nconf->nc_proto, NC_TCP) == 0) { 526177633Sdfr netid_tcp = strdup(nconf->nc_netid, 527177633Sdfr M_RPC); 528177633Sdfr } else 529177633Sdfr if (strcmp(nconf->nc_proto, NC_UDP) == 0) { 530177633Sdfr netid_udp = strdup(nconf->nc_netid, 531177633Sdfr M_RPC); 532177633Sdfr } 533177633Sdfr } 534177633Sdfr } 535177633Sdfr endnetconfig(confighandle); 536177633Sdfr } 537177633Sdfr if (strcmp(nettype, "udp") == 0) 538177633Sdfr netid = netid_udp; 539177633Sdfr else if (strcmp(nettype, "tcp") == 0) 540177633Sdfr netid = netid_tcp; 541177633Sdfr else { 542177633Sdfr return (NULL); 543177633Sdfr } 544177633Sdfr if ((netid == NULL) || (netid[0] == 0)) { 545177633Sdfr return (NULL); 546177633Sdfr } 547177633Sdfr dummy = getnetconfigent(netid); 548177633Sdfr return (dummy); 549177633Sdfr} 550177633Sdfr 551177633Sdfr/* 552177633Sdfr * Returns the type of the nettype, which should then be used with 553177633Sdfr * __rpc_getconf(). 554177633Sdfr * 555177633Sdfr * For simplicity in the kernel, we don't support the NETPATH 556177633Sdfr * environment variable. We behave as userland would then NETPATH is 557177633Sdfr * unset, i.e. iterate over all visible entries in netconfig. 558177633Sdfr */ 559177633Sdfrvoid * 560177633Sdfr__rpc_setconf(nettype) 561177633Sdfr const char *nettype; 562177633Sdfr{ 563177633Sdfr struct handle *handle; 564177633Sdfr 565177633Sdfr handle = (struct handle *) malloc(sizeof (struct handle), 566177633Sdfr M_RPC, M_WAITOK); 567177633Sdfr switch (handle->nettype = getnettype(nettype)) { 568177633Sdfr case _RPC_NETPATH: 569177633Sdfr case _RPC_CIRCUIT_N: 570177633Sdfr case _RPC_DATAGRAM_N: 571177633Sdfr if (!(handle->nhandle = setnetconfig())) 572177633Sdfr goto failed; 573177633Sdfr handle->nflag = TRUE; 574177633Sdfr break; 575177633Sdfr case _RPC_VISIBLE: 576177633Sdfr case _RPC_CIRCUIT_V: 577177633Sdfr case _RPC_DATAGRAM_V: 578177633Sdfr case _RPC_TCP: 579177633Sdfr case _RPC_UDP: 580177633Sdfr if (!(handle->nhandle = setnetconfig())) { 581177633Sdfr log(LOG_ERR, "rpc: failed to open " NETCONFIG); 582177633Sdfr goto failed; 583177633Sdfr } 584177633Sdfr handle->nflag = FALSE; 585177633Sdfr break; 586177633Sdfr default: 587177633Sdfr goto failed; 588177633Sdfr } 589177633Sdfr 590177633Sdfr return (handle); 591177633Sdfr 592177633Sdfrfailed: 593177633Sdfr free(handle, M_RPC); 594177633Sdfr return (NULL); 595177633Sdfr} 596177633Sdfr 597177633Sdfr/* 598177633Sdfr * Returns the next netconfig struct for the given "net" type. 599177633Sdfr * __rpc_setconf() should have been called previously. 600177633Sdfr */ 601177633Sdfrstruct netconfig * 602177633Sdfr__rpc_getconf(void *vhandle) 603177633Sdfr{ 604177633Sdfr struct handle *handle; 605177633Sdfr struct netconfig *nconf; 606177633Sdfr 607177633Sdfr handle = (struct handle *)vhandle; 608177633Sdfr if (handle == NULL) { 609177633Sdfr return (NULL); 610177633Sdfr } 611177633Sdfr for (;;) { 612177633Sdfr if (handle->nflag) { 613177633Sdfr nconf = getnetconfig(handle->nhandle); 614177633Sdfr if (nconf && !(nconf->nc_flag & NC_VISIBLE)) 615177633Sdfr continue; 616177633Sdfr } else { 617177633Sdfr nconf = getnetconfig(handle->nhandle); 618177633Sdfr } 619177633Sdfr if (nconf == NULL) 620177633Sdfr break; 621177633Sdfr if ((nconf->nc_semantics != NC_TPI_CLTS) && 622177633Sdfr (nconf->nc_semantics != NC_TPI_COTS) && 623177633Sdfr (nconf->nc_semantics != NC_TPI_COTS_ORD)) 624177633Sdfr continue; 625177633Sdfr switch (handle->nettype) { 626177633Sdfr case _RPC_VISIBLE: 627177633Sdfr if (!(nconf->nc_flag & NC_VISIBLE)) 628177633Sdfr continue; 629177633Sdfr /* FALLTHROUGH */ 630177633Sdfr case _RPC_NETPATH: /* Be happy */ 631177633Sdfr break; 632177633Sdfr case _RPC_CIRCUIT_V: 633177633Sdfr if (!(nconf->nc_flag & NC_VISIBLE)) 634177633Sdfr continue; 635177633Sdfr /* FALLTHROUGH */ 636177633Sdfr case _RPC_CIRCUIT_N: 637177633Sdfr if ((nconf->nc_semantics != NC_TPI_COTS) && 638177633Sdfr (nconf->nc_semantics != NC_TPI_COTS_ORD)) 639177633Sdfr continue; 640177633Sdfr break; 641177633Sdfr case _RPC_DATAGRAM_V: 642177633Sdfr if (!(nconf->nc_flag & NC_VISIBLE)) 643177633Sdfr continue; 644177633Sdfr /* FALLTHROUGH */ 645177633Sdfr case _RPC_DATAGRAM_N: 646177633Sdfr if (nconf->nc_semantics != NC_TPI_CLTS) 647177633Sdfr continue; 648177633Sdfr break; 649177633Sdfr case _RPC_TCP: 650177633Sdfr if (((nconf->nc_semantics != NC_TPI_COTS) && 651177633Sdfr (nconf->nc_semantics != NC_TPI_COTS_ORD)) || 652177633Sdfr (strcmp(nconf->nc_protofmly, NC_INET) 653177633Sdfr#ifdef INET6 654177633Sdfr && strcmp(nconf->nc_protofmly, NC_INET6)) 655177633Sdfr#else 656177633Sdfr ) 657177633Sdfr#endif 658177633Sdfr || 659177633Sdfr strcmp(nconf->nc_proto, NC_TCP)) 660177633Sdfr continue; 661177633Sdfr break; 662177633Sdfr case _RPC_UDP: 663177633Sdfr if ((nconf->nc_semantics != NC_TPI_CLTS) || 664177633Sdfr (strcmp(nconf->nc_protofmly, NC_INET) 665177633Sdfr#ifdef INET6 666177633Sdfr && strcmp(nconf->nc_protofmly, NC_INET6)) 667177633Sdfr#else 668177633Sdfr ) 669177633Sdfr#endif 670177633Sdfr || 671177633Sdfr strcmp(nconf->nc_proto, NC_UDP)) 672177633Sdfr continue; 673177633Sdfr break; 674177633Sdfr } 675177633Sdfr break; 676177633Sdfr } 677177633Sdfr return (nconf); 678177633Sdfr} 679177633Sdfr 680177633Sdfrvoid 681177633Sdfr__rpc_endconf(vhandle) 682177633Sdfr void * vhandle; 683177633Sdfr{ 684177633Sdfr struct handle *handle; 685177633Sdfr 686177633Sdfr handle = (struct handle *) vhandle; 687177633Sdfr if (handle == NULL) { 688177633Sdfr return; 689177633Sdfr } 690177633Sdfr endnetconfig(handle->nhandle); 691177633Sdfr free(handle, M_RPC); 692177633Sdfr} 693177633Sdfr 694177633Sdfrint 695177633Sdfr__rpc_sockisbound(struct socket *so) 696177633Sdfr{ 697177633Sdfr struct sockaddr *sa; 698177633Sdfr int error, bound; 699177633Sdfr 700177633Sdfr error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); 701177633Sdfr if (error) 702177633Sdfr return (0); 703177633Sdfr 704177633Sdfr switch (sa->sa_family) { 705177633Sdfr case AF_INET: 706177633Sdfr bound = (((struct sockaddr_in *) sa)->sin_port != 0); 707177633Sdfr break; 708177633Sdfr#ifdef INET6 709177633Sdfr case AF_INET6: 710177633Sdfr bound = (((struct sockaddr_in6 *) sa)->sin6_port != 0); 711177633Sdfr break; 712177633Sdfr#endif 713177633Sdfr case AF_LOCAL: 714177633Sdfr /* XXX check this */ 715177633Sdfr bound = (((struct sockaddr_un *) sa)->sun_path[0] != '\0'); 716177633Sdfr break; 717177633Sdfr default: 718177633Sdfr bound = FALSE; 719177633Sdfr break; 720177633Sdfr } 721177633Sdfr 722177633Sdfr free(sa, M_SONAME); 723177633Sdfr 724177633Sdfr return bound; 725177633Sdfr} 726177662Sdfr 727177662Sdfr/* 728184588Sdfr * Implement XDR-style API for RPC call. 729184588Sdfr */ 730184588Sdfrenum clnt_stat 731184588Sdfrclnt_call_private( 732184588Sdfr CLIENT *cl, /* client handle */ 733184588Sdfr struct rpc_callextra *ext, /* call metadata */ 734184588Sdfr rpcproc_t proc, /* procedure number */ 735184588Sdfr xdrproc_t xargs, /* xdr routine for args */ 736184588Sdfr void *argsp, /* pointer to args */ 737184588Sdfr xdrproc_t xresults, /* xdr routine for results */ 738184588Sdfr void *resultsp, /* pointer to results */ 739184588Sdfr struct timeval utimeout) /* seconds to wait before giving up */ 740184588Sdfr{ 741184588Sdfr XDR xdrs; 742184588Sdfr struct mbuf *mreq; 743184588Sdfr struct mbuf *mrep; 744184588Sdfr enum clnt_stat stat; 745184588Sdfr 746184588Sdfr MGET(mreq, M_WAIT, MT_DATA); 747184588Sdfr MCLGET(mreq, M_WAIT); 748184588Sdfr mreq->m_len = 0; 749184588Sdfr 750184588Sdfr xdrmbuf_create(&xdrs, mreq, XDR_ENCODE); 751184588Sdfr if (!xargs(&xdrs, argsp)) { 752184588Sdfr m_freem(mreq); 753184588Sdfr return (RPC_CANTENCODEARGS); 754184588Sdfr } 755184588Sdfr XDR_DESTROY(&xdrs); 756184588Sdfr 757184588Sdfr stat = CLNT_CALL_MBUF(cl, ext, proc, mreq, &mrep, utimeout); 758184588Sdfr m_freem(mreq); 759184588Sdfr 760184588Sdfr if (stat == RPC_SUCCESS) { 761184588Sdfr xdrmbuf_create(&xdrs, mrep, XDR_DECODE); 762184588Sdfr if (!xresults(&xdrs, resultsp)) { 763184588Sdfr XDR_DESTROY(&xdrs); 764184588Sdfr return (RPC_CANTDECODERES); 765184588Sdfr } 766184588Sdfr XDR_DESTROY(&xdrs); 767184588Sdfr } 768184588Sdfr 769184588Sdfr return (stat); 770184588Sdfr} 771184588Sdfr 772184588Sdfr/* 773184588Sdfr * Bind a socket to a privileged IP port 774184588Sdfr */ 775184588Sdfrint 776184588Sdfrbindresvport(struct socket *so, struct sockaddr *sa) 777184588Sdfr{ 778184588Sdfr int old, error, af; 779184588Sdfr bool_t freesa = FALSE; 780184588Sdfr struct sockaddr_in *sin; 781184588Sdfr#ifdef INET6 782184588Sdfr struct sockaddr_in6 *sin6; 783184588Sdfr#endif 784184588Sdfr struct sockopt opt; 785184588Sdfr int proto, portrange, portlow; 786184588Sdfr u_int16_t *portp; 787184588Sdfr socklen_t salen; 788184588Sdfr 789184588Sdfr if (sa == NULL) { 790184588Sdfr error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); 791184588Sdfr if (error) 792184588Sdfr return (error); 793184588Sdfr freesa = TRUE; 794184588Sdfr af = sa->sa_family; 795184588Sdfr salen = sa->sa_len; 796184588Sdfr memset(sa, 0, sa->sa_len); 797184588Sdfr } else { 798184588Sdfr af = sa->sa_family; 799184588Sdfr salen = sa->sa_len; 800184588Sdfr } 801184588Sdfr 802184588Sdfr switch (af) { 803184588Sdfr case AF_INET: 804184588Sdfr proto = IPPROTO_IP; 805184588Sdfr portrange = IP_PORTRANGE; 806184588Sdfr portlow = IP_PORTRANGE_LOW; 807184588Sdfr sin = (struct sockaddr_in *)sa; 808184588Sdfr portp = &sin->sin_port; 809184588Sdfr break; 810184588Sdfr#ifdef INET6 811184588Sdfr case AF_INET6: 812184588Sdfr proto = IPPROTO_IPV6; 813184588Sdfr portrange = IPV6_PORTRANGE; 814184588Sdfr portlow = IPV6_PORTRANGE_LOW; 815184588Sdfr sin6 = (struct sockaddr_in6 *)sa; 816184588Sdfr portp = &sin6->sin6_port; 817184588Sdfr break; 818184588Sdfr#endif 819184588Sdfr default: 820184588Sdfr return (EPFNOSUPPORT); 821184588Sdfr } 822184588Sdfr 823184588Sdfr sa->sa_family = af; 824184588Sdfr sa->sa_len = salen; 825184588Sdfr 826184588Sdfr if (*portp == 0) { 827196503Szec CURVNET_SET(so->so_vnet); 828184588Sdfr bzero(&opt, sizeof(opt)); 829184588Sdfr opt.sopt_dir = SOPT_GET; 830184588Sdfr opt.sopt_level = proto; 831184588Sdfr opt.sopt_name = portrange; 832184588Sdfr opt.sopt_val = &old; 833184588Sdfr opt.sopt_valsize = sizeof(old); 834184588Sdfr error = sogetopt(so, &opt); 835196503Szec if (error) { 836196503Szec CURVNET_RESTORE(); 837184588Sdfr goto out; 838196503Szec } 839184588Sdfr 840184588Sdfr opt.sopt_dir = SOPT_SET; 841184588Sdfr opt.sopt_val = &portlow; 842184588Sdfr error = sosetopt(so, &opt); 843196503Szec CURVNET_RESTORE(); 844184588Sdfr if (error) 845184588Sdfr goto out; 846184588Sdfr } 847184588Sdfr 848184588Sdfr error = sobind(so, sa, curthread); 849184588Sdfr 850184588Sdfr if (*portp == 0) { 851184588Sdfr if (error) { 852184588Sdfr opt.sopt_dir = SOPT_SET; 853184588Sdfr opt.sopt_val = &old; 854196503Szec CURVNET_SET(so->so_vnet); 855184588Sdfr sosetopt(so, &opt); 856196503Szec CURVNET_RESTORE(); 857184588Sdfr } 858184588Sdfr } 859184588Sdfrout: 860184588Sdfr if (freesa) 861184588Sdfr free(sa, M_SONAME); 862184588Sdfr 863184588Sdfr return (error); 864184588Sdfr} 865184588Sdfr 866184588Sdfr/* 867177662Sdfr * Kernel module glue 868177662Sdfr */ 869177662Sdfrstatic int 870177662Sdfrkrpc_modevent(module_t mod, int type, void *data) 871177662Sdfr{ 872177662Sdfr 873177662Sdfr return (0); 874177662Sdfr} 875177662Sdfrstatic moduledata_t krpc_mod = { 876177662Sdfr "krpc", 877177662Sdfr krpc_modevent, 878177662Sdfr NULL, 879177662Sdfr}; 880177662SdfrDECLARE_MODULE(krpc, krpc_mod, SI_SUB_VFS, SI_ORDER_ANY); 881177662Sdfr 882177662Sdfr/* So that loader and kldload(2) can find us, wherever we are.. */ 883177662SdfrMODULE_VERSION(krpc, 1); 884