xref: /illumos-gate/usr/src/cmd/vscan/vscand/vs_stats.c (revision bea83d026ee1bd1b2a2419e1d0232f107a5d7d9b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Implementation of the vscan statistics interface
30  */
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <syslog.h>
37 #include <pthread.h>
38 #include <door.h>
39 #include <pwd.h>
40 #include <auth_attr.h>
41 #include <secdb.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include "vs_incl.h"
45 
46 
47 /* local data */
48 static vs_stats_t vscan_stats;
49 static int vs_stats_door_cookie;
50 static int vs_stats_door_fd = -1;
51 static pthread_mutex_t vs_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
52 
53 
54 /* function prototype */
55 static int vs_stats_check_auth(void);
56 static void vs_stats_door_call(void *, char *, size_t, door_desc_t *, uint_t);
57 
58 
59 /*
60  * vs_stats_init
61  *
62  * Invoked on daemon load and unload
63  */
64 int
65 vs_stats_init(void)
66 {
67 	(void) pthread_mutex_lock(&vs_stats_mutex);
68 
69 	(void) memset(&vscan_stats, 0, sizeof (vs_stats_t));
70 
71 	/* door initialization */
72 	if ((vs_stats_door_fd = door_create(vs_stats_door_call,
73 	    &vs_stats_door_cookie, (DOOR_UNREF | DOOR_REFUSE_DESC))) < 0) {
74 		vs_stats_door_fd = -1;
75 	} else {
76 		(void) fdetach(VS_STATS_DOOR_NAME);
77 		if (fattach(vs_stats_door_fd, VS_STATS_DOOR_NAME) < 0) {
78 			(void) door_revoke(vs_stats_door_fd);
79 			vs_stats_door_fd = -1;
80 		}
81 	}
82 
83 	(void) pthread_mutex_unlock(&vs_stats_mutex);
84 
85 	return ((vs_stats_door_fd == -1) ? -1 : 0);
86 }
87 
88 
89 /*
90  * vs_stats_fini
91  *
92  * Invoked on daemon unload
93  */
94 void
95 vs_stats_fini(void)
96 {
97 	(void) pthread_mutex_lock(&vs_stats_mutex);
98 
99 	/* door termination */
100 	if (vs_stats_door_fd != -1)
101 		(void) door_revoke(vs_stats_door_fd);
102 	vs_stats_door_fd = -1;
103 
104 	(void) fdetach(VS_STATS_DOOR_NAME);
105 	(void) unlink(VS_STATS_DOOR_NAME);
106 
107 	(void) pthread_mutex_unlock(&vs_stats_mutex);
108 }
109 
110 
111 /*
112  * vs_stats_check_auth
113  *
114  * Returns: 0 caller authorized to reset stats
115  *         -1 caller not authorized to reset stats
116  */
117 static int
118 vs_stats_check_auth()
119 {
120 	ucred_t *uc = NULL;
121 	uid_t uid;
122 	struct passwd *pw;
123 
124 	if (door_ucred(&uc) != 0)
125 		return (-1);
126 
127 	if (((uid = ucred_getsuid(uc)) == (uid_t)-1) ||
128 	    ((pw = getpwuid(uid)) == NULL) ||
129 	    (chkauthattr(VS_VALUE_AUTH, pw->pw_name) != 1)) {
130 		ucred_free(uc);
131 		return (-1);
132 	}
133 
134 	ucred_free(uc);
135 	return (0);
136 }
137 
138 
139 /*
140  * vs_stats_door_call
141  */
142 /* ARGSUSED */
143 static void
144 vs_stats_door_call(void *cookie, char *ptr, size_t size, door_desc_t *dp,
145 		uint_t n_desc)
146 {
147 	/* LINTED E_BAD_PTR_CAST_ALIGN - to be fixed with encoding */
148 	vs_stats_req_t *req = (vs_stats_req_t *)ptr;
149 	vs_stats_t rsp;
150 
151 	switch (*req) {
152 	case VS_STATS_GET:
153 		(void) pthread_mutex_lock(&vs_stats_mutex);
154 		(void) memcpy(&rsp, &vscan_stats, sizeof (vs_stats_t));
155 		(void) pthread_mutex_unlock(&vs_stats_mutex);
156 		(void) door_return((char *)&rsp, sizeof (vs_stats_t), NULL, 0);
157 		break;
158 
159 	case VS_STATS_RESET:
160 		if (vs_stats_check_auth() == 0) {
161 			(void) pthread_mutex_lock(&vs_stats_mutex);
162 			(void) memset(&vscan_stats, 0, sizeof (vs_stats_t));
163 			(void) pthread_mutex_unlock(&vs_stats_mutex);
164 		}
165 		(void) door_return(NULL, 0, NULL, 0);
166 		break;
167 
168 	default:
169 		(void) door_return(NULL, 0, NULL, 0);
170 		break;
171 	}
172 }
173 
174 
175 /*
176  * vs_stats_set
177  *
178  * Update scan request stats
179  */
180 void
181 vs_stats_set(int retval)
182 {
183 	(void) pthread_mutex_lock(&vs_stats_mutex);
184 
185 	switch (retval) {
186 	case VS_RESULT_CLEAN:
187 		vscan_stats.vss_scanned++;
188 		break;
189 	case VS_RESULT_CLEANED:
190 		vscan_stats.vss_scanned++;
191 		vscan_stats.vss_infected++;
192 		vscan_stats.vss_cleaned++;
193 		break;
194 	case VS_RESULT_FORBIDDEN:
195 		vscan_stats.vss_scanned++;
196 		vscan_stats.vss_infected++;
197 		break;
198 	case VS_RESULT_SE_ERROR:
199 	case VS_RESULT_ERROR:
200 	default:
201 		vscan_stats.vss_failed++;
202 		break;
203 	}
204 
205 	(void) pthread_mutex_unlock(&vs_stats_mutex);
206 }
207 
208 
209 /*
210  * vs_stats_eng_err
211  *
212  * Increment the error count stat for eng
213  */
214 void
215 vs_stats_eng_err(char *engid)
216 {
217 	int i;
218 
219 	(void) pthread_mutex_lock(&vs_stats_mutex);
220 
221 	for (i = 0; i < VS_SE_MAX; i++) {
222 		if (*(vscan_stats.vss_eng[i].vss_engid) == 0)
223 			break;
224 
225 		if (strcmp(vscan_stats.vss_eng[i].vss_engid, engid) == 0) {
226 			++(vscan_stats.vss_eng[i].vss_errors);
227 			break;
228 		}
229 	}
230 
231 	(void) pthread_mutex_unlock(&vs_stats_mutex);
232 }
233 
234 
235 /*
236  * vs_stats_config
237  */
238 void
239 vs_stats_config(vs_props_all_t *config)
240 {
241 	int i, j;
242 	char *engid, *previd;
243 	vs_stats_t prev;
244 
245 	(void) pthread_mutex_lock(&vs_stats_mutex);
246 
247 	(void) memcpy(&prev, &vscan_stats, sizeof (vs_stats_t));
248 	(void) memset(&vscan_stats.vss_eng, 0, sizeof (vscan_stats.vss_eng));
249 
250 	for (i = 0; i < VS_SE_MAX; i++) {
251 		engid = config->va_se[i].vep_engid;
252 		if (*engid == 0)
253 			break;
254 
255 		(void) strlcpy(vscan_stats.vss_eng[i].vss_engid, engid,
256 		    VS_SE_NAME_LEN);
257 
258 		/* find previous error count for engid */
259 		for (j = 0; j < VS_SE_MAX; j++) {
260 			previd = prev.vss_eng[j].vss_engid;
261 			if (strcmp(previd, engid) == 0) {
262 				vscan_stats.vss_eng[i].vss_errors =
263 				    prev.vss_eng[j].vss_errors;
264 				break;
265 			}
266 		}
267 	}
268 
269 	(void) pthread_mutex_unlock(&vs_stats_mutex);
270 }
271