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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * rpcb_stat.c 247c478bd9Sstevel@tonic-gate * Allows for gathering of statistics 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * Copyright (c) 1990 by Sun Microsystems, Inc. 277c478bd9Sstevel@tonic-gate */ 28*8f6d9daeSMarcel Telka /* 29*8f6d9daeSMarcel Telka * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 30*8f6d9daeSMarcel Telka */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <netconfig.h> 347c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 357c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h> 367c478bd9Sstevel@tonic-gate #include <sys/stat.h> 377c478bd9Sstevel@tonic-gate #ifdef PORTMAP 387c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h> 397c478bd9Sstevel@tonic-gate #endif 407c478bd9Sstevel@tonic-gate #include <stdlib.h> 41*8f6d9daeSMarcel Telka #include <atomic.h> 42*8f6d9daeSMarcel Telka #include <assert.h> 43*8f6d9daeSMarcel Telka #include <thread.h> 44*8f6d9daeSMarcel Telka #include <synch.h> 45*8f6d9daeSMarcel Telka #include <string.h> 467c478bd9Sstevel@tonic-gate #include "rpcbind.h" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate static rpcb_stat_byvers inf; 49*8f6d9daeSMarcel Telka static rwlock_t inf_lock = DEFAULTRWLOCK; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate void 52*8f6d9daeSMarcel Telka rpcbs_procinfo(int rtype, rpcproc_t proc) 537c478bd9Sstevel@tonic-gate { 54*8f6d9daeSMarcel Telka assert(rtype >= 0 && rtype < RPCBVERS_STAT); 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #ifdef PORTMAP 57*8f6d9daeSMarcel Telka if ((rtype == RPCBVERS_2_STAT) && (proc > rpcb_highproc_2)) 587c478bd9Sstevel@tonic-gate return; 59*8f6d9daeSMarcel Telka #else 60*8f6d9daeSMarcel Telka assert(rtype != RPCBVERS_2_STAT); 617c478bd9Sstevel@tonic-gate #endif 62*8f6d9daeSMarcel Telka 63*8f6d9daeSMarcel Telka if ((rtype == RPCBVERS_3_STAT) && (proc > rpcb_highproc_3)) 647c478bd9Sstevel@tonic-gate return; 65*8f6d9daeSMarcel Telka 66*8f6d9daeSMarcel Telka if ((rtype == RPCBVERS_4_STAT) && (proc > rpcb_highproc_4)) 677c478bd9Sstevel@tonic-gate return; 68*8f6d9daeSMarcel Telka 69*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&inf[rtype].info[proc], 1); 707c478bd9Sstevel@tonic-gate } 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate void 73*8f6d9daeSMarcel Telka rpcbs_set(int rtype, bool_t success) 747c478bd9Sstevel@tonic-gate { 75*8f6d9daeSMarcel Telka assert(rtype >= 0 && rtype < RPCBVERS_STAT); 76*8f6d9daeSMarcel Telka 77*8f6d9daeSMarcel Telka if (success == FALSE) 787c478bd9Sstevel@tonic-gate return; 79*8f6d9daeSMarcel Telka 80*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&inf[rtype].setinfo, 1); 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate void 84*8f6d9daeSMarcel Telka rpcbs_unset(int rtype, bool_t success) 857c478bd9Sstevel@tonic-gate { 86*8f6d9daeSMarcel Telka assert(rtype >= 0 && rtype < RPCBVERS_STAT); 87*8f6d9daeSMarcel Telka 88*8f6d9daeSMarcel Telka if (success == FALSE) 897c478bd9Sstevel@tonic-gate return; 90*8f6d9daeSMarcel Telka 91*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&inf[rtype].unsetinfo, 1); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate void 95*8f6d9daeSMarcel Telka rpcbs_getaddr(int rtype, rpcprog_t prog, rpcvers_t vers, char *netid, 96*8f6d9daeSMarcel Telka char *uaddr) 977c478bd9Sstevel@tonic-gate { 987c478bd9Sstevel@tonic-gate rpcbs_addrlist *al; 99*8f6d9daeSMarcel Telka rpcbs_addrlist *s; 100*8f6d9daeSMarcel Telka rpcbs_addrlist *wal; 1017c478bd9Sstevel@tonic-gate struct netconfig *nconf; 1027c478bd9Sstevel@tonic-gate 103*8f6d9daeSMarcel Telka assert(rtype >= 0 && rtype < RPCBVERS_STAT); 1047c478bd9Sstevel@tonic-gate 105*8f6d9daeSMarcel Telka /* 106*8f6d9daeSMarcel Telka * First try with read lock only. 107*8f6d9daeSMarcel Telka */ 108*8f6d9daeSMarcel Telka (void) rw_rdlock(&inf_lock); 109*8f6d9daeSMarcel Telka for (s = al = inf[rtype].addrinfo; al; al = al->next) { 1107c478bd9Sstevel@tonic-gate if ((al->prog == prog) && (al->vers == vers) && 1117c478bd9Sstevel@tonic-gate (strcmp(al->netid, netid) == 0)) { 112*8f6d9daeSMarcel Telka (void) rw_unlock(&inf_lock); 113*8f6d9daeSMarcel Telka 1147c478bd9Sstevel@tonic-gate if ((uaddr == NULL) || (uaddr[0] == NULL)) 115*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&al->failure, 1); 1167c478bd9Sstevel@tonic-gate else 117*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&al->success, 1); 118*8f6d9daeSMarcel Telka 1197c478bd9Sstevel@tonic-gate return; 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate } 122*8f6d9daeSMarcel Telka (void) rw_unlock(&inf_lock); 123*8f6d9daeSMarcel Telka 124*8f6d9daeSMarcel Telka /* 125*8f6d9daeSMarcel Telka * If not found, we will likely need to add a new entry, 126*8f6d9daeSMarcel Telka * so pre-allocate it, and then try to search again with write lock. 127*8f6d9daeSMarcel Telka */ 1287c478bd9Sstevel@tonic-gate nconf = rpcbind_get_conf(netid); 1297c478bd9Sstevel@tonic-gate if (nconf == NULL) { 1307c478bd9Sstevel@tonic-gate return; 1317c478bd9Sstevel@tonic-gate } 132*8f6d9daeSMarcel Telka 1337c478bd9Sstevel@tonic-gate al = (rpcbs_addrlist *) malloc(sizeof (rpcbs_addrlist)); 1347c478bd9Sstevel@tonic-gate if (al == NULL) { 1357c478bd9Sstevel@tonic-gate return; 1367c478bd9Sstevel@tonic-gate } 137*8f6d9daeSMarcel Telka 1387c478bd9Sstevel@tonic-gate al->prog = prog; 1397c478bd9Sstevel@tonic-gate al->vers = vers; 1407c478bd9Sstevel@tonic-gate al->netid = nconf->nc_netid; 1417c478bd9Sstevel@tonic-gate if ((uaddr == NULL) || (uaddr[0] == NULL)) { 1427c478bd9Sstevel@tonic-gate al->failure = 1; 1437c478bd9Sstevel@tonic-gate al->success = 0; 1447c478bd9Sstevel@tonic-gate } else { 1457c478bd9Sstevel@tonic-gate al->failure = 0; 1467c478bd9Sstevel@tonic-gate al->success = 1; 1477c478bd9Sstevel@tonic-gate } 148*8f6d9daeSMarcel Telka 149*8f6d9daeSMarcel Telka (void) rw_wrlock(&inf_lock); 150*8f6d9daeSMarcel Telka for (wal = inf[rtype].addrinfo; wal != s; wal = wal->next) { 151*8f6d9daeSMarcel Telka if ((wal->prog == prog) && (wal->vers == vers) && 152*8f6d9daeSMarcel Telka (strcmp(wal->netid, netid) == 0)) { 153*8f6d9daeSMarcel Telka (void) rw_unlock(&inf_lock); 154*8f6d9daeSMarcel Telka 155*8f6d9daeSMarcel Telka free(al); 156*8f6d9daeSMarcel Telka 157*8f6d9daeSMarcel Telka if ((uaddr == NULL) || (uaddr[0] == NULL)) 158*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&wal->failure, 1); 159*8f6d9daeSMarcel Telka else 160*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&wal->success, 1); 161*8f6d9daeSMarcel Telka 162*8f6d9daeSMarcel Telka return; 163*8f6d9daeSMarcel Telka } 164*8f6d9daeSMarcel Telka } 165*8f6d9daeSMarcel Telka 1667c478bd9Sstevel@tonic-gate al->next = inf[rtype].addrinfo; 1677c478bd9Sstevel@tonic-gate inf[rtype].addrinfo = al; 168*8f6d9daeSMarcel Telka (void) rw_unlock(&inf_lock); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 171*8f6d9daeSMarcel Telka /* 172*8f6d9daeSMarcel Telka * rpcbproc - rpcbind proc number on which this was called 173*8f6d9daeSMarcel Telka */ 1747c478bd9Sstevel@tonic-gate void 175*8f6d9daeSMarcel Telka rpcbs_rmtcall(int rtype, rpcproc_t rpcbproc, rpcprog_t prog, rpcvers_t vers, 176*8f6d9daeSMarcel Telka rpcproc_t proc, char *netid, rpcblist_ptr rbl) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate rpcbs_rmtcalllist *rl; 179*8f6d9daeSMarcel Telka rpcbs_rmtcalllist *s; 180*8f6d9daeSMarcel Telka rpcbs_rmtcalllist *wrl; 1817c478bd9Sstevel@tonic-gate struct netconfig *nconf; 1827c478bd9Sstevel@tonic-gate 183*8f6d9daeSMarcel Telka assert(rtype >= 0 && rtype < RPCBVERS_STAT); 1847c478bd9Sstevel@tonic-gate 185*8f6d9daeSMarcel Telka /* 186*8f6d9daeSMarcel Telka * First try with read lock only. 187*8f6d9daeSMarcel Telka */ 188*8f6d9daeSMarcel Telka (void) rw_rdlock(&inf_lock); 189*8f6d9daeSMarcel Telka for (s = rl = inf[rtype].rmtinfo; rl; rl = rl->next) { 1907c478bd9Sstevel@tonic-gate if ((rl->prog == prog) && (rl->vers == vers) && 191*8f6d9daeSMarcel Telka (rl->proc == proc) && (strcmp(rl->netid, netid) == 0)) { 192*8f6d9daeSMarcel Telka (void) rw_unlock(&inf_lock); 193*8f6d9daeSMarcel Telka 194*8f6d9daeSMarcel Telka if ((rbl == NULL) || (rbl->rpcb_map.r_vers != vers)) 195*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&rl->failure, 1); 1967c478bd9Sstevel@tonic-gate else 197*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&rl->success, 1); 1987c478bd9Sstevel@tonic-gate if (rpcbproc == RPCBPROC_INDIRECT) 199*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&rl->indirect, 1); 200*8f6d9daeSMarcel Telka 2017c478bd9Sstevel@tonic-gate return; 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate } 204*8f6d9daeSMarcel Telka (void) rw_unlock(&inf_lock); 205*8f6d9daeSMarcel Telka 206*8f6d9daeSMarcel Telka /* 207*8f6d9daeSMarcel Telka * If not found, we will likely need to add a new entry, 208*8f6d9daeSMarcel Telka * so pre-allocate it, and then try to search again with write lock. 209*8f6d9daeSMarcel Telka */ 2107c478bd9Sstevel@tonic-gate nconf = rpcbind_get_conf(netid); 2117c478bd9Sstevel@tonic-gate if (nconf == NULL) { 2127c478bd9Sstevel@tonic-gate return; 2137c478bd9Sstevel@tonic-gate } 214*8f6d9daeSMarcel Telka 2157c478bd9Sstevel@tonic-gate rl = (rpcbs_rmtcalllist *) malloc(sizeof (rpcbs_rmtcalllist)); 2167c478bd9Sstevel@tonic-gate if (rl == NULL) { 2177c478bd9Sstevel@tonic-gate return; 2187c478bd9Sstevel@tonic-gate } 219*8f6d9daeSMarcel Telka 2207c478bd9Sstevel@tonic-gate rl->prog = prog; 2217c478bd9Sstevel@tonic-gate rl->vers = vers; 2227c478bd9Sstevel@tonic-gate rl->proc = proc; 2237c478bd9Sstevel@tonic-gate rl->netid = nconf->nc_netid; 224*8f6d9daeSMarcel Telka if ((rbl == NULL) || (rbl->rpcb_map.r_vers != vers)) { 2257c478bd9Sstevel@tonic-gate rl->failure = 1; 2267c478bd9Sstevel@tonic-gate rl->success = 0; 2277c478bd9Sstevel@tonic-gate } else { 2287c478bd9Sstevel@tonic-gate rl->failure = 0; 2297c478bd9Sstevel@tonic-gate rl->success = 1; 2307c478bd9Sstevel@tonic-gate } 231*8f6d9daeSMarcel Telka rl->indirect = rpcbproc == RPCBPROC_INDIRECT ? 1 : 0; 232*8f6d9daeSMarcel Telka 233*8f6d9daeSMarcel Telka (void) rw_wrlock(&inf_lock); 234*8f6d9daeSMarcel Telka for (wrl = inf[rtype].rmtinfo; wrl != s; wrl = wrl->next) { 235*8f6d9daeSMarcel Telka if ((wrl->prog == prog) && (wrl->vers == vers) && 236*8f6d9daeSMarcel Telka (wrl->proc == proc) && (strcmp(wrl->netid, netid) == 0)) { 237*8f6d9daeSMarcel Telka (void) rw_unlock(&inf_lock); 238*8f6d9daeSMarcel Telka 239*8f6d9daeSMarcel Telka free(rl); 240*8f6d9daeSMarcel Telka 241*8f6d9daeSMarcel Telka if ((rbl == NULL) || (rbl->rpcb_map.r_vers != vers)) 242*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&wrl->failure, 1); 243*8f6d9daeSMarcel Telka else 244*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&wrl->success, 1); 245*8f6d9daeSMarcel Telka if (rpcbproc == RPCBPROC_INDIRECT) 246*8f6d9daeSMarcel Telka atomic_add_int((uint_t *)&wrl->indirect, 1); 247*8f6d9daeSMarcel Telka 2487c478bd9Sstevel@tonic-gate return; 2497c478bd9Sstevel@tonic-gate } 250*8f6d9daeSMarcel Telka } 2517c478bd9Sstevel@tonic-gate 252*8f6d9daeSMarcel Telka rl->next = inf[rtype].rmtinfo; 253*8f6d9daeSMarcel Telka inf[rtype].rmtinfo = rl; 254*8f6d9daeSMarcel Telka (void) rw_unlock(&inf_lock); 255*8f6d9daeSMarcel Telka } 256*8f6d9daeSMarcel Telka 257*8f6d9daeSMarcel Telka /* ARGSUSED */ 258*8f6d9daeSMarcel Telka bool_t 259*8f6d9daeSMarcel Telka rpcbproc_getstat(void *argp, rpcb_stat_byvers **result) 2607c478bd9Sstevel@tonic-gate { 261*8f6d9daeSMarcel Telka /* 262*8f6d9daeSMarcel Telka * inf_lock is unlocked in xdr_rpcb_stat_byvers_ptr() 263*8f6d9daeSMarcel Telka */ 264*8f6d9daeSMarcel Telka (void) rw_rdlock(&inf_lock); 265*8f6d9daeSMarcel Telka *result = &inf; 266*8f6d9daeSMarcel Telka return (TRUE); 267*8f6d9daeSMarcel Telka } 268*8f6d9daeSMarcel Telka 269*8f6d9daeSMarcel Telka bool_t 270*8f6d9daeSMarcel Telka xdr_rpcb_stat_byvers_ptr(XDR *xdrs, rpcb_stat_byvers **objp) 271*8f6d9daeSMarcel Telka { 272*8f6d9daeSMarcel Telka if (xdrs->x_op == XDR_FREE) { 273*8f6d9daeSMarcel Telka /* 274*8f6d9daeSMarcel Telka * inf_lock is locked in rpcbproc_getstat() 275*8f6d9daeSMarcel Telka */ 276*8f6d9daeSMarcel Telka (void) rw_unlock(&inf_lock); 277*8f6d9daeSMarcel Telka return (TRUE); 278*8f6d9daeSMarcel Telka } 279*8f6d9daeSMarcel Telka 280*8f6d9daeSMarcel Telka return (xdr_rpcb_stat_byvers(xdrs, (rpcb_stat *)*objp)); 2817c478bd9Sstevel@tonic-gate } 282