xref: /onnv-gate/usr/src/cmd/vscan/vscand/vs_stats.c (revision 6407:71e85e2b3164)
15440Sjm199354 /*
25440Sjm199354  * CDDL HEADER START
35440Sjm199354  *
45440Sjm199354  * The contents of this file are subject to the terms of the
55440Sjm199354  * Common Development and Distribution License (the "License").
65440Sjm199354  * You may not use this file except in compliance with the License.
75440Sjm199354  *
85440Sjm199354  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95440Sjm199354  * or http://www.opensolaris.org/os/licensing.
105440Sjm199354  * See the License for the specific language governing permissions
115440Sjm199354  * and limitations under the License.
125440Sjm199354  *
135440Sjm199354  * When distributing Covered Code, include this CDDL HEADER in each
145440Sjm199354  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155440Sjm199354  * If applicable, add the following below this CDDL HEADER, with the
165440Sjm199354  * fields enclosed by brackets "[]" replaced with your own identifying
175440Sjm199354  * information: Portions Copyright [yyyy] [name of copyright owner]
185440Sjm199354  *
195440Sjm199354  * CDDL HEADER END
205440Sjm199354  */
215440Sjm199354 /*
22*6407Sjm199354  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235440Sjm199354  * Use is subject to license terms.
245440Sjm199354  */
255440Sjm199354 
265440Sjm199354 #pragma ident	"%Z%%M%	%I%	%E% SMI"
275440Sjm199354 
285440Sjm199354 /*
295440Sjm199354  * Implementation of the vscan statistics interface
305440Sjm199354  */
315440Sjm199354 
325440Sjm199354 #include <stdio.h>
335440Sjm199354 #include <stdlib.h>
345440Sjm199354 #include <unistd.h>
355440Sjm199354 #include <string.h>
365440Sjm199354 #include <syslog.h>
375440Sjm199354 #include <pthread.h>
385440Sjm199354 #include <door.h>
395440Sjm199354 #include <pwd.h>
405440Sjm199354 #include <auth_attr.h>
415440Sjm199354 #include <secdb.h>
425440Sjm199354 #include <sys/stat.h>
435440Sjm199354 #include <fcntl.h>
445440Sjm199354 #include "vs_incl.h"
455440Sjm199354 
465440Sjm199354 
475440Sjm199354 /* local data */
485440Sjm199354 static vs_stats_t vscan_stats;
495440Sjm199354 static int vs_stats_door_cookie;
505440Sjm199354 static int vs_stats_door_fd = -1;
515440Sjm199354 static pthread_mutex_t vs_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
525440Sjm199354 
535440Sjm199354 
545440Sjm199354 /* function prototype */
555440Sjm199354 static int vs_stats_check_auth(void);
56*6407Sjm199354 static void vs_stats_reset(void);
575440Sjm199354 static void vs_stats_door_call(void *, char *, size_t, door_desc_t *, uint_t);
585440Sjm199354 
595440Sjm199354 
605440Sjm199354 /*
615440Sjm199354  * vs_stats_init
625440Sjm199354  *
635440Sjm199354  * Invoked on daemon load and unload
645440Sjm199354  */
655440Sjm199354 int
vs_stats_init(void)665440Sjm199354 vs_stats_init(void)
675440Sjm199354 {
685440Sjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
695440Sjm199354 
705440Sjm199354 	(void) memset(&vscan_stats, 0, sizeof (vs_stats_t));
715440Sjm199354 
725440Sjm199354 	/* door initialization */
735440Sjm199354 	if ((vs_stats_door_fd = door_create(vs_stats_door_call,
745440Sjm199354 	    &vs_stats_door_cookie, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
755440Sjm199354 		vs_stats_door_fd = -1;
765440Sjm199354 	} else {
775440Sjm199354 		(void) fdetach(VS_STATS_DOOR_NAME);
785440Sjm199354 		if (fattach(vs_stats_door_fd, VS_STATS_DOOR_NAME) < 0) {
795440Sjm199354 			(void) door_revoke(vs_stats_door_fd);
805440Sjm199354 			vs_stats_door_fd = -1;
815440Sjm199354 		}
825440Sjm199354 	}
835440Sjm199354 
845440Sjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
855440Sjm199354 
865440Sjm199354 	return ((vs_stats_door_fd == -1) ? -1 : 0);
875440Sjm199354 }
885440Sjm199354 
895440Sjm199354 
905440Sjm199354 /*
915440Sjm199354  * vs_stats_fini
925440Sjm199354  *
935440Sjm199354  * Invoked on daemon unload
945440Sjm199354  */
955440Sjm199354 void
vs_stats_fini(void)965440Sjm199354 vs_stats_fini(void)
975440Sjm199354 {
985440Sjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
995440Sjm199354 
1005440Sjm199354 	/* door termination */
1015440Sjm199354 	if (vs_stats_door_fd != -1)
1025440Sjm199354 		(void) door_revoke(vs_stats_door_fd);
1035440Sjm199354 	vs_stats_door_fd = -1;
1045440Sjm199354 
1055440Sjm199354 	(void) fdetach(VS_STATS_DOOR_NAME);
1065440Sjm199354 	(void) unlink(VS_STATS_DOOR_NAME);
1075440Sjm199354 
1085440Sjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
1095440Sjm199354 }
1105440Sjm199354 
1115440Sjm199354 
1125440Sjm199354 /*
1135440Sjm199354  * vs_stats_check_auth
1145440Sjm199354  *
1155440Sjm199354  * Returns: 0 caller authorized to reset stats
1165440Sjm199354  *         -1 caller not authorized to reset stats
1175440Sjm199354  */
1185440Sjm199354 static int
vs_stats_check_auth()1195440Sjm199354 vs_stats_check_auth()
1205440Sjm199354 {
1215440Sjm199354 	ucred_t *uc = NULL;
1225440Sjm199354 	uid_t uid;
1235440Sjm199354 	struct passwd *pw;
1245440Sjm199354 
1255440Sjm199354 	if (door_ucred(&uc) != 0)
1265440Sjm199354 		return (-1);
1275440Sjm199354 
1285440Sjm199354 	if (((uid = ucred_getsuid(uc)) == (uid_t)-1) ||
1295440Sjm199354 	    ((pw = getpwuid(uid)) == NULL) ||
1305440Sjm199354 	    (chkauthattr(VS_VALUE_AUTH, pw->pw_name) != 1)) {
1315440Sjm199354 		ucred_free(uc);
1325440Sjm199354 		return (-1);
1335440Sjm199354 	}
1345440Sjm199354 
1355440Sjm199354 	ucred_free(uc);
1365440Sjm199354 	return (0);
1375440Sjm199354 }
1385440Sjm199354 
1395440Sjm199354 
1405440Sjm199354 /*
1415440Sjm199354  * vs_stats_door_call
1425440Sjm199354  */
1435440Sjm199354 /* ARGSUSED */
1445440Sjm199354 static void
vs_stats_door_call(void * cookie,char * ptr,size_t size,door_desc_t * dp,uint_t n_desc)1455440Sjm199354 vs_stats_door_call(void *cookie, char *ptr, size_t size, door_desc_t *dp,
1465440Sjm199354 		uint_t n_desc)
1475440Sjm199354 {
148*6407Sjm199354 	/* LINTED E_BAD_PTR_CAST_ALIGN */
1495440Sjm199354 	vs_stats_req_t *req = (vs_stats_req_t *)ptr;
150*6407Sjm199354 	vs_stats_rsp_t rsp;
1515440Sjm199354 
152*6407Sjm199354 	if ((cookie != &vs_stats_door_cookie) ||
153*6407Sjm199354 	    (ptr == NULL) ||
154*6407Sjm199354 	    (size != sizeof (vs_stats_req_t)) ||
155*6407Sjm199354 	    (req->vsr_magic != VS_STATS_DOOR_MAGIC)) {
156*6407Sjm199354 		return;
157*6407Sjm199354 	}
158*6407Sjm199354 
159*6407Sjm199354 	rsp.vsr_magic = VS_STATS_DOOR_MAGIC;
160*6407Sjm199354 
161*6407Sjm199354 	switch (req->vsr_id) {
1625440Sjm199354 	case VS_STATS_GET:
1635440Sjm199354 		(void) pthread_mutex_lock(&vs_stats_mutex);
164*6407Sjm199354 		rsp.vsr_stats = vscan_stats;
1655440Sjm199354 		(void) pthread_mutex_unlock(&vs_stats_mutex);
166*6407Sjm199354 		(void) door_return((char *)&rsp, sizeof (vs_stats_rsp_t),
167*6407Sjm199354 		    NULL, 0);
1685440Sjm199354 		break;
1695440Sjm199354 
1705440Sjm199354 	case VS_STATS_RESET:
171*6407Sjm199354 		vs_stats_reset();
1725440Sjm199354 		(void) door_return(NULL, 0, NULL, 0);
1735440Sjm199354 		break;
1745440Sjm199354 
1755440Sjm199354 	default:
176*6407Sjm199354 		return;
1775440Sjm199354 	}
1785440Sjm199354 }
1795440Sjm199354 
1805440Sjm199354 
1815440Sjm199354 /*
182*6407Sjm199354  * vs_stats_reset
183*6407Sjm199354  *
184*6407Sjm199354  * Reset totals and per-engine statistics to 0
185*6407Sjm199354  */
186*6407Sjm199354 static void
vs_stats_reset()187*6407Sjm199354 vs_stats_reset()
188*6407Sjm199354 {
189*6407Sjm199354 	int i;
190*6407Sjm199354 
191*6407Sjm199354 	if (vs_stats_check_auth() != 0)
192*6407Sjm199354 		return;
193*6407Sjm199354 
194*6407Sjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
195*6407Sjm199354 
196*6407Sjm199354 	vscan_stats.vss_scanned = 0;
197*6407Sjm199354 	vscan_stats.vss_infected = 0;
198*6407Sjm199354 	vscan_stats.vss_cleaned = 0;
199*6407Sjm199354 	vscan_stats.vss_failed = 0;
200*6407Sjm199354 
201*6407Sjm199354 	for (i = 0; i < VS_SE_MAX; i++)
202*6407Sjm199354 		vscan_stats.vss_eng[i].vss_errors = 0;
203*6407Sjm199354 
204*6407Sjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
205*6407Sjm199354 }
206*6407Sjm199354 
207*6407Sjm199354 
208*6407Sjm199354 /*
2095440Sjm199354  * vs_stats_set
2105440Sjm199354  *
2115440Sjm199354  * Update scan request stats
2125440Sjm199354  */
2135440Sjm199354 void
vs_stats_set(int retval)2145440Sjm199354 vs_stats_set(int retval)
2155440Sjm199354 {
2165440Sjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
2175440Sjm199354 
2185440Sjm199354 	switch (retval) {
2195440Sjm199354 	case VS_RESULT_CLEAN:
2205440Sjm199354 		vscan_stats.vss_scanned++;
2215440Sjm199354 		break;
2225440Sjm199354 	case VS_RESULT_CLEANED:
2235440Sjm199354 		vscan_stats.vss_scanned++;
2245440Sjm199354 		vscan_stats.vss_infected++;
2255440Sjm199354 		vscan_stats.vss_cleaned++;
2265440Sjm199354 		break;
2275440Sjm199354 	case VS_RESULT_FORBIDDEN:
2285440Sjm199354 		vscan_stats.vss_scanned++;
2295440Sjm199354 		vscan_stats.vss_infected++;
2305440Sjm199354 		break;
2315440Sjm199354 	case VS_RESULT_SE_ERROR:
2325440Sjm199354 	case VS_RESULT_ERROR:
2335440Sjm199354 	default:
2345440Sjm199354 		vscan_stats.vss_failed++;
2355440Sjm199354 		break;
2365440Sjm199354 	}
2375440Sjm199354 
2385440Sjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
2395440Sjm199354 }
2405440Sjm199354 
2415440Sjm199354 
2425440Sjm199354 /*
2435440Sjm199354  * vs_stats_eng_err
2445440Sjm199354  *
2455440Sjm199354  * Increment the error count stat for eng
2465440Sjm199354  */
2475440Sjm199354 void
vs_stats_eng_err(char * engid)2485440Sjm199354 vs_stats_eng_err(char *engid)
2495440Sjm199354 {
2505440Sjm199354 	int i;
2515440Sjm199354 
2525440Sjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
2535440Sjm199354 
2545440Sjm199354 	for (i = 0; i < VS_SE_MAX; i++) {
2555440Sjm199354 		if (*(vscan_stats.vss_eng[i].vss_engid) == 0)
2565440Sjm199354 			break;
2575440Sjm199354 
2585440Sjm199354 		if (strcmp(vscan_stats.vss_eng[i].vss_engid, engid) == 0) {
2595440Sjm199354 			++(vscan_stats.vss_eng[i].vss_errors);
2605440Sjm199354 			break;
2615440Sjm199354 		}
2625440Sjm199354 	}
2635440Sjm199354 
2645440Sjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
2655440Sjm199354 }
2665440Sjm199354 
2675440Sjm199354 
2685440Sjm199354 /*
2695440Sjm199354  * vs_stats_config
2705440Sjm199354  */
2715440Sjm199354 void
vs_stats_config(vs_props_all_t * config)2725440Sjm199354 vs_stats_config(vs_props_all_t *config)
2735440Sjm199354 {
2745440Sjm199354 	int i, j;
2755440Sjm199354 	char *engid, *previd;
2765440Sjm199354 	vs_stats_t prev;
2775440Sjm199354 
2785440Sjm199354 	(void) pthread_mutex_lock(&vs_stats_mutex);
2795440Sjm199354 
2805440Sjm199354 	(void) memcpy(&prev, &vscan_stats, sizeof (vs_stats_t));
2815440Sjm199354 	(void) memset(&vscan_stats.vss_eng, 0, sizeof (vscan_stats.vss_eng));
2825440Sjm199354 
2835440Sjm199354 	for (i = 0; i < VS_SE_MAX; i++) {
2845440Sjm199354 		engid = config->va_se[i].vep_engid;
2855440Sjm199354 		if (*engid == 0)
2865440Sjm199354 			break;
2875440Sjm199354 
2885440Sjm199354 		(void) strlcpy(vscan_stats.vss_eng[i].vss_engid, engid,
2895440Sjm199354 		    VS_SE_NAME_LEN);
2905440Sjm199354 
2915440Sjm199354 		/* find previous error count for engid */
2925440Sjm199354 		for (j = 0; j < VS_SE_MAX; j++) {
2935440Sjm199354 			previd = prev.vss_eng[j].vss_engid;
2945440Sjm199354 			if (strcmp(previd, engid) == 0) {
2955440Sjm199354 				vscan_stats.vss_eng[i].vss_errors =
2965440Sjm199354 				    prev.vss_eng[j].vss_errors;
2975440Sjm199354 				break;
2985440Sjm199354 			}
2995440Sjm199354 		}
3005440Sjm199354 	}
3015440Sjm199354 
3025440Sjm199354 	(void) pthread_mutex_unlock(&vs_stats_mutex);
3035440Sjm199354 }
304