xref: /netbsd-src/libexec/rpc.rstatd/rstat_proc.c (revision 3e9d705017917d4119ac917ea11dea6f076f82e3)
1*3e9d7050Skre /*	$NetBSD: rstat_proc.c,v 1.53 2018/10/30 21:18:39 kre Exp $	*/
2176865a0Sthorpej 
3e7153151Sbrezak /*
4e7153151Sbrezak  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5e7153151Sbrezak  * unrestricted use provided that this legend is included on all tape
6e7153151Sbrezak  * media and as a part of the software program in whole or part.  Users
7e7153151Sbrezak  * may copy or modify Sun RPC without charge, but are not authorized
8e7153151Sbrezak  * to license or distribute it to anyone else except as part of a product or
9e7153151Sbrezak  * program developed by the user.
10e7153151Sbrezak  *
11e7153151Sbrezak  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12e7153151Sbrezak  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13e7153151Sbrezak  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14e7153151Sbrezak  *
15e7153151Sbrezak  * Sun RPC is provided with no support and without any obligation on the
16e7153151Sbrezak  * part of Sun Microsystems, Inc. to assist in its use, correction,
17e7153151Sbrezak  * modification or enhancement.
18e7153151Sbrezak  *
19e7153151Sbrezak  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20e7153151Sbrezak  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21e7153151Sbrezak  * OR ANY PART THEREOF.
22e7153151Sbrezak  *
23e7153151Sbrezak  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24e7153151Sbrezak  * or profits or other special, indirect and consequential damages, even if
25e7153151Sbrezak  * Sun has been advised of the possibility of such damages.
26e7153151Sbrezak  *
27e7153151Sbrezak  * Sun Microsystems, Inc.
28e7153151Sbrezak  * 2550 Garcia Avenue
29e7153151Sbrezak  * Mountain View, California  94043
30e7153151Sbrezak  */
31a5a68ff5Smrg 
32a5a68ff5Smrg #include <sys/cdefs.h>
33fedb6c32Sdholland #if 0
34fedb6c32Sdholland static char sccsid[] =
35fedb6c32Sdholland 	"from: @(#)rpc.rstatd.c 1.1 86/09/25 Copyr 1984 Sun Micro";
36fedb6c32Sdholland static char sccsid[] =
37fedb6c32Sdholland 	"from: @(#)rstat_proc.c	2.2 88/08/01 4.0 RPCSRC";
38fedb6c32Sdholland #endif
39*3e9d7050Skre __RCSID("$NetBSD: rstat_proc.c,v 1.53 2018/10/30 21:18:39 kre Exp $");
40e7153151Sbrezak 
41e7153151Sbrezak /*
42e7153151Sbrezak  * rstat service:  built with rstat.x and derived from rpc.rstatd.c
43e9d867efSmycroft  *
44e9d867efSmycroft  * Copyright (c) 1984 by Sun Microsystems, Inc.
45e7153151Sbrezak  */
46e7153151Sbrezak 
47f1d37094Smrg #include <sys/param.h>
4879b8558eSperry #include <sys/sched.h>
49f1d37094Smrg #include <sys/socket.h>
50b760a206Sjoerg #include <sys/ioctl.h>
51f1d37094Smrg 
523ed4fcf6Skleink #include <errno.h>
53e7153151Sbrezak #include <stdio.h>
5459e456d7Sjtc #include <stdlib.h>
5559e456d7Sjtc #include <string.h>
5659e456d7Sjtc #include <signal.h>
577cb090d9Spk #include <fcntl.h>
587cb090d9Spk #include <limits.h>
59e7153151Sbrezak #include <syslog.h>
60f1d37094Smrg #include <sys/sysctl.h>
61f1d37094Smrg #include <uvm/uvm_extern.h>
62d791be4bSblymn #include "drvstats.h"
63e7153151Sbrezak #include <net/if.h>
6459e456d7Sjtc 
65f1d37094Smrg /*
66f1d37094Smrg  * XXX
67f1d37094Smrg  *
68f1d37094Smrg  * this is a huge hack to stop `struct pmap' being
69f1d37094Smrg  * defined twice!
70f1d37094Smrg  */
718a0d3fa9Sbad #define _RPC_PMAP_PROT_H_
72f1d37094Smrg #include <rpc/rpc.h>
73f1d37094Smrg 
7459e456d7Sjtc #undef FSHIFT			 /* Use protocol's shift and scale values */
7559e456d7Sjtc #undef FSCALE
76570159beSmycroft #undef DK_NDRIVE
7700b7161eScgd #undef CPUSTATES
7800b7161eScgd #undef if_ipackets
7900b7161eScgd #undef if_ierrors
8000b7161eScgd #undef if_opackets
8100b7161eScgd #undef if_oerrors
8200b7161eScgd #undef if_collisions
83e7153151Sbrezak #include <rpcsvc/rstat.h>
84e7153151Sbrezak 
857cb090d9Spk #define BSD_CPUSTATES	5	/* Use protocol's idea of CPU states */
867cb090d9Spk int	cp_xlat[CPUSTATES] = { CP_USER, CP_NICE, CP_SYS, CP_IDLE };
877cb090d9Spk 
88b817db1eSthorpej int hz;
89b817db1eSthorpej 
90e7153151Sbrezak extern int from_inetd;
91e7153151Sbrezak int sincelastreq = 0;		/* number of alarms since last request */
92e7153151Sbrezak extern int closedown;
93e7153151Sbrezak 
94e7153151Sbrezak union {
95e7153151Sbrezak 	struct stats s1;
96e7153151Sbrezak 	struct statsswtch s2;
97e7153151Sbrezak 	struct statstime s3;
98e7153151Sbrezak } stats_all;
99e7153151Sbrezak 
1003ff53c6cSfvdl void updatestat(int);
1013ff53c6cSfvdl void stat_init(void);
1023ff53c6cSfvdl int havedisk(void);
1033ff53c6cSfvdl void rstat_service(struct svc_req *, SVCXPRT *);
104a5a68ff5Smrg 
105984d89b0Smrg static int stat_is_init = 0;
106e7153151Sbrezak 
107e7153151Sbrezak #ifndef FSCALE
108e7153151Sbrezak #define FSCALE (1 << 8)
109e7153151Sbrezak #endif
110e7153151Sbrezak 
111a5a68ff5Smrg void
stat_init(void)112c5642eeaSdholland stat_init(void)
113e7153151Sbrezak {
114e7153151Sbrezak 	stat_is_init = 1;
115b760a206Sjoerg 	drvinit(0);
116a5a68ff5Smrg 	updatestat(0);
117e7153151Sbrezak 	(void) signal(SIGALRM, updatestat);
118e7153151Sbrezak 	alarm(1);
119e7153151Sbrezak }
120e7153151Sbrezak 
121e7153151Sbrezak statstime *
rstatproc_stats_3_svc(void * arg,struct svc_req * rqstp)1223ff53c6cSfvdl rstatproc_stats_3_svc(void *arg, struct svc_req *rqstp)
123e7153151Sbrezak {
124e7153151Sbrezak 	if (!stat_is_init)
125e7153151Sbrezak 	        stat_init();
126e7153151Sbrezak 	sincelastreq = 0;
127e7153151Sbrezak 	return (&stats_all.s3);
128e7153151Sbrezak }
129e7153151Sbrezak 
130e7153151Sbrezak statsswtch *
rstatproc_stats_2_svc(void * arg,struct svc_req * rqstp)1313ff53c6cSfvdl rstatproc_stats_2_svc(void *arg, struct svc_req *rqstp)
132e7153151Sbrezak {
133e7153151Sbrezak 	if (!stat_is_init)
134e7153151Sbrezak 	        stat_init();
135e7153151Sbrezak 	sincelastreq = 0;
1366ca80cfbSfvdl 	stats_all.s2.if_opackets = stats_all.s3.if_opackets;
137e7153151Sbrezak 	return (&stats_all.s2);
138e7153151Sbrezak }
139e7153151Sbrezak 
140e7153151Sbrezak stats *
rstatproc_stats_1_svc(void * arg,struct svc_req * rqstp)1413ff53c6cSfvdl rstatproc_stats_1_svc(void *arg, struct svc_req *rqstp)
142e7153151Sbrezak {
143e7153151Sbrezak 	if (!stat_is_init)
144e7153151Sbrezak 	        stat_init();
145e7153151Sbrezak 	sincelastreq = 0;
1466ca80cfbSfvdl 	stats_all.s1.if_opackets = stats_all.s3.if_opackets;
147e7153151Sbrezak 	return (&stats_all.s1);
148e7153151Sbrezak }
149e7153151Sbrezak 
150e7153151Sbrezak u_int *
rstatproc_havedisk_3_svc(void * arg,struct svc_req * rqstp)1513ff53c6cSfvdl rstatproc_havedisk_3_svc(void *arg, struct svc_req *rqstp)
152e7153151Sbrezak {
153e7153151Sbrezak 	static u_int have;
154e7153151Sbrezak 
155e7153151Sbrezak 	if (!stat_is_init)
156e7153151Sbrezak 	        stat_init();
157e7153151Sbrezak 	sincelastreq = 0;
158e7153151Sbrezak 	have = havedisk();
159e7153151Sbrezak 	return (&have);
160e7153151Sbrezak }
161e7153151Sbrezak 
162e7153151Sbrezak u_int *
rstatproc_havedisk_2_svc(void * arg,struct svc_req * rqstp)1633ff53c6cSfvdl rstatproc_havedisk_2_svc(void *arg, struct svc_req *rqstp)
164e7153151Sbrezak {
165fed935ebSpk 	return (rstatproc_havedisk_3_svc(arg, rqstp));
166e7153151Sbrezak }
167e7153151Sbrezak 
168e7153151Sbrezak u_int *
rstatproc_havedisk_1_svc(void * arg,struct svc_req * rqstp)1693ff53c6cSfvdl rstatproc_havedisk_1_svc(void *arg, struct svc_req *rqstp)
170e7153151Sbrezak {
171fed935ebSpk 	return (rstatproc_havedisk_3_svc(arg, rqstp));
172e7153151Sbrezak }
173e7153151Sbrezak 
174e7153151Sbrezak void
updatestat(int dummy)1753ff53c6cSfvdl updatestat(int dummy)
176e7153151Sbrezak {
177b760a206Sjoerg 	struct if_nameindex *ifps;
178b760a206Sjoerg 	struct ifdatareq ifdr;
179b760a206Sjoerg 	size_t i, len;
180b760a206Sjoerg 	int mib[2], s;
181ba632e70Ssimonb 	struct uvmexp_sysctl uvmexp;
182e7153151Sbrezak 	double avrun[3];
183*3e9d7050Skre 	struct timeval tm;
184*3e9d7050Skre 	struct timespec btm;
185e7153151Sbrezak 
186e7153151Sbrezak #ifdef DEBUG
18748bf1a7fSmycroft 	syslog(LOG_DEBUG, "entering updatestat");
188e7153151Sbrezak #endif
189e7153151Sbrezak 	if (sincelastreq >= closedown) {
190e7153151Sbrezak #ifdef DEBUG
19148bf1a7fSmycroft                 syslog(LOG_DEBUG, "about to closedown");
192e7153151Sbrezak #endif
193e7153151Sbrezak                 if (from_inetd)
194e7153151Sbrezak                         exit(0);
195e7153151Sbrezak                 else {
196e7153151Sbrezak                         stat_is_init = 0;
197e7153151Sbrezak                         return;
198e7153151Sbrezak                 }
199e7153151Sbrezak 	}
200e7153151Sbrezak 	sincelastreq++;
201e7153151Sbrezak 
202b817db1eSthorpej 	/*
203d791be4bSblymn 	 * drvreadstats reads in the "disk_count" as well as the "disklist"
204b817db1eSthorpej 	 * statistics.  It also retrieves "hz" and the "cp_time" array.
205b817db1eSthorpej 	 */
206d791be4bSblymn 	drvreadstats();
2076ca80cfbSfvdl 	memset(stats_all.s3.dk_xfer, 0, sizeof(stats_all.s3.dk_xfer));
208d791be4bSblymn 	for (i = 0; i < ndrive && i < DK_NDRIVE; i++)
209d791be4bSblymn 		stats_all.s3.dk_xfer[i] = cur.rxfer[i] + cur.wxfer[i];
210b817db1eSthorpej 
2117cb090d9Spk 	for (i = 0; i < CPUSTATES; i++)
2126ca80cfbSfvdl 		stats_all.s3.cp_time[i] = cur.cp_time[cp_xlat[i]];
213e7153151Sbrezak         (void)getloadavg(avrun, sizeof(avrun) / sizeof(avrun[0]));
2146ca80cfbSfvdl 	stats_all.s3.avenrun[0] = avrun[0] * FSCALE;
2156ca80cfbSfvdl 	stats_all.s3.avenrun[1] = avrun[1] * FSCALE;
2166ca80cfbSfvdl 	stats_all.s3.avenrun[2] = avrun[2] * FSCALE;
217b788ab76Smrg 	mib[0] = CTL_KERN;
218b788ab76Smrg 	mib[1] = KERN_BOOTTIME;
219b788ab76Smrg 	len = sizeof(btm);
220b788ab76Smrg 	if (sysctl(mib, 2, &btm, &len, NULL, 0) < 0) {
221b788ab76Smrg 		syslog(LOG_ERR, "can't sysctl kern.boottime");
222e7153151Sbrezak 		exit(1);
223e7153151Sbrezak 	}
2246ca80cfbSfvdl 	stats_all.s3.boottime.tv_sec = btm.tv_sec;
225*3e9d7050Skre 	stats_all.s3.boottime.tv_usec = (suseconds_t)(btm.tv_nsec / 1000L);
226e7153151Sbrezak 
227e7153151Sbrezak 
228e7153151Sbrezak #ifdef DEBUG
2296c872090Ssimonb 	syslog(LOG_DEBUG, "%d %d %d %d %d\n", stats_all.s3.cp_time[0],
2306c872090Ssimonb 	    stats_all.s3.cp_time[1], stats_all.s3.cp_time[2],
2316c872090Ssimonb 	    stats_all.s3.cp_time[3], stats_all.s3.cp_time[4]);
232e7153151Sbrezak #endif
233e7153151Sbrezak 
234f1d37094Smrg 	mib[0] = CTL_VM;
235ba632e70Ssimonb 	mib[1] = VM_UVMEXP2;
236f1d37094Smrg 	len = sizeof(uvmexp);
237f1d37094Smrg 	if (sysctl(mib, 2, &uvmexp, &len, NULL, 0) < 0) {
238ba632e70Ssimonb 		syslog(LOG_ERR, "can't sysctl vm.uvmexp2");
239f1d37094Smrg 		exit(1);
240f1d37094Smrg 	}
241f1d37094Smrg 	stats_all.s3.v_pgpgin = uvmexp.fltanget;
242f1d37094Smrg 	stats_all.s3.v_pgpgout = uvmexp.pdpageouts;
243f1d37094Smrg 	stats_all.s3.v_pswpin = uvmexp.swapins;
244f1d37094Smrg 	stats_all.s3.v_pswpout = uvmexp.swapouts;
245f1d37094Smrg 	stats_all.s3.v_intr = uvmexp.intrs;
246f1d37094Smrg 	stats_all.s3.v_swtch = uvmexp.swtch;
247e7153151Sbrezak 	gettimeofday(&tm, (struct timezone *) 0);
2486ca80cfbSfvdl 	stats_all.s3.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
249*3e9d7050Skre 	    hz*(tm.tv_usec - (suseconds_t)(btm.tv_nsec / 1000))/1000000;
250e7153151Sbrezak 
2516ca80cfbSfvdl 	stats_all.s3.if_ipackets = 0;
2526ca80cfbSfvdl 	stats_all.s3.if_opackets = 0;
2536ca80cfbSfvdl 	stats_all.s3.if_ierrors = 0;
2546ca80cfbSfvdl 	stats_all.s3.if_oerrors = 0;
2556ca80cfbSfvdl 	stats_all.s3.if_collisions = 0;
256b760a206Sjoerg 
257b760a206Sjoerg 	ifps = if_nameindex();
258b760a206Sjoerg 	if (ifps == NULL) {
259b760a206Sjoerg 		syslog(LOG_ERR, "can't read interface list from kernel");
260e7153151Sbrezak 		exit(1);
261e7153151Sbrezak 	}
262b760a206Sjoerg 	s = socket(AF_INET, SOCK_DGRAM, 0);
263b760a206Sjoerg 	for (i = 0; s != -1 && ifps[i].if_name != NULL; ++i) {
264bcd3afecSchristos 		strlcpy(ifdr.ifdr_name, ifps[i].if_name, sizeof(ifdr.ifdr_name));
265b760a206Sjoerg 		if (ioctl(s, SIOCGIFDATA, &ifdr) != 0)
266b760a206Sjoerg 			continue;
267b760a206Sjoerg 		stats_all.s3.if_ipackets += ifdr.ifdr_data.ifi_ipackets;
268b760a206Sjoerg 		stats_all.s3.if_opackets += ifdr.ifdr_data.ifi_opackets;
269b760a206Sjoerg 		stats_all.s3.if_ierrors += ifdr.ifdr_data.ifi_ierrors;
270b760a206Sjoerg 		stats_all.s3.if_oerrors += ifdr.ifdr_data.ifi_oerrors;
271b760a206Sjoerg 		stats_all.s3.if_collisions += ifdr.ifdr_data.ifi_collisions;
272e7153151Sbrezak 	}
273b760a206Sjoerg 	if (s != -1)
274b760a206Sjoerg 		close(s);
275b760a206Sjoerg 	if_freenameindex(ifps);
276b760a206Sjoerg 
277a775363fShannken 	stats_all.s3.curtime.tv_sec = tm.tv_sec;
278a775363fShannken 	stats_all.s3.curtime.tv_usec = tm.tv_usec;
279e7153151Sbrezak 	alarm(1);
280e7153151Sbrezak }
281e7153151Sbrezak 
282e7153151Sbrezak /*
283e7153151Sbrezak  * returns true if have a disk
284e7153151Sbrezak  */
2857cb090d9Spk int
havedisk(void)286c5642eeaSdholland havedisk(void)
287e7153151Sbrezak {
288d791be4bSblymn 	return ndrive != 0;
289e7153151Sbrezak }
290e7153151Sbrezak 
291e7153151Sbrezak void
rstat_service(struct svc_req * rqstp,SVCXPRT * transp)2923ff53c6cSfvdl rstat_service(struct svc_req *rqstp, SVCXPRT *transp)
293e7153151Sbrezak {
294e7153151Sbrezak 	union {
295e7153151Sbrezak 		int fill;
296e7153151Sbrezak 	} argument;
297e7153151Sbrezak 	char *result;
2984a5c9a20Spk 	xdrproc_t xdr_argument, xdr_result;
29980bd9216Ssimonb 	char *(*local)(void *, struct svc_req *);
300e7153151Sbrezak 
301e7153151Sbrezak 	switch (rqstp->rq_proc) {
302e7153151Sbrezak 	case NULLPROC:
3032b8aaed8Splunky 		(void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
304e7153151Sbrezak 		goto leave;
305e7153151Sbrezak 
306e7153151Sbrezak 	case RSTATPROC_STATS:
3074a5c9a20Spk 		xdr_argument = (xdrproc_t)xdr_void;
3084a5c9a20Spk 		xdr_result = (xdrproc_t)xdr_statstime;
309e7153151Sbrezak                 switch (rqstp->rq_vers) {
310e7153151Sbrezak                 case RSTATVERS_ORIG:
31180bd9216Ssimonb                         local = (char *(*)(void *, struct svc_req *))
312fed935ebSpk 				rstatproc_stats_1_svc;
313e7153151Sbrezak                         break;
314e7153151Sbrezak                 case RSTATVERS_SWTCH:
31580bd9216Ssimonb                         local = (char *(*)(void *, struct svc_req *))
316fed935ebSpk 				rstatproc_stats_2_svc;
317e7153151Sbrezak                         break;
318e7153151Sbrezak                 case RSTATVERS_TIME:
31980bd9216Ssimonb                         local = (char *(*)(void *, struct svc_req *))
320fed935ebSpk 				rstatproc_stats_3_svc;
321e7153151Sbrezak                         break;
322e7153151Sbrezak                 default:
32348b71954Sbrezak                         svcerr_progvers(transp, RSTATVERS_ORIG, RSTATVERS_TIME);
324e7153151Sbrezak                         goto leave;
325e7153151Sbrezak                 }
326e7153151Sbrezak 		break;
327e7153151Sbrezak 
328e7153151Sbrezak 	case RSTATPROC_HAVEDISK:
3294a5c9a20Spk 		xdr_argument = (xdrproc_t)xdr_void;
3304a5c9a20Spk 		xdr_result = (xdrproc_t)xdr_u_int;
331e7153151Sbrezak                 switch (rqstp->rq_vers) {
332e7153151Sbrezak                 case RSTATVERS_ORIG:
33380bd9216Ssimonb                         local = (char *(*)(void *, struct svc_req *))
334fed935ebSpk 				rstatproc_havedisk_1_svc;
335e7153151Sbrezak                         break;
336e7153151Sbrezak                 case RSTATVERS_SWTCH:
33780bd9216Ssimonb                         local = (char *(*)(void *, struct svc_req *))
338fed935ebSpk 				rstatproc_havedisk_2_svc;
339e7153151Sbrezak                         break;
340e7153151Sbrezak                 case RSTATVERS_TIME:
34180bd9216Ssimonb                         local = (char *(*)(void *, struct svc_req *))
342fed935ebSpk 				rstatproc_havedisk_3_svc;
343e7153151Sbrezak                         break;
344e7153151Sbrezak                 default:
34548b71954Sbrezak                         svcerr_progvers(transp, RSTATVERS_ORIG, RSTATVERS_TIME);
346e7153151Sbrezak                         goto leave;
347e7153151Sbrezak                 }
348e7153151Sbrezak 		break;
349e7153151Sbrezak 
350e7153151Sbrezak 	default:
351e7153151Sbrezak 		svcerr_noproc(transp);
352e7153151Sbrezak 		goto leave;
353e7153151Sbrezak 	}
354bfd52621Sperry 	memset((char *)&argument, 0, sizeof(argument));
355b54e7589Scgd 	if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
356e7153151Sbrezak 		svcerr_decode(transp);
357e7153151Sbrezak 		goto leave;
358e7153151Sbrezak 	}
359e7153151Sbrezak 	result = (*local)(&argument, rqstp);
360e7153151Sbrezak 	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
361e7153151Sbrezak 		svcerr_systemerr(transp);
362e7153151Sbrezak 	}
363b54e7589Scgd 	if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
364e7153151Sbrezak 		(void)fprintf(stderr, "unable to free arguments\n");
365e7153151Sbrezak 		exit(1);
366e7153151Sbrezak 	}
367e7153151Sbrezak leave:
368e7153151Sbrezak         if (from_inetd)
369e7153151Sbrezak                 exit(0);
370e7153151Sbrezak }
371