xref: /titanic_50/usr/src/cmd/vscan/vscand/vs_stats.c (revision bfc848c632c9eacb2a640246d96e198f1b185c03)
1911106dfSjm199354 /*
2911106dfSjm199354  * CDDL HEADER START
3911106dfSjm199354  *
4911106dfSjm199354  * The contents of this file are subject to the terms of the
5911106dfSjm199354  * Common Development and Distribution License (the "License").
6911106dfSjm199354  * You may not use this file except in compliance with the License.
7911106dfSjm199354  *
8911106dfSjm199354  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9911106dfSjm199354  * or http://www.opensolaris.org/os/licensing.
10911106dfSjm199354  * See the License for the specific language governing permissions
11911106dfSjm199354  * and limitations under the License.
12911106dfSjm199354  *
13911106dfSjm199354  * When distributing Covered Code, include this CDDL HEADER in each
14911106dfSjm199354  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15911106dfSjm199354  * If applicable, add the following below this CDDL HEADER, with the
16911106dfSjm199354  * fields enclosed by brackets "[]" replaced with your own identifying
17911106dfSjm199354  * information: Portions Copyright [yyyy] [name of copyright owner]
18911106dfSjm199354  *
19911106dfSjm199354  * CDDL HEADER END
20911106dfSjm199354  */
21911106dfSjm199354 /*
22*bfc848c6Sjm199354  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23911106dfSjm199354  * Use is subject to license terms.
24911106dfSjm199354  */
25911106dfSjm199354 
26911106dfSjm199354 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27911106dfSjm199354 
28911106dfSjm199354 /*
29911106dfSjm199354  * Implementation of the vscan statistics interface
30911106dfSjm199354  */
31911106dfSjm199354 
32911106dfSjm199354 #include <stdio.h>
33911106dfSjm199354 #include <stdlib.h>
34911106dfSjm199354 #include <unistd.h>
35911106dfSjm199354 #include <string.h>
36911106dfSjm199354 #include <syslog.h>
37911106dfSjm199354 #include <pthread.h>
38911106dfSjm199354 #include <door.h>
39911106dfSjm199354 #include <pwd.h>
40911106dfSjm199354 #include <auth_attr.h>
41911106dfSjm199354 #include <secdb.h>
42911106dfSjm199354 #include <sys/stat.h>
43911106dfSjm199354 #include <fcntl.h>
44911106dfSjm199354 #include "vs_incl.h"
45911106dfSjm199354 
46911106dfSjm199354 
47911106dfSjm199354 /* local data */
48911106dfSjm199354 static vs_stats_t vscan_stats;
49911106dfSjm199354 static int vs_stats_door_cookie;
50911106dfSjm199354 static int vs_stats_door_fd = -1;
51911106dfSjm199354 static pthread_mutex_t vs_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
52911106dfSjm199354 
53911106dfSjm199354 
54911106dfSjm199354 /* function prototype */
55911106dfSjm199354 static int vs_stats_check_auth(void);
56*bfc848c6Sjm199354 static void vs_stats_reset(void);
57911106dfSjm199354 static void vs_stats_door_call(void *, char *, size_t, door_desc_t *, uint_t);
58911106dfSjm199354 
59911106dfSjm199354 
60911106dfSjm199354 /*
61911106dfSjm199354  * vs_stats_init
62911106dfSjm199354  *
63911106dfSjm199354  * Invoked on daemon load and unload
64911106dfSjm199354  */
65911106dfSjm199354 int
vs_stats_init(void)66911106dfSjm199354 vs_stats_init(void)
67911106dfSjm199354 {
68911106dfSjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
69911106dfSjm199354 
70911106dfSjm199354 	(void) memset(&vscan_stats, 0, sizeof (vs_stats_t));
71911106dfSjm199354 
72911106dfSjm199354 	/* door initialization */
73911106dfSjm199354 	if ((vs_stats_door_fd = door_create(vs_stats_door_call,
74911106dfSjm199354 	    &vs_stats_door_cookie, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
75911106dfSjm199354 		vs_stats_door_fd = -1;
76911106dfSjm199354 	} else {
77911106dfSjm199354 		(void) fdetach(VS_STATS_DOOR_NAME);
78911106dfSjm199354 		if (fattach(vs_stats_door_fd, VS_STATS_DOOR_NAME) < 0) {
79911106dfSjm199354 			(void) door_revoke(vs_stats_door_fd);
80911106dfSjm199354 			vs_stats_door_fd = -1;
81911106dfSjm199354 		}
82911106dfSjm199354 	}
83911106dfSjm199354 
84911106dfSjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
85911106dfSjm199354 
86911106dfSjm199354 	return ((vs_stats_door_fd == -1) ? -1 : 0);
87911106dfSjm199354 }
88911106dfSjm199354 
89911106dfSjm199354 
90911106dfSjm199354 /*
91911106dfSjm199354  * vs_stats_fini
92911106dfSjm199354  *
93911106dfSjm199354  * Invoked on daemon unload
94911106dfSjm199354  */
95911106dfSjm199354 void
vs_stats_fini(void)96911106dfSjm199354 vs_stats_fini(void)
97911106dfSjm199354 {
98911106dfSjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
99911106dfSjm199354 
100911106dfSjm199354 	/* door termination */
101911106dfSjm199354 	if (vs_stats_door_fd != -1)
102911106dfSjm199354 		(void) door_revoke(vs_stats_door_fd);
103911106dfSjm199354 	vs_stats_door_fd = -1;
104911106dfSjm199354 
105911106dfSjm199354 	(void) fdetach(VS_STATS_DOOR_NAME);
106911106dfSjm199354 	(void) unlink(VS_STATS_DOOR_NAME);
107911106dfSjm199354 
108911106dfSjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
109911106dfSjm199354 }
110911106dfSjm199354 
111911106dfSjm199354 
112911106dfSjm199354 /*
113911106dfSjm199354  * vs_stats_check_auth
114911106dfSjm199354  *
115911106dfSjm199354  * Returns: 0 caller authorized to reset stats
116911106dfSjm199354  *         -1 caller not authorized to reset stats
117911106dfSjm199354  */
118911106dfSjm199354 static int
vs_stats_check_auth()119911106dfSjm199354 vs_stats_check_auth()
120911106dfSjm199354 {
121911106dfSjm199354 	ucred_t *uc = NULL;
122911106dfSjm199354 	uid_t uid;
123911106dfSjm199354 	struct passwd *pw;
124911106dfSjm199354 
125911106dfSjm199354 	if (door_ucred(&uc) != 0)
126911106dfSjm199354 		return (-1);
127911106dfSjm199354 
128911106dfSjm199354 	if (((uid = ucred_getsuid(uc)) == (uid_t)-1) ||
129911106dfSjm199354 	    ((pw = getpwuid(uid)) == NULL) ||
130911106dfSjm199354 	    (chkauthattr(VS_VALUE_AUTH, pw->pw_name) != 1)) {
131911106dfSjm199354 		ucred_free(uc);
132911106dfSjm199354 		return (-1);
133911106dfSjm199354 	}
134911106dfSjm199354 
135911106dfSjm199354 	ucred_free(uc);
136911106dfSjm199354 	return (0);
137911106dfSjm199354 }
138911106dfSjm199354 
139911106dfSjm199354 
140911106dfSjm199354 /*
141911106dfSjm199354  * vs_stats_door_call
142911106dfSjm199354  */
143911106dfSjm199354 /* ARGSUSED */
144911106dfSjm199354 static void
vs_stats_door_call(void * cookie,char * ptr,size_t size,door_desc_t * dp,uint_t n_desc)145911106dfSjm199354 vs_stats_door_call(void *cookie, char *ptr, size_t size, door_desc_t *dp,
146911106dfSjm199354 		uint_t n_desc)
147911106dfSjm199354 {
148*bfc848c6Sjm199354 	/* LINTED E_BAD_PTR_CAST_ALIGN */
149911106dfSjm199354 	vs_stats_req_t *req = (vs_stats_req_t *)ptr;
150*bfc848c6Sjm199354 	vs_stats_rsp_t rsp;
151911106dfSjm199354 
152*bfc848c6Sjm199354 	if ((cookie != &vs_stats_door_cookie) ||
153*bfc848c6Sjm199354 	    (ptr == NULL) ||
154*bfc848c6Sjm199354 	    (size != sizeof (vs_stats_req_t)) ||
155*bfc848c6Sjm199354 	    (req->vsr_magic != VS_STATS_DOOR_MAGIC)) {
156*bfc848c6Sjm199354 		return;
157*bfc848c6Sjm199354 	}
158*bfc848c6Sjm199354 
159*bfc848c6Sjm199354 	rsp.vsr_magic = VS_STATS_DOOR_MAGIC;
160*bfc848c6Sjm199354 
161*bfc848c6Sjm199354 	switch (req->vsr_id) {
162911106dfSjm199354 	case VS_STATS_GET:
163911106dfSjm199354 		(void) pthread_mutex_lock(&vs_stats_mutex);
164*bfc848c6Sjm199354 		rsp.vsr_stats = vscan_stats;
165911106dfSjm199354 		(void) pthread_mutex_unlock(&vs_stats_mutex);
166*bfc848c6Sjm199354 		(void) door_return((char *)&rsp, sizeof (vs_stats_rsp_t),
167*bfc848c6Sjm199354 		    NULL, 0);
168911106dfSjm199354 		break;
169911106dfSjm199354 
170911106dfSjm199354 	case VS_STATS_RESET:
171*bfc848c6Sjm199354 		vs_stats_reset();
172911106dfSjm199354 		(void) door_return(NULL, 0, NULL, 0);
173911106dfSjm199354 		break;
174911106dfSjm199354 
175911106dfSjm199354 	default:
176*bfc848c6Sjm199354 		return;
177911106dfSjm199354 	}
178911106dfSjm199354 }
179911106dfSjm199354 
180911106dfSjm199354 
181911106dfSjm199354 /*
182*bfc848c6Sjm199354  * vs_stats_reset
183*bfc848c6Sjm199354  *
184*bfc848c6Sjm199354  * Reset totals and per-engine statistics to 0
185*bfc848c6Sjm199354  */
186*bfc848c6Sjm199354 static void
vs_stats_reset()187*bfc848c6Sjm199354 vs_stats_reset()
188*bfc848c6Sjm199354 {
189*bfc848c6Sjm199354 	int i;
190*bfc848c6Sjm199354 
191*bfc848c6Sjm199354 	if (vs_stats_check_auth() != 0)
192*bfc848c6Sjm199354 		return;
193*bfc848c6Sjm199354 
194*bfc848c6Sjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
195*bfc848c6Sjm199354 
196*bfc848c6Sjm199354 	vscan_stats.vss_scanned = 0;
197*bfc848c6Sjm199354 	vscan_stats.vss_infected = 0;
198*bfc848c6Sjm199354 	vscan_stats.vss_cleaned = 0;
199*bfc848c6Sjm199354 	vscan_stats.vss_failed = 0;
200*bfc848c6Sjm199354 
201*bfc848c6Sjm199354 	for (i = 0; i < VS_SE_MAX; i++)
202*bfc848c6Sjm199354 		vscan_stats.vss_eng[i].vss_errors = 0;
203*bfc848c6Sjm199354 
204*bfc848c6Sjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
205*bfc848c6Sjm199354 }
206*bfc848c6Sjm199354 
207*bfc848c6Sjm199354 
208*bfc848c6Sjm199354 /*
209911106dfSjm199354  * vs_stats_set
210911106dfSjm199354  *
211911106dfSjm199354  * Update scan request stats
212911106dfSjm199354  */
213911106dfSjm199354 void
vs_stats_set(int retval)214911106dfSjm199354 vs_stats_set(int retval)
215911106dfSjm199354 {
216911106dfSjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
217911106dfSjm199354 
218911106dfSjm199354 	switch (retval) {
219911106dfSjm199354 	case VS_RESULT_CLEAN:
220911106dfSjm199354 		vscan_stats.vss_scanned++;
221911106dfSjm199354 		break;
222911106dfSjm199354 	case VS_RESULT_CLEANED:
223911106dfSjm199354 		vscan_stats.vss_scanned++;
224911106dfSjm199354 		vscan_stats.vss_infected++;
225911106dfSjm199354 		vscan_stats.vss_cleaned++;
226911106dfSjm199354 		break;
227911106dfSjm199354 	case VS_RESULT_FORBIDDEN:
228911106dfSjm199354 		vscan_stats.vss_scanned++;
229911106dfSjm199354 		vscan_stats.vss_infected++;
230911106dfSjm199354 		break;
231911106dfSjm199354 	case VS_RESULT_SE_ERROR:
232911106dfSjm199354 	case VS_RESULT_ERROR:
233911106dfSjm199354 	default:
234911106dfSjm199354 		vscan_stats.vss_failed++;
235911106dfSjm199354 		break;
236911106dfSjm199354 	}
237911106dfSjm199354 
238911106dfSjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
239911106dfSjm199354 }
240911106dfSjm199354 
241911106dfSjm199354 
242911106dfSjm199354 /*
243911106dfSjm199354  * vs_stats_eng_err
244911106dfSjm199354  *
245911106dfSjm199354  * Increment the error count stat for eng
246911106dfSjm199354  */
247911106dfSjm199354 void
vs_stats_eng_err(char * engid)248911106dfSjm199354 vs_stats_eng_err(char *engid)
249911106dfSjm199354 {
250911106dfSjm199354 	int i;
251911106dfSjm199354 
252911106dfSjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
253911106dfSjm199354 
254911106dfSjm199354 	for (i = 0; i < VS_SE_MAX; i++) {
255911106dfSjm199354 		if (*(vscan_stats.vss_eng[i].vss_engid) == 0)
256911106dfSjm199354 			break;
257911106dfSjm199354 
258911106dfSjm199354 		if (strcmp(vscan_stats.vss_eng[i].vss_engid, engid) == 0) {
259911106dfSjm199354 			++(vscan_stats.vss_eng[i].vss_errors);
260911106dfSjm199354 			break;
261911106dfSjm199354 		}
262911106dfSjm199354 	}
263911106dfSjm199354 
264911106dfSjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
265911106dfSjm199354 }
266911106dfSjm199354 
267911106dfSjm199354 
268911106dfSjm199354 /*
269911106dfSjm199354  * vs_stats_config
270911106dfSjm199354  */
271911106dfSjm199354 void
vs_stats_config(vs_props_all_t * config)272911106dfSjm199354 vs_stats_config(vs_props_all_t *config)
273911106dfSjm199354 {
274911106dfSjm199354 	int i, j;
275911106dfSjm199354 	char *engid, *previd;
276911106dfSjm199354 	vs_stats_t prev;
277911106dfSjm199354 
278911106dfSjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
279911106dfSjm199354 
280911106dfSjm199354 	(void) memcpy(&prev, &vscan_stats, sizeof (vs_stats_t));
281911106dfSjm199354 	(void) memset(&vscan_stats.vss_eng, 0, sizeof (vscan_stats.vss_eng));
282911106dfSjm199354 
283911106dfSjm199354 	for (i = 0; i < VS_SE_MAX; i++) {
284911106dfSjm199354 		engid = config->va_se[i].vep_engid;
285911106dfSjm199354 		if (*engid == 0)
286911106dfSjm199354 			break;
287911106dfSjm199354 
288911106dfSjm199354 		(void) strlcpy(vscan_stats.vss_eng[i].vss_engid, engid,
289911106dfSjm199354 		    VS_SE_NAME_LEN);
290911106dfSjm199354 
291911106dfSjm199354 		/* find previous error count for engid */
292911106dfSjm199354 		for (j = 0; j < VS_SE_MAX; j++) {
293911106dfSjm199354 			previd = prev.vss_eng[j].vss_engid;
294911106dfSjm199354 			if (strcmp(previd, engid) == 0) {
295911106dfSjm199354 				vscan_stats.vss_eng[i].vss_errors =
296911106dfSjm199354 				    prev.vss_eng[j].vss_errors;
297911106dfSjm199354 				break;
298911106dfSjm199354 			}
299911106dfSjm199354 		}
300911106dfSjm199354 	}
301911106dfSjm199354 
302911106dfSjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
303911106dfSjm199354 }
304