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