1911106dfSjm /*
2911106dfSjm  * CDDL HEADER START
3911106dfSjm  *
4911106dfSjm  * The contents of this file are subject to the terms of the
5911106dfSjm  * Common Development and Distribution License (the "License").
6911106dfSjm  * You may not use this file except in compliance with the License.
7911106dfSjm  *
8911106dfSjm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9911106dfSjm  * or http://www.opensolaris.org/os/licensing.
10911106dfSjm  * See the License for the specific language governing permissions
11911106dfSjm  * and limitations under the License.
12911106dfSjm  *
13911106dfSjm  * When distributing Covered Code, include this CDDL HEADER in each
14911106dfSjm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15911106dfSjm  * If applicable, add the following below this CDDL HEADER, with the
16911106dfSjm  * fields enclosed by brackets "[]" replaced with your own identifying
17911106dfSjm  * information: Portions Copyright [yyyy] [name of copyright owner]
18911106dfSjm  *
19911106dfSjm  * CDDL HEADER END
20911106dfSjm  */
21911106dfSjm /*
22*96a62adaSjoyce mcintosh  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23911106dfSjm  * Use is subject to license terms.
24911106dfSjm  */
25911106dfSjm 
26911106dfSjm 
27911106dfSjm #include <stdio.h>
28911106dfSjm #include <strings.h>
29911106dfSjm #include <limits.h>
30911106dfSjm #include <stdlib.h>
31911106dfSjm #include <stdarg.h>
32911106dfSjm #include <errno.h>
33911106dfSjm #include <ctype.h>
34911106dfSjm #include <arpa/inet.h>
35911106dfSjm #include <unistd.h>
36911106dfSjm #include <sys/types.h>
37911106dfSjm #include <sys/stat.h>
38911106dfSjm #include <fcntl.h>
39911106dfSjm #include <libintl.h>
40*96a62adaSjoyce mcintosh #include <locale.h>
41911106dfSjm #include <libvscan.h>
42911106dfSjm 
43*96a62adaSjoyce mcintosh #if !defined(TEXT_DOMAIN)
44*96a62adaSjoyce mcintosh #define	TEXT_DOMAIN "SYS_TEST"
45*96a62adaSjoyce mcintosh #endif
46*96a62adaSjoyce mcintosh 
47911106dfSjm 
48911106dfSjm /* Property Names */
49911106dfSjm #define	VS_ADM_MAXSIZE		"max-size"
50911106dfSjm #define	VS_ADM_MAXSIZE_ACTION	"max-size-action"
51911106dfSjm #define	VS_ADM_TYPES		"types"
52911106dfSjm 
53911106dfSjm /* Scan Engine Property Names */
54911106dfSjm #define	VS_ADM_SE_ENABLE	"enable"
55911106dfSjm #define	VS_ADM_SE_HOST		"host"
56911106dfSjm #define	VS_ADM_SE_PORT		"port"
57911106dfSjm #define	VS_ADM_SE_MAXCONN	"max-connection"
58911106dfSjm 
59911106dfSjm /* Property Values */
60911106dfSjm #define	VS_ADM_ON		"on"
61911106dfSjm #define	VS_ADM_OFF		"off"
62911106dfSjm #define	VS_ADM_ALLOW		"allow"
63911106dfSjm #define	VS_ADM_DENY		"deny"
64911106dfSjm 
65911106dfSjm 
66911106dfSjm /*
67911106dfSjm  * Print buffer length: used for sizing buffers that are filled with
68911106dfSjm  * user-readable strings for property values. Define a number that
69911106dfSjm  * accounts for some pre-value information, and won't (likely)
70911106dfSjm  * wrap an 80-column display
71911106dfSjm  */
72911106dfSjm #define	VS_ADM_PRINT_BUF_LEN	4096
73911106dfSjm 
74911106dfSjm /* Program exit codes */
75911106dfSjm #define	VS_ADM_EXIT_SUCCESS	0
76911106dfSjm #define	VS_ADM_EXIT_ERROR	1
77911106dfSjm #define	VS_ADM_EXIT_USAGE	2
78911106dfSjm 
79911106dfSjm 
80911106dfSjm /*
81911106dfSjm  * vscanadm property definition. Maps the property ids to a
82911106dfSjm  * property name, and includes functions to convert to and from
83911106dfSjm  * input strings and native data.
84911106dfSjm  */
85911106dfSjm typedef struct vs_adm_property {
86911106dfSjm 	const char *vap_name;
87911106dfSjm 	uint64_t vap_id;
88911106dfSjm 	int (*vap_parse)(const char *, void *);
89911106dfSjm 	int (*vap_unparse)(const void *, char *, size_t);
90911106dfSjm } vs_adm_property_t;
91911106dfSjm 
92911106dfSjm 
93911106dfSjm /* usage/help information for subcommnds */
94911106dfSjm #define	VS_ADM_HELP_GET		("[-p property]...\n" \
95911106dfSjm 	"\tdisplay vscan properties")
96911106dfSjm #define	VS_ADM_HELP_SET		("-p property=value [-p property=value]...\n" \
97911106dfSjm 	"\tset values of vscan properties")
98911106dfSjm #define	VS_ADM_HELP_GET_ENG	("[-p property] [engine_id]\n" \
99911106dfSjm 	"\tdisplay values of scan engine properties")
100911106dfSjm #define	VS_ADM_HELP_ADD_ENG	("[-p property=value]... engine_id\n" \
101911106dfSjm 	"\tadd scan engine")
102911106dfSjm #define	VS_ADM_HELP_SET_ENG	("-p property=value [-p property=value]" \
103911106dfSjm 	"... engine_id\n\tset values of scan engine properties")
104911106dfSjm #define	VS_ADM_HELP_REM_ENG	("engine_id\n" \
105911106dfSjm 	"\tremove scan engine")
106911106dfSjm #define	VS_ADM_HELP_SHOW	("\n\tdisplay the values of all vscan " \
107911106dfSjm 	"service and scan engine properties")
108911106dfSjm #define	VS_ADM_HELP_STATS	("[-z]\n\tdisplay vscan service statistics")
109911106dfSjm #define	VS_ADM_HELP_IMPORT	("-p property filename\n" \
110911106dfSjm 	"\timport property from file")
111911106dfSjm #define	VS_ADM_HELP_EXPORT	("-p property filename\n" \
112911106dfSjm 	"\texport property to file")
113911106dfSjm #define	VS_ADM_HELP_VALIDATE	("-p property filename\n" \
114911106dfSjm 	"\tvalidate property in file")
115911106dfSjm 
116911106dfSjm 
117911106dfSjm /*
118911106dfSjm  * vscanadm command structure. Encapsulates the vscanadm
119911106dfSjm  * subcommand name, pointer to the subcommand implementation
120911106dfSjm  * function, and a help id to get usage/help information.
121911106dfSjm  */
122911106dfSjm typedef struct vs_adm_cmd {
123911106dfSjm 	int (*vac_func)(int, char *[]);
124911106dfSjm 	const char *vac_name;
125911106dfSjm 	char *vac_helpid;
126911106dfSjm }
127911106dfSjm vs_adm_cmd_t;
128911106dfSjm 
129911106dfSjm 
130911106dfSjm /* Subcommand implementation functions */
131911106dfSjm static int vs_adm_set(int, char **);
132911106dfSjm static int vs_adm_get(int, char **);
133911106dfSjm static int vs_adm_set_engine(int, char **);
134911106dfSjm static int vs_adm_get_engine(int, char **);
135911106dfSjm static int vs_adm_rem_engine(int, char **);
136911106dfSjm static int vs_adm_show(int, char **);
137911106dfSjm static int vs_adm_stats(int, char **);
138911106dfSjm static int vs_adm_import(int, char **);
139911106dfSjm static int vs_adm_export(int, char **);
140911106dfSjm static int vs_adm_validate(int, char **);
141911106dfSjm 
142911106dfSjm 
143911106dfSjm /*
144911106dfSjm  * Parse routines to transform libvscan API data into user-readable strings
145911106dfSjm  */
146911106dfSjm static int vs_adm_parse_maxsize(const char *, void *);
147911106dfSjm static int vs_adm_parse_maxsize_action(const char *, void *);
148911106dfSjm static int vs_adm_parse_types(const char *, void *);
149911106dfSjm static int vs_adm_parse_enable(const char *, void *);
150911106dfSjm static int vs_adm_parse_host(const char *, void *);
151911106dfSjm static int vs_adm_parse_port(const char *, void *);
152911106dfSjm static int vs_adm_parse_maxconn(const char *, void *);
153911106dfSjm 
154911106dfSjm 
155911106dfSjm /*
156911106dfSjm  * Unparse routines to transform strings from the user input into
157911106dfSjm  * API native data.
158911106dfSjm  *
159911106dfSjm  * While some value validation is performed in the course of unparsing
160911106dfSjm  * string data, complete value validation is left to libvscan.
161911106dfSjm  * Values that are in unacceptable form, out of range, or otherwise
162911106dfSjm  * violate rules for a given property will be rejected
163911106dfSjm  */
164911106dfSjm static int vs_adm_unparse_maxsize(const void *, char *, size_t);
165911106dfSjm static int vs_adm_unparse_maxsize_action(const void *, char *, size_t);
166911106dfSjm static int vs_adm_unparse_types(const void *, char *, size_t);
167911106dfSjm static int vs_adm_unparse_enable(const void *, char *, size_t);
168911106dfSjm static int vs_adm_unparse_host(const void *, char *, size_t);
169911106dfSjm static int vs_adm_unparse_port(const void *, char *, size_t);
170911106dfSjm static int vs_adm_unparse_maxconn(const void *, char *, size_t);
171911106dfSjm 
172911106dfSjm 
173911106dfSjm /*
174911106dfSjm  * The properties table includes a vscanadm property entry, specifying
175911106dfSjm  * the property nane, property id, parse amd inparse methods,
176911106dfSjm  * for each vscanadm property.
177911106dfSjm  */
178911106dfSjm static const vs_adm_property_t vs_adm_props_all[] = {
179911106dfSjm 	{ VS_ADM_MAXSIZE, VS_PROPID_MAXSIZE,
180911106dfSjm 		vs_adm_parse_maxsize, vs_adm_unparse_maxsize },
181911106dfSjm 	{ VS_ADM_MAXSIZE_ACTION, VS_PROPID_MAXSIZE_ACTION,
182911106dfSjm 		vs_adm_parse_maxsize_action, vs_adm_unparse_maxsize_action },
183911106dfSjm 	{ VS_ADM_TYPES, VS_PROPID_TYPES,
184911106dfSjm 		vs_adm_parse_types, vs_adm_unparse_types },
185911106dfSjm 	{ VS_ADM_SE_ENABLE, VS_PROPID_SE_ENABLE,
186911106dfSjm 		vs_adm_parse_enable, vs_adm_unparse_enable },
187911106dfSjm 	{ VS_ADM_SE_HOST, VS_PROPID_SE_HOST,
188911106dfSjm 		vs_adm_parse_host, vs_adm_unparse_host },
189911106dfSjm 	{ VS_ADM_SE_PORT, VS_PROPID_SE_PORT,
190911106dfSjm 		vs_adm_parse_port, vs_adm_unparse_port },
191911106dfSjm 	{ VS_ADM_SE_MAXCONN, VS_PROPID_SE_MAXCONN,
192911106dfSjm 		vs_adm_parse_maxconn, vs_adm_unparse_maxconn },
193911106dfSjm 	{ NULL, 0, NULL, NULL }
194911106dfSjm };
195911106dfSjm 
196911106dfSjm 
197911106dfSjm /*
198911106dfSjm  * The subcommand table.  Used to find the subcommand specified
199911106dfSjm  * by the user and dispatch the processing for the subcommand.
200911106dfSjm  * Also used to display usage information for each subcommand.
201911106dfSjm  */
202911106dfSjm static const vs_adm_cmd_t vs_adm_cmds[] =
203911106dfSjm {
204911106dfSjm 	{ vs_adm_get, "get", VS_ADM_HELP_GET },
205911106dfSjm 	{ vs_adm_set, "set", VS_ADM_HELP_SET },
206911106dfSjm 	{ vs_adm_get_engine, "get-engine", VS_ADM_HELP_GET_ENG },
207911106dfSjm 	{ vs_adm_set_engine, "set-engine", VS_ADM_HELP_SET_ENG },
208911106dfSjm 	{ vs_adm_set_engine, "add-engine", VS_ADM_HELP_ADD_ENG },
209911106dfSjm 	{ vs_adm_rem_engine, "remove-engine", VS_ADM_HELP_REM_ENG },
210911106dfSjm 	{ vs_adm_import, "import", VS_ADM_HELP_IMPORT },
211911106dfSjm 	{ vs_adm_export, "export", VS_ADM_HELP_EXPORT },
212911106dfSjm 	{ vs_adm_validate, "validate", VS_ADM_HELP_VALIDATE },
213911106dfSjm 	{ vs_adm_show, "show", VS_ADM_HELP_SHOW },
214911106dfSjm 	{ vs_adm_stats, "stats", VS_ADM_HELP_STATS },
215911106dfSjm 	{ NULL, NULL, NULL }
216911106dfSjm };
217911106dfSjm 
218911106dfSjm 
219911106dfSjm static const char *vs_adm_cmd;
220911106dfSjm static const char *vs_adm_subcmd;
221911106dfSjm 
222911106dfSjm static int vs_adm_usage(FILE *);
223911106dfSjm static int vs_adm_props_from_input(int, char **, vs_props_t *, uint64_t *);
224911106dfSjm static void vs_adm_output_getcmd(uint64_t, const void *);
225911106dfSjm static void vs_adm_output_stats(vs_stats_t *);
226911106dfSjm static const vs_adm_property_t *vs_adm_prop_by_name(const char *);
227911106dfSjm static const vs_adm_property_t *vs_adm_prop_by_id(const uint64_t);
228911106dfSjm static int vs_adm_parse(const vs_adm_property_t *, const char *, void *);
229911106dfSjm static void vs_adm_unparse(const vs_adm_property_t *, const void *,
230911106dfSjm     char *, size_t);
231911106dfSjm 
232911106dfSjm static int vs_adm_file_read(char *, char *, int);
233911106dfSjm static int vs_adm_file_write(char *, char *);
234911106dfSjm static int vs_adm_file_usage(int argc, char **argv);
235911106dfSjm 
236911106dfSjm /*
237911106dfSjm  * main
238911106dfSjm  */
239911106dfSjm int
main(int argc,char ** argv)240911106dfSjm main(int argc, char **argv)
241911106dfSjm {
242911106dfSjm 	const vs_adm_cmd_t *cp;
243911106dfSjm 	const char *p;
244911106dfSjm 	int i, err;
245911106dfSjm 
246*96a62adaSjoyce mcintosh 	(void) setlocale(LC_ALL, "");
247*96a62adaSjoyce mcintosh 	(void) textdomain(TEXT_DOMAIN);
248*96a62adaSjoyce mcintosh 
249911106dfSjm 	/* executable and subcommand names */
250911106dfSjm 	if ((p = strrchr(argv[0], '/')) == NULL)
251911106dfSjm 		vs_adm_cmd = argv[0];
252911106dfSjm 	else
253911106dfSjm 		vs_adm_cmd = p + 1;
254911106dfSjm 
255911106dfSjm 	vs_adm_subcmd = argv[1];
256911106dfSjm 
257911106dfSjm 	/* require at least command and sub-command */
258911106dfSjm 	if (argc < 2)
259911106dfSjm 		return (vs_adm_usage(stdout));
260911106dfSjm 
261911106dfSjm 	/* Check for the "-?" help switch */
262911106dfSjm 	for (i = 1; i < argc; i++) {
263911106dfSjm 		if (strcmp(argv[i], "-?") == 0)
264911106dfSjm 			return (vs_adm_usage(stdout));
265911106dfSjm 	}
266911106dfSjm 
267911106dfSjm 	/* Locate the specified subcommand */
268911106dfSjm 	for (cp = vs_adm_cmds; cp->vac_name != NULL; cp++) {
269911106dfSjm 		if (strcmp(cp->vac_name, vs_adm_subcmd) == 0)
270911106dfSjm 			break;
271911106dfSjm 	}
272911106dfSjm 
273911106dfSjm 	if (cp->vac_name == NULL) {
274911106dfSjm 		(void) fprintf(stderr, "%s: %s -- %s\n",
275911106dfSjm 		    gettext("invalid subcommand"),
276911106dfSjm 		    vs_adm_cmd, vs_adm_subcmd);
277911106dfSjm 		return (vs_adm_usage(stderr));
278911106dfSjm 	}
279911106dfSjm 
280911106dfSjm 	/* invoke sub-command handler */
281911106dfSjm 	err = cp->vac_func(argc, argv);
282911106dfSjm 
283911106dfSjm 	return (err == VS_ADM_EXIT_USAGE ? vs_adm_usage(stderr) : err);
284911106dfSjm }
285911106dfSjm 
286911106dfSjm 
287911106dfSjm /*
288911106dfSjm  * vs_adm_usage
289911106dfSjm  */
290911106dfSjm static int
vs_adm_usage(FILE * fp)291911106dfSjm vs_adm_usage(FILE *fp)
292911106dfSjm {
293911106dfSjm 	const vs_adm_cmd_t *cp;
294911106dfSjm 
295911106dfSjm 	for (cp = vs_adm_cmds; cp->vac_name != NULL; cp++) {
296911106dfSjm 		(void) fprintf(fp, "%s %s", vs_adm_cmd, cp->vac_name);
297911106dfSjm 		if (cp->vac_helpid != NULL)
298911106dfSjm 			(void) fprintf(fp, " %s\n", cp->vac_helpid);
299911106dfSjm 	}
300911106dfSjm 
301911106dfSjm 	return (VS_ADM_EXIT_USAGE);
302911106dfSjm }
303911106dfSjm 
304911106dfSjm 
305911106dfSjm /*
306911106dfSjm  * vs_adm_get
307911106dfSjm  *
308911106dfSjm  * Gets and displays general vscan service configuration properties.
309911106dfSjm  */
310911106dfSjm static int
vs_adm_get(int argc,char ** argv)311911106dfSjm vs_adm_get(int argc, char **argv)
312911106dfSjm {
313911106dfSjm 	uint64_t propids;
314911106dfSjm 	int i, rc;
315911106dfSjm 	vs_props_t vp;
316911106dfSjm 	const vs_adm_property_t *vap;
317911106dfSjm 
318911106dfSjm 	(void) memset(&vp, 0, sizeof (vp));
319911106dfSjm 
320911106dfSjm 	if (argc <= 2) {
321911106dfSjm 		propids = VS_PROPID_GEN_ALL;
322911106dfSjm 	} else {
323911106dfSjm 		propids = 0LL;
324911106dfSjm 		for (i = 2; i < argc; i++) {
325911106dfSjm 			/* the "-p" specifier is optional */
326911106dfSjm 			if (strcmp(argv[i], "-p") == 0) {
327911106dfSjm 				if (++i >= argc)
328911106dfSjm 					return (VS_ADM_EXIT_USAGE);
329911106dfSjm 			}
330911106dfSjm 
331911106dfSjm 			if ((vap = vs_adm_prop_by_name(argv[i])) == NULL) {
332911106dfSjm 				(void) fprintf(stderr, "%s '%s'\n",
333911106dfSjm 				    gettext("invalid property"), argv[i]);
334911106dfSjm 				return (VS_ADM_EXIT_ERROR);
335911106dfSjm 			}
336911106dfSjm 
337911106dfSjm 			propids |= vap->vap_id;
338911106dfSjm 		}
339911106dfSjm 	}
340911106dfSjm 
341911106dfSjm 	rc = vs_props_get(&vp, propids);
342911106dfSjm 	if (rc != VS_ERR_NONE) {
343911106dfSjm 		(void) fprintf(stderr, "%s\n", vs_strerror(rc));
344911106dfSjm 		return (VS_ADM_EXIT_ERROR);
345911106dfSjm 	}
346911106dfSjm 
347911106dfSjm 	vs_adm_output_getcmd(propids, &vp);
348911106dfSjm 
349911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
350911106dfSjm }
351911106dfSjm 
352911106dfSjm 
353911106dfSjm /*
354911106dfSjm  * vs_adm_set
355911106dfSjm  *
356911106dfSjm  * Sets values for general vscan service configuration properties
357911106dfSjm  *
358911106dfSjm  * Calls a common function used by the set, add, and remove
359911106dfSjm  * subcommands to modify general property values.
360911106dfSjm  */
361911106dfSjm static int
vs_adm_set(int argc,char ** argv)362911106dfSjm vs_adm_set(int argc, char **argv)
363911106dfSjm {
364911106dfSjm 	vs_props_t vp;
365911106dfSjm 	uint64_t propids;
366911106dfSjm 	int rc;
367911106dfSjm 
368911106dfSjm 	if (argc < 3)
369911106dfSjm 		return (VS_ADM_EXIT_USAGE);
370911106dfSjm 
371911106dfSjm 	rc = vs_adm_props_from_input(argc, argv, &vp, &propids);
372911106dfSjm 	if (rc != VS_ADM_EXIT_SUCCESS)
373911106dfSjm 		return (rc);
374911106dfSjm 
375911106dfSjm 	rc = vs_props_set(&vp, propids);
376911106dfSjm 	if (rc != VS_ERR_NONE) {
377911106dfSjm 		(void) fprintf(stderr, "%s\n", vs_strerror(rc));
378911106dfSjm 		return (VS_ADM_EXIT_ERROR);
379911106dfSjm 	}
380911106dfSjm 
381911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
382911106dfSjm }
383911106dfSjm 
384911106dfSjm 
385911106dfSjm /*
386911106dfSjm  * vs_adm_get_engine
387911106dfSjm  *
388911106dfSjm  * Gets and displays scan engine configuration properties for
389911106dfSjm  * one or more scan engines.
390911106dfSjm  */
391911106dfSjm static int
vs_adm_get_engine(int argc,char ** argv)392911106dfSjm vs_adm_get_engine(int argc, char **argv)
393911106dfSjm {
394911106dfSjm 	int i, rc;
395911106dfSjm 	uint64_t propids;
396911106dfSjm 	char *engid = NULL;
397911106dfSjm 	const vs_adm_property_t *vap;
398911106dfSjm 	vs_props_all_t va;
399911106dfSjm 
400911106dfSjm 	propids = 0LL;
401911106dfSjm 	for (i = 2; i < argc; i++) {
402911106dfSjm 		/* if not preceded by -p, must be engine id and must be last */
403911106dfSjm 		if (strcmp(argv[i], "-p") != 0) {
404911106dfSjm 			if (i != (argc - 1))
405911106dfSjm 				return (VS_ADM_EXIT_USAGE);
406911106dfSjm 
407911106dfSjm 			engid = argv[i];
408911106dfSjm 			if (strlen(engid) > VS_SE_NAME_LEN) {
409911106dfSjm 				(void) fprintf(stderr, "%s\n",
410911106dfSjm 				    gettext("invalid scan engine"));
411911106dfSjm 				return (VS_ADM_EXIT_ERROR);
412911106dfSjm 			}
413911106dfSjm 		} else {
414911106dfSjm 			/* property should follow the -p */
415911106dfSjm 			if (++i >= argc)
416911106dfSjm 				return (VS_ADM_EXIT_USAGE);
417911106dfSjm 
418911106dfSjm 			if ((vap = vs_adm_prop_by_name(argv[i])) == NULL) {
419911106dfSjm 				(void) fprintf(stderr, "%s '%s'\n",
420911106dfSjm 				    gettext("invalid property"), argv[i]);
421911106dfSjm 				return (VS_ADM_EXIT_ERROR);
422911106dfSjm 			}
423911106dfSjm 
424911106dfSjm 			propids |= vap->vap_id;
425911106dfSjm 		}
426911106dfSjm 	}
427911106dfSjm 
428911106dfSjm 	if (propids == 0LL)
429911106dfSjm 		propids = VS_PROPID_SE_ALL;
430911106dfSjm 
431911106dfSjm 	/* get properties for specified engine */
432911106dfSjm 	if (engid) {
433911106dfSjm 		rc = vs_props_se_get(engid, &va.va_se[0], propids);
434911106dfSjm 		if (rc != VS_ERR_NONE) {
435911106dfSjm 			(void) fprintf(stderr, "%s\n", vs_strerror(rc));
436911106dfSjm 			return (VS_ADM_EXIT_ERROR);
437911106dfSjm 		}
438911106dfSjm 		vs_adm_output_getcmd(propids, &va.va_se[0]);
439911106dfSjm 		return (VS_ADM_EXIT_SUCCESS);
440911106dfSjm 	}
441911106dfSjm 
442911106dfSjm 	/* get properties for all engines */
443911106dfSjm 	if ((rc = vs_props_get_all(&va)) != VS_ERR_NONE) {
444911106dfSjm 		(void) fprintf(stderr, "%s\n", vs_strerror(rc));
445911106dfSjm 		return (VS_ADM_EXIT_ERROR);
446911106dfSjm 	}
447911106dfSjm 
448911106dfSjm 	for (i = 0; i < VS_SE_MAX; i++) {
449911106dfSjm 		if (*(va.va_se[i].vep_engid) == 0)
450911106dfSjm 			break;
451911106dfSjm 		vs_adm_output_getcmd(propids, &va.va_se[i]);
452911106dfSjm 	}
453911106dfSjm 	if (i == 0) {
454911106dfSjm 		(void) fprintf(stdout, "%s\n",
455911106dfSjm 		    gettext("no scan engines configured"));
456911106dfSjm 	}
457911106dfSjm 
458911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
459911106dfSjm }
460911106dfSjm 
461911106dfSjm 
462911106dfSjm /*
463911106dfSjm  * vs_adm_set_engine
464911106dfSjm  *
465911106dfSjm  * Sets one or more scan engine configuration properties for a
466911106dfSjm  * single scan engine.
467911106dfSjm  */
468911106dfSjm static int
vs_adm_set_engine(int argc,char ** argv)469911106dfSjm vs_adm_set_engine(int argc, char **argv)
470911106dfSjm {
471911106dfSjm 	const vs_adm_property_t *vap;
472911106dfSjm 	vs_props_se_t sep;
473911106dfSjm 	char *val;
474911106dfSjm 	uint64_t propids;
475911106dfSjm 	int i, rc;
476911106dfSjm 	char *engid;
477911106dfSjm 	int add = (strcmp(vs_adm_subcmd, "add-engine") == 0) ? 1 : 0;
478911106dfSjm 
479911106dfSjm 
480911106dfSjm 	if ((argc < 3) || ((!add) && (argc < 4)))
481911106dfSjm 		return (VS_ADM_EXIT_USAGE);
482911106dfSjm 
483911106dfSjm 	/* Get the engine id */
484911106dfSjm 	engid = argv[argc - 1];
485911106dfSjm 	if (strchr(engid, '=') || strcmp(argv[argc - 2], "-p") == 0) {
486911106dfSjm 		return (VS_ADM_EXIT_USAGE);
487911106dfSjm 	}
488911106dfSjm 
489911106dfSjm 	if (strlen(engid) > VS_SE_NAME_LEN) {
490911106dfSjm 		(void) fprintf(stderr, "%s\n",
491911106dfSjm 		    gettext("invalid scan engine"));
492911106dfSjm 		return (VS_ADM_EXIT_ERROR);
493911106dfSjm 	}
494911106dfSjm 
495911106dfSjm 	propids = 0LL;
496911106dfSjm 
497911106dfSjm 	for (i = 2; i < (argc - 1); i++) {
498911106dfSjm 		/* The "-p" is optional */
499911106dfSjm 		if (strcmp(argv[i], "-p") == 0) {
500911106dfSjm 			if (++i >= argc)
501911106dfSjm 				return (VS_ADM_EXIT_USAGE);
502911106dfSjm 		}
503911106dfSjm 
504911106dfSjm 		if ((val = strchr(argv[i], '=')) == NULL)
505911106dfSjm 			return (VS_ADM_EXIT_USAGE);
506911106dfSjm 
507911106dfSjm 		*val = 0;
508911106dfSjm 		val++;
509911106dfSjm 
510911106dfSjm 		/* Find the SE property pointer from the SE property name */
511911106dfSjm 		if ((vap = vs_adm_prop_by_name(argv[i])) == NULL) {
512911106dfSjm 			(void) fprintf(stderr, "%s '%s'\n",
513911106dfSjm 			    gettext("invalid property"), argv[i]);
514911106dfSjm 			return (VS_ADM_EXIT_ERROR);
515911106dfSjm 		}
516911106dfSjm 
517911106dfSjm 		propids |= vap->vap_id;
518911106dfSjm 
519911106dfSjm 		if ((vs_adm_parse(vap, val, &sep)) != 0) {
520911106dfSjm 			(void) fprintf(stderr, "%s '%s'\n",
521911106dfSjm 			    gettext("invalid property value"), val);
522911106dfSjm 			return (VS_ADM_EXIT_ERROR);
523911106dfSjm 		}
524911106dfSjm 	}
525911106dfSjm 
526911106dfSjm 	if (add)
527911106dfSjm 		rc = vs_props_se_create(engid, &sep, propids);
528911106dfSjm 	else
529911106dfSjm 		rc = vs_props_se_set(engid, &sep, propids);
530911106dfSjm 
531911106dfSjm 	if (rc != VS_ERR_NONE) {
532911106dfSjm 		(void) fprintf(stderr, "%s\n", vs_strerror(rc));
533911106dfSjm 		return (VS_ADM_EXIT_ERROR);
534911106dfSjm 	}
535911106dfSjm 
536911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
537911106dfSjm }
538911106dfSjm 
539911106dfSjm 
540911106dfSjm /*
541911106dfSjm  * vs_adm_rem_engine
542911106dfSjm  */
543911106dfSjm /* ARGSUSED */
544911106dfSjm static int
vs_adm_rem_engine(int argc,char ** argv)545911106dfSjm vs_adm_rem_engine(int argc, char **argv)
546911106dfSjm {
547911106dfSjm 	int rc;
548911106dfSjm 	char *engid;
549911106dfSjm 
550911106dfSjm 	if (argc != 3)
551911106dfSjm 		return (VS_ADM_EXIT_USAGE);
552911106dfSjm 
553911106dfSjm 	engid = argv[2];
554911106dfSjm 
555911106dfSjm 	if (strlen(engid) > VS_SE_NAME_LEN) {
556911106dfSjm 		(void) fprintf(stderr, "%s\n",
557911106dfSjm 		    gettext("invalid scan engine"));
558911106dfSjm 		return (VS_ADM_EXIT_ERROR);
559911106dfSjm 	}
560911106dfSjm 
561911106dfSjm 	if ((rc = vs_props_se_delete(engid)) != VS_ERR_NONE) {
562911106dfSjm 		(void) fprintf(stderr, "%s\n", vs_strerror(rc));
563911106dfSjm 		return (rc);
564911106dfSjm 	}
565911106dfSjm 
566911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
567911106dfSjm }
568911106dfSjm 
569911106dfSjm 
570911106dfSjm /*
571911106dfSjm  * vs_adm_import
572911106dfSjm  */
573911106dfSjm static int
vs_adm_import(int argc,char ** argv)574911106dfSjm vs_adm_import(int argc, char **argv)
575911106dfSjm {
576911106dfSjm 	int rc;
577911106dfSjm 	vs_props_t vp;
578911106dfSjm 	uint64_t propids;
579911106dfSjm 	char *filename;
580911106dfSjm 
581911106dfSjm 	if ((rc = vs_adm_file_usage(argc, argv)) != VS_ADM_EXIT_SUCCESS)
582911106dfSjm 		return (rc);
583911106dfSjm 
584911106dfSjm 	filename = argv[argc - 1];
585911106dfSjm 	rc = vs_adm_file_read(filename, vp.vp_types, sizeof (vp.vp_types));
586911106dfSjm 	if (rc != VS_ADM_EXIT_SUCCESS)
587911106dfSjm 		return (rc);
588911106dfSjm 
589911106dfSjm 	propids = VS_PROPID_TYPES;
590911106dfSjm 	rc = vs_props_set(&vp, propids);
591911106dfSjm 	if (rc != VS_ERR_NONE) {
592911106dfSjm 		(void) fprintf(stderr, "%s\n", vs_strerror(rc));
593911106dfSjm 		return (VS_ADM_EXIT_ERROR);
594911106dfSjm 	}
595911106dfSjm 
596911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
597911106dfSjm }
598911106dfSjm 
599911106dfSjm 
600911106dfSjm /*
601911106dfSjm  * vs_adm_validate
602911106dfSjm  */
603911106dfSjm static int
vs_adm_validate(int argc,char ** argv)604911106dfSjm vs_adm_validate(int argc, char **argv)
605911106dfSjm {
606911106dfSjm 	int rc;
607911106dfSjm 	vs_props_t vp;
608911106dfSjm 	char *filename;
609911106dfSjm 
610911106dfSjm 	if ((rc = vs_adm_file_usage(argc, argv)) != VS_ADM_EXIT_SUCCESS)
611911106dfSjm 		return (rc);
612911106dfSjm 
613911106dfSjm 	filename = argv[argc - 1];
614911106dfSjm 	rc = vs_adm_file_read(filename, vp.vp_types, sizeof (vp.vp_types));
615911106dfSjm 	if (rc != VS_ADM_EXIT_SUCCESS)
616911106dfSjm 		return (rc);
617911106dfSjm 
618911106dfSjm 	if (vs_props_validate(&vp, VS_PROPID_TYPES) != VS_ERR_NONE) {
619911106dfSjm 		(void) fprintf(stderr, "%s: %s\n", filename, vs_strerror(rc));
620911106dfSjm 		return (VS_ADM_EXIT_ERROR);
621911106dfSjm 	}
622911106dfSjm 
623911106dfSjm 	(void) fprintf(stdout, "%s: valid\n", filename);
624911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
625911106dfSjm }
626911106dfSjm 
627911106dfSjm 
628911106dfSjm /*
629911106dfSjm  * vs_adm_export
630911106dfSjm  */
631911106dfSjm static int
vs_adm_export(int argc,char ** argv)632911106dfSjm vs_adm_export(int argc, char **argv)
633911106dfSjm {
634911106dfSjm 	int rc;
635911106dfSjm 	vs_props_t vp;
636911106dfSjm 	uint64_t propids;
637911106dfSjm 	char *filename;
638911106dfSjm 
639911106dfSjm 	if ((rc = vs_adm_file_usage(argc, argv)) != VS_ADM_EXIT_SUCCESS)
640911106dfSjm 		return (rc);
641911106dfSjm 
642911106dfSjm 	filename = argv[argc - 1];
643911106dfSjm 	(void) memset(&vp, 0, sizeof (vs_props_t));
644911106dfSjm 	propids = VS_PROPID_TYPES;
645911106dfSjm 	if ((rc = vs_props_get(&vp, propids)) != VS_ERR_NONE) {
646911106dfSjm 		(void) fprintf(stderr, "%s: %s\n", filename, vs_strerror(rc));
647911106dfSjm 		return (VS_ADM_EXIT_ERROR);
648911106dfSjm 	}
649911106dfSjm 
650911106dfSjm 	rc = vs_adm_file_write(filename, vp.vp_types);
651911106dfSjm 	if (rc != VS_ADM_EXIT_SUCCESS)
652911106dfSjm 		return (rc);
653911106dfSjm 
654911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
655911106dfSjm }
656911106dfSjm 
657911106dfSjm 
658911106dfSjm /*
659911106dfSjm  * vs_adm_file_usage
660911106dfSjm  *
661911106dfSjm  * import, export and validate - VS_PROPID_TYPES only
662911106dfSjm  */
663911106dfSjm static int
vs_adm_file_usage(int argc,char ** argv)664911106dfSjm vs_adm_file_usage(int argc, char **argv)
665911106dfSjm {
666911106dfSjm 	const vs_adm_property_t *vap;
667911106dfSjm 	char *prop;
668911106dfSjm 
669911106dfSjm 	if (argc < 4)
670911106dfSjm 		return (VS_ADM_EXIT_USAGE);
671911106dfSjm 
672911106dfSjm 	/* -p optional */
673911106dfSjm 	if (strcmp(argv[2], "-p") == 0) {
674911106dfSjm 		if (argc != 5)
675911106dfSjm 			return (VS_ADM_EXIT_USAGE);
676911106dfSjm 	} else if (argc != 4)
677911106dfSjm 		return (VS_ADM_EXIT_USAGE);
678911106dfSjm 
679911106dfSjm 	/* only VS_PROPID_TYPES supported */
680911106dfSjm 	prop = argv[argc - 2];
681911106dfSjm 	vap = vs_adm_prop_by_name(prop);
682911106dfSjm 	if ((vap == NULL) || (vap->vap_id != VS_PROPID_TYPES)) {
683911106dfSjm 		(void) fprintf(stderr, "%s '%s'\n",
684911106dfSjm 		    gettext("invalid property"), prop);
685911106dfSjm 		return (VS_ADM_EXIT_USAGE);
686911106dfSjm 	}
687911106dfSjm 
688911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
689911106dfSjm }
690911106dfSjm 
691911106dfSjm 
692911106dfSjm /*
693911106dfSjm  * vs_adm_file_read
694911106dfSjm  */
695911106dfSjm static int
vs_adm_file_read(char * filename,char * buf,int len)696911106dfSjm vs_adm_file_read(char *filename, char *buf, int len)
697911106dfSjm {
698911106dfSjm 	FILE *fp;
699911106dfSjm 
700911106dfSjm 	if ((fp = fopen(filename, "r")) == NULL) {
701911106dfSjm 		(void) fprintf(stderr, "%s: %s\n", filename,
702911106dfSjm 		    vs_strerror(VS_ERR_SYS));
703911106dfSjm 		return (VS_ADM_EXIT_ERROR);
704911106dfSjm 	}
705911106dfSjm 
706911106dfSjm 	(void) memset(buf, 0, len);
707911106dfSjm 	if (fgets(buf, len, fp) == NULL) {
708911106dfSjm 		(void) fprintf(stderr, "%s: %s\n", filename,
709911106dfSjm 		    gettext("invalid property value"));
710911106dfSjm 		(void) fclose(fp);
711911106dfSjm 		return (VS_ADM_EXIT_ERROR);
712911106dfSjm 	}
713911106dfSjm 
714911106dfSjm 	(void) fclose(fp);
715911106dfSjm 
716911106dfSjm 	/* remove newline */
717911106dfSjm 	if (buf[strlen(buf) - 1] == '\n')
718911106dfSjm 		buf[strlen(buf) - 1] = '\0';
719911106dfSjm 
720911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
721911106dfSjm }
722911106dfSjm 
723911106dfSjm 
724911106dfSjm /*
725911106dfSjm  * vs_adm_file_write
726911106dfSjm  */
727911106dfSjm static int
vs_adm_file_write(char * filename,char * buf)728911106dfSjm vs_adm_file_write(char *filename, char *buf)
729911106dfSjm {
730911106dfSjm 	FILE *fp;
731911106dfSjm 	int bytes;
732911106dfSjm 
733911106dfSjm 	if ((fp = fopen(filename, "w")) == NULL) {
734911106dfSjm 		(void) fprintf(stderr, "%s: %s\n", filename,
735911106dfSjm 		    vs_strerror(VS_ERR_SYS));
736911106dfSjm 		return (VS_ADM_EXIT_ERROR);
737911106dfSjm 	}
738911106dfSjm 
739911106dfSjm 	bytes = fprintf(fp, "%s\n", buf);
740911106dfSjm 	if ((bytes < 0) || (bytes != strlen(buf) + 1)) {
741911106dfSjm 		(void) fprintf(stderr, "%s: %s\n", filename,
742911106dfSjm 		    vs_strerror(VS_ERR_SYS));
743911106dfSjm 		(void) fclose(fp);
744911106dfSjm 		return (VS_ADM_EXIT_ERROR);
745911106dfSjm 	}
746911106dfSjm 
747911106dfSjm 	(void) fclose(fp);
748911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
749911106dfSjm }
750911106dfSjm 
751911106dfSjm 
752911106dfSjm /*
753911106dfSjm  * vs_adm_show
754911106dfSjm  *
755911106dfSjm  * Gets and displays all general properties and all scan engine
756911106dfSjm  * properties.
757911106dfSjm  */
758911106dfSjm /* ARGSUSED */
759911106dfSjm static int
vs_adm_show(int argc,char ** argv)760911106dfSjm vs_adm_show(int argc, char **argv)
761911106dfSjm {
762911106dfSjm 	if (argc > 2)
763911106dfSjm 		return (VS_ADM_EXIT_USAGE);
764911106dfSjm 
765911106dfSjm 	(void) vs_adm_get(argc, argv);
766911106dfSjm 	(void) vs_adm_get_engine(argc, argv);
767911106dfSjm 
768911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
769911106dfSjm }
770911106dfSjm 
771911106dfSjm 
772911106dfSjm /*
773911106dfSjm  * vs_adm_stats
774911106dfSjm  *
775911106dfSjm  * Gets and displays vscan service statistics.
776911106dfSjm  */
777911106dfSjm /* ARGSUSED */
778911106dfSjm static int
vs_adm_stats(int argc,char ** argv)779911106dfSjm vs_adm_stats(int argc, char **argv)
780911106dfSjm {
781911106dfSjm 	int rc;
782911106dfSjm 	vs_stats_t stats;
783911106dfSjm 
784911106dfSjm 	/* get statistics */
785911106dfSjm 	if (argc == 2) {
786911106dfSjm 		if ((rc = vs_statistics(&stats)) == VS_ERR_NONE) {
787911106dfSjm 			vs_adm_output_stats(&stats);
788911106dfSjm 			return (VS_ADM_EXIT_SUCCESS);
789911106dfSjm 		} else {
790911106dfSjm 			(void) fprintf(stdout, "%s\n", vs_strerror(rc));
791911106dfSjm 			return (VS_ADM_EXIT_ERROR);
792911106dfSjm 		}
793911106dfSjm 	}
794911106dfSjm 
795911106dfSjm 	/* reset statistics */
796911106dfSjm 	if (argc == 3 && strcmp(argv[2], "-z") == 0) {
797911106dfSjm 		if ((rc = vs_statistics_reset()) == VS_ERR_NONE) {
798911106dfSjm 			return (VS_ADM_EXIT_SUCCESS);
799911106dfSjm 		} else {
800911106dfSjm 			(void) fprintf(stdout, "%s\n", vs_strerror(rc));
801911106dfSjm 			return (VS_ADM_EXIT_ERROR);
802911106dfSjm 		}
803911106dfSjm 	}
804911106dfSjm 
805911106dfSjm 	/* usage error */
806911106dfSjm 	return (vs_adm_usage(stdout));
807911106dfSjm }
808911106dfSjm 
809911106dfSjm 
810911106dfSjm /*
811911106dfSjm  * vs_adm_output_stats
812911106dfSjm  */
813911106dfSjm static void
vs_adm_output_stats(vs_stats_t * stats)814911106dfSjm vs_adm_output_stats(vs_stats_t *stats)
815911106dfSjm {
816911106dfSjm 	int i;
817911106dfSjm 	char *engid;
818911106dfSjm 
819911106dfSjm 	if (stats == NULL)
820911106dfSjm 		return;
821911106dfSjm 
822911106dfSjm 	(void) fprintf(stdout, "scanned=%lld\n", stats->vss_scanned);
823911106dfSjm 	(void) fprintf(stdout, "infected=%lld\n", stats->vss_infected);
824911106dfSjm 	if (stats->vss_cleaned > 0)
825911106dfSjm 		(void) printf("cleaned=%lld\n", stats->vss_cleaned);
826911106dfSjm 	(void) fprintf(stdout, "failed=%lld\n", stats->vss_failed);
827911106dfSjm 
828911106dfSjm 	for (i = 0; i < VS_SE_MAX; i++) {
829911106dfSjm 		engid = stats->vss_eng[i].vss_engid;
830911106dfSjm 		if (*engid == 0)
831911106dfSjm 			break;
832911106dfSjm 		(void) fprintf(stdout, "%s:errors=%lld\n", engid,
833911106dfSjm 		    stats->vss_eng[i].vss_errors);
834911106dfSjm 	}
835911106dfSjm }
836911106dfSjm 
837911106dfSjm 
838911106dfSjm /*
839911106dfSjm  * vs_adm_props_from_input
840911106dfSjm  */
841911106dfSjm static int
vs_adm_props_from_input(int argc,char ** argv,vs_props_t * vsprops,uint64_t * propids)842911106dfSjm vs_adm_props_from_input(int argc, char **argv, vs_props_t *vsprops,
843911106dfSjm     uint64_t *propids)
844911106dfSjm {
845911106dfSjm 	const vs_adm_property_t *vap;
846911106dfSjm 	char *val;
847911106dfSjm 	int i;
848911106dfSjm 
849911106dfSjm 	(void) memset(vsprops, 0, sizeof (vs_props_t));
850911106dfSjm 
851911106dfSjm 	*propids = 0LL;
852911106dfSjm 	for (i = 2; i < argc; i++) {
853911106dfSjm 		/* The "-p" is optional */
854911106dfSjm 		if (strcmp(argv[i], "-p") == 0) {
855911106dfSjm 			if (++i >= argc)
856911106dfSjm 				return (VS_ADM_EXIT_USAGE);
857911106dfSjm 		}
858911106dfSjm 
859911106dfSjm 		if ((val = strchr(argv[i], '=')) == NULL)
860911106dfSjm 			return (VS_ADM_EXIT_USAGE);
861911106dfSjm 
862911106dfSjm 		/* Find the vscanadm property pointer from the property name */
863911106dfSjm 		*val = '\0';
864911106dfSjm 		val++;
865911106dfSjm 		if ((vap = vs_adm_prop_by_name(argv[i])) == NULL) {
866911106dfSjm 			(void) fprintf(stderr, "%s '%s'\n",
867911106dfSjm 			    gettext("invalid property"), argv[i]);
868911106dfSjm 			return (VS_ADM_EXIT_ERROR);
869911106dfSjm 		}
870911106dfSjm 
871911106dfSjm 		/* Add in the property id and parse the property value */
872911106dfSjm 		*propids |= vap->vap_id;
873911106dfSjm 		if ((vs_adm_parse(vap, val, vsprops)) != 0) {
874911106dfSjm 			(void) fprintf(stderr, "%s '%s'\n",
875911106dfSjm 			    gettext("invalid property value"), val);
876911106dfSjm 			return (VS_ADM_EXIT_ERROR);
877911106dfSjm 		}
878911106dfSjm 	}
879911106dfSjm 
880911106dfSjm 	return (VS_ADM_EXIT_SUCCESS);
881911106dfSjm }
882911106dfSjm 
883911106dfSjm 
884911106dfSjm /*
885911106dfSjm  * vs_adm_output_getcmd
886911106dfSjm  *
887911106dfSjm  * Prints the results of a get command; both the get for general
888911106dfSjm  * configuration properties as well as the get for an engine
889911106dfSjm  * properties.
890911106dfSjm  *
891911106dfSjm  */
892911106dfSjm static void
vs_adm_output_getcmd(uint64_t propids,const void * props)893911106dfSjm vs_adm_output_getcmd(uint64_t propids, const void *props)
894911106dfSjm {
895911106dfSjm 	char value[VS_ADM_PRINT_BUF_LEN];
896911106dfSjm 	uint64_t propid;
897911106dfSjm 	const vs_adm_property_t *vap;
898911106dfSjm 	char *label = NULL;
899911106dfSjm 
900911106dfSjm 	if (VS_PROPID_IS_SE(propids))
901911106dfSjm 		label = ((vs_props_se_t *)props)->vep_engid;
902911106dfSjm 
903911106dfSjm 	/*
904911106dfSjm 	 * Unparse values from the property structure into readable strings
905911106dfSjm 	 * and print them.
906911106dfSjm 	 */
907911106dfSjm 	for (propid = 1LL; propid <= VS_PROPID_MAX; propid <<= 1) {
908911106dfSjm 		if ((propids & propid) == 0)
909911106dfSjm 			continue;
910911106dfSjm 
911911106dfSjm 		if ((vap = vs_adm_prop_by_id(propid)) == NULL)
912911106dfSjm 			continue;
913911106dfSjm 
914911106dfSjm 		*value = '\0';
915911106dfSjm 		vs_adm_unparse(vap, props, value, sizeof (value));
916911106dfSjm 
917911106dfSjm 		if (label)
918911106dfSjm 			(void) fprintf(stdout, "%s:", label);
919911106dfSjm 		(void) fprintf(stdout, "%s=%s\n", vap->vap_name, value);
920911106dfSjm 	}
921911106dfSjm 
922911106dfSjm 	(void) fprintf(stdout, "\n");
923911106dfSjm }
924911106dfSjm 
925911106dfSjm 
926911106dfSjm /*
927911106dfSjm  * vs_adm_prop_by_name
928911106dfSjm  *
929911106dfSjm  * Finds and returns a pointer to a vscan property structure from the
930911106dfSjm  * property table by property name.
931911106dfSjm  */
932911106dfSjm static const vs_adm_property_t *
vs_adm_prop_by_name(const char * propname)933911106dfSjm vs_adm_prop_by_name(const char *propname)
934911106dfSjm {
935911106dfSjm 	const vs_adm_property_t *p;
936911106dfSjm 
937911106dfSjm 	for (p = vs_adm_props_all; p->vap_name != NULL; p++) {
938911106dfSjm 		if (strcmp(propname, p->vap_name) == 0)
939911106dfSjm 			return (p);
940911106dfSjm 	}
941911106dfSjm 
942911106dfSjm 	return (NULL);
943911106dfSjm }
944911106dfSjm 
945911106dfSjm 
946911106dfSjm /*
947911106dfSjm  * vs_adm_prop_by_id
948911106dfSjm  *
949911106dfSjm  * Finds and returns a pointer to a vscan property structure from the
950911106dfSjm  * property table by property name.
951911106dfSjm  */
952911106dfSjm static const vs_adm_property_t *
vs_adm_prop_by_id(const uint64_t propid)953911106dfSjm vs_adm_prop_by_id(const uint64_t propid)
954911106dfSjm {
955911106dfSjm 	const vs_adm_property_t *p;
956911106dfSjm 
957911106dfSjm 	for (p = vs_adm_props_all; p->vap_id != 0; p++) {
958911106dfSjm 		if (propid == p->vap_id)
959911106dfSjm 			return (p);
960911106dfSjm 	}
961911106dfSjm 
962911106dfSjm 	return (NULL);
963911106dfSjm }
964911106dfSjm 
965911106dfSjm 
966911106dfSjm /*
967911106dfSjm  * vs_adm_parse
968911106dfSjm  *
969911106dfSjm  * Entry point for parsing the user input strings into a data structure
970911106dfSjm  * used for setting values. Dispatches the actual parsing to the parse
971911106dfSjm  * routine for the specified vscanadm property.
972911106dfSjm  *
973911106dfSjm  * This function is used to dispatch parsing for values supplied by the
974911106dfSjm  * user for all subcommands; both the general configuration as well as
975911106dfSjm  * scan engine configuration. The structure pointer is therefore typed
976911106dfSjm  * as a void pointer, and cast appropriately in the parse routine for
977911106dfSjm  * the vscanadm property.
978911106dfSjm  */
979911106dfSjm static int
vs_adm_parse(const vs_adm_property_t * vap,const char * valvap_name,void * vp)980911106dfSjm vs_adm_parse(const vs_adm_property_t *vap, const char *valvap_name,
981911106dfSjm 	void *vp)
982911106dfSjm {
983911106dfSjm 	return ((vap->vap_parse)(valvap_name, vp));
984911106dfSjm }
985911106dfSjm 
986911106dfSjm 
987911106dfSjm /*
988911106dfSjm  * vs_adm_parse_maxsize
989911106dfSjm  *
990911106dfSjm  * Parses a user-supplied string into a maxsize (decimal) value for
991911106dfSjm  * the general vscan configuration properties.
992911106dfSjm  */
993911106dfSjm static int
vs_adm_parse_maxsize(const char * valstr,void * vp)994911106dfSjm vs_adm_parse_maxsize(const char *valstr, void *vp)
995911106dfSjm {
996911106dfSjm 	vs_props_t *svcp = vp;
997911106dfSjm 
998911106dfSjm 	uint64_t maxsize;
999911106dfSjm 	char *end;
1000911106dfSjm 
1001911106dfSjm 	errno = 0;
1002911106dfSjm 	maxsize = strtoll(valstr, &end, 10);
1003911106dfSjm 	if (errno != 0)
1004911106dfSjm 		return (-1);
1005911106dfSjm 	(void) snprintf(svcp->vp_maxsize, sizeof (svcp->vp_maxsize),
1006911106dfSjm 	    "%llu%s", maxsize, end);
1007911106dfSjm 
1008911106dfSjm 	return (0);
1009911106dfSjm }
1010911106dfSjm 
1011911106dfSjm 
1012911106dfSjm /*
1013911106dfSjm  * vs_adm_parse_maxsize_action
1014911106dfSjm  *
1015911106dfSjm  * Parses a user-supplied string into a maxsize action value for the
1016911106dfSjm  * general vscan configuration properties.
1017911106dfSjm  *
1018911106dfSjm  * Returns: 0 success
1019911106dfSjm  *         -1 failure
1020911106dfSjm  */
1021911106dfSjm static int
vs_adm_parse_maxsize_action(const char * valstr,void * vp)1022911106dfSjm vs_adm_parse_maxsize_action(const char *valstr, void *vp)
1023911106dfSjm {
1024911106dfSjm 	vs_props_t *svcp = vp;
1025911106dfSjm 
1026911106dfSjm 	if (strcmp(valstr, VS_ADM_ALLOW) == 0) {
1027911106dfSjm 		svcp->vp_maxsize_action = B_TRUE;
1028911106dfSjm 		return (0);
1029911106dfSjm 	}
1030911106dfSjm 
1031911106dfSjm 	if (strcmp(valstr, VS_ADM_DENY) == 0) {
1032911106dfSjm 		svcp->vp_maxsize_action = B_FALSE;
1033911106dfSjm 		return (0);
1034911106dfSjm 	}
1035911106dfSjm 
1036911106dfSjm 	return (-1);
1037911106dfSjm }
1038911106dfSjm 
1039911106dfSjm 
1040911106dfSjm /*
1041911106dfSjm  * vs_adm_parse_types
1042911106dfSjm  *
1043911106dfSjm  * Returns: 0 success
1044911106dfSjm  *         -1 on failure.
1045911106dfSjm  */
1046911106dfSjm static int
vs_adm_parse_types(const char * valstr,void * vp)1047911106dfSjm vs_adm_parse_types(const char *valstr, void *vp)
1048911106dfSjm {
1049911106dfSjm 	vs_props_t *svcp = vp;
1050911106dfSjm 
1051911106dfSjm 	if (strlen(valstr) >= sizeof (svcp->vp_types))
1052911106dfSjm 		return (-1);
1053911106dfSjm 
1054911106dfSjm 	if (strlcpy(svcp->vp_types, valstr, sizeof (svcp->vp_types))
1055911106dfSjm 	    >= sizeof (svcp->vp_types))
1056911106dfSjm 		return (-1);
1057911106dfSjm 
1058911106dfSjm 	return (0);
1059911106dfSjm }
1060911106dfSjm 
1061911106dfSjm 
1062911106dfSjm /*
1063911106dfSjm  * vs_adm_parse_enable
1064911106dfSjm  *
1065911106dfSjm  * Parses a user-supplied string into an enable value for the
1066911106dfSjm  * properties of a scan engine.
1067911106dfSjm  *
1068911106dfSjm  * Returns: 0 success
1069911106dfSjm  *         -1 on failure.
1070911106dfSjm  */
1071911106dfSjm static int
vs_adm_parse_enable(const char * valstr,void * vp)1072911106dfSjm vs_adm_parse_enable(const char *valstr, void *vp)
1073911106dfSjm {
1074911106dfSjm 	vs_props_se_t *sep = vp;
1075911106dfSjm 
1076911106dfSjm 	if (strcmp(valstr, VS_ADM_ON) == 0) {
1077911106dfSjm 		sep->vep_enable = B_TRUE;
1078911106dfSjm 		return (0);
1079911106dfSjm 	}
1080911106dfSjm 
1081911106dfSjm 	if (strcmp(valstr, VS_ADM_OFF) == 0) {
1082911106dfSjm 		sep->vep_enable = B_FALSE;
1083911106dfSjm 		return (0);
1084911106dfSjm 	}
1085911106dfSjm 
1086911106dfSjm 	return (-1);
1087911106dfSjm }
1088911106dfSjm 
1089911106dfSjm 
1090911106dfSjm /*
1091911106dfSjm  * vs_adm_parse_host
1092911106dfSjm  *
1093911106dfSjm  * Parses a user-supplied string into an ip address value for the
1094911106dfSjm  * properties of a scan engine.
1095911106dfSjm  */
1096911106dfSjm static int
vs_adm_parse_host(const char * valstr,void * vp)1097911106dfSjm vs_adm_parse_host(const char *valstr, void *vp)
1098911106dfSjm {
1099911106dfSjm 	vs_props_se_t *sep = vp;
1100911106dfSjm 
1101911106dfSjm 	if (strlen(valstr) >= sizeof (sep->vep_host))
1102911106dfSjm 		return (-1);
1103911106dfSjm 
1104911106dfSjm 	if (strlcpy(sep->vep_host, valstr, sizeof (sep->vep_host)) >=
1105911106dfSjm 	    sizeof (sep->vep_host))
1106911106dfSjm 		return (-1);
1107911106dfSjm 
1108911106dfSjm 	return (0);
1109911106dfSjm }
1110911106dfSjm 
1111911106dfSjm 
1112911106dfSjm /*
1113911106dfSjm  * vs_adm_parse_port
1114911106dfSjm  *
1115911106dfSjm  * Parses a user-supplied string into a port value for the properties of
1116911106dfSjm  * a scan engine. The port is an unsigned short int, but the conversion
1117911106dfSjm  * must be done on a word-sized int. Casting the converted int into the
1118911106dfSjm  * port member of the property structure can result in a valid but
1119911106dfSjm  * unintended value, so the range is checked first for validity.
1120911106dfSjm  *
1121911106dfSjm  * Returns: 0 success
1122911106dfSjm  *         -1 on failure.
1123911106dfSjm  */
1124911106dfSjm static int
vs_adm_parse_port(const char * valstr,void * vp)1125911106dfSjm vs_adm_parse_port(const char *valstr, void *vp)
1126911106dfSjm {
1127911106dfSjm 	vs_props_se_t *sep = vp;
1128911106dfSjm 	unsigned long port;
1129911106dfSjm 	char *end;
1130911106dfSjm 
1131911106dfSjm 	end = 0;
1132911106dfSjm 	port = strtoul(valstr, &end, 0);
1133911106dfSjm 	if (port > UINT16_MAX || (end < (valstr + strlen(valstr))))
1134911106dfSjm 		return (-1);
1135911106dfSjm 
1136911106dfSjm 	sep->vep_port = port;
1137911106dfSjm 
1138911106dfSjm 	return (0);
1139911106dfSjm }
1140911106dfSjm 
1141911106dfSjm 
1142911106dfSjm /*
1143911106dfSjm  * vs_adm_parse_maxconn
1144911106dfSjm  *
1145911106dfSjm  * Parses a user-supplied string into a max connections (decimal) value
1146911106dfSjm  * for the properties of a scan engine.
1147911106dfSjm  *
1148911106dfSjm  * Returns: 0 success
1149911106dfSjm  *         -1 on failure.
1150911106dfSjm  */
1151911106dfSjm static int
vs_adm_parse_maxconn(const char * valstr,void * vp)1152911106dfSjm vs_adm_parse_maxconn(const char *valstr, void *vp)
1153911106dfSjm {
1154911106dfSjm 	vs_props_se_t *sep = vp;
1155911106dfSjm 	char *end;
1156911106dfSjm 
1157911106dfSjm 	sep->vep_maxconn = strtoll(valstr, &end, 10);
1158911106dfSjm 	if (end < valstr + strlen(valstr))
1159911106dfSjm 		return (-1);
1160911106dfSjm 
1161911106dfSjm 	return (0);
1162911106dfSjm }
1163911106dfSjm 
1164911106dfSjm 
1165911106dfSjm /*
1166911106dfSjm  * vs_adm_unparse
1167911106dfSjm  *
1168911106dfSjm  * Entry point for unparsing native data into a readable string
1169911106dfSjm  * used for display to the user. Dispatches the actual unparsing to
1170911106dfSjm  * the unparse routine for the specified vscanadm property.
1171911106dfSjm  *
1172911106dfSjm  * This function is used to dispatch unparsing for all subcommands.
1173911106dfSjm  * The structure pointer is therefore typed as a void pointer, and
1174911106dfSjm  * cast appropriately in the unparse routine for the vscanadm property.
1175911106dfSjm  */
1176911106dfSjm static void
vs_adm_unparse(const vs_adm_property_t * vap,const void * vp,char * buf,size_t len)1177911106dfSjm vs_adm_unparse(const vs_adm_property_t *vap, const void *vp,
1178911106dfSjm 	char *buf, size_t len)
1179911106dfSjm {
1180911106dfSjm 	if ((vap->vap_unparse)(vp, buf, len) != 0)
1181911106dfSjm 		(void) snprintf(buf, len, gettext(" (error) "));
1182911106dfSjm }
1183911106dfSjm 
1184911106dfSjm 
1185911106dfSjm /*
1186911106dfSjm  *  vs_adm_unparse_maxsize
1187911106dfSjm  *
1188911106dfSjm  * Unparses a max fsize value in native data form into a
1189911106dfSjm  * user-readable string.
1190911106dfSjm  */
1191911106dfSjm /* ARGSUSED */
1192911106dfSjm static int
vs_adm_unparse_maxsize(const void * vp,char * buf,size_t len)1193911106dfSjm vs_adm_unparse_maxsize(const void *vp, char *buf, size_t len)
1194911106dfSjm {
1195911106dfSjm 	const vs_props_t *svcp = vp;
1196911106dfSjm 
1197911106dfSjm 	(void) snprintf(buf, len, "%s", svcp->vp_maxsize);
1198911106dfSjm 
1199911106dfSjm 	return (0);
1200911106dfSjm }
1201911106dfSjm 
1202911106dfSjm 
1203911106dfSjm /*
1204911106dfSjm  * vs_adm_unparse_maxsize_action
1205911106dfSjm  *
1206911106dfSjm  * Unparses a max fsize action value in native data form into a
1207911106dfSjm  * user-readable string.
1208911106dfSjm  */
1209911106dfSjm /* ARGSUSED */
1210911106dfSjm static int
vs_adm_unparse_maxsize_action(const void * vp,char * buf,size_t len)1211911106dfSjm vs_adm_unparse_maxsize_action(const void *vp, char *buf, size_t len)
1212911106dfSjm {
1213911106dfSjm 	const vs_props_t *svcp = vp;
1214911106dfSjm 
1215911106dfSjm 	(void) snprintf(buf, len, "%s",
1216911106dfSjm 	    svcp->vp_maxsize_action ?  VS_ADM_ALLOW : VS_ADM_DENY);
1217911106dfSjm 
1218911106dfSjm 	return (0);
1219911106dfSjm }
1220911106dfSjm 
1221911106dfSjm 
1222911106dfSjm /*
1223911106dfSjm  * vs_adm_unparse_types
1224911106dfSjm  *
1225911106dfSjm  * Returns: 0 success
1226911106dfSjm  *         -1 on failure.
1227911106dfSjm  */
1228911106dfSjm static int
vs_adm_unparse_types(const void * vp,char * buf,size_t len)1229911106dfSjm vs_adm_unparse_types(const void *vp, char *buf, size_t len)
1230911106dfSjm {
1231911106dfSjm 	const vs_props_t *svcp = vp;
1232911106dfSjm 
1233911106dfSjm 	(void) strlcpy(buf, svcp->vp_types, len);
1234911106dfSjm 
1235911106dfSjm 	return (0);
1236911106dfSjm }
1237911106dfSjm 
1238911106dfSjm 
1239911106dfSjm /*
1240911106dfSjm  * vs_adm_unparse_enable
1241911106dfSjm  *
1242911106dfSjm  * Unparses the enable value for a scan engine in native data
1243911106dfSjm  * form into a user-readable string.
1244911106dfSjm  */
1245911106dfSjm /* ARGSUSED */
1246911106dfSjm static int
vs_adm_unparse_enable(const void * vp,char * buf,size_t len)1247911106dfSjm vs_adm_unparse_enable(const void *vp, char *buf, size_t len)
1248911106dfSjm {
1249911106dfSjm 	const vs_props_se_t *sep = vp;
1250911106dfSjm 
1251911106dfSjm 	(void) snprintf(buf, len, "%s",
1252911106dfSjm 	    sep->vep_enable ?  VS_ADM_ON : VS_ADM_OFF);
1253911106dfSjm 
1254911106dfSjm 	return (0);
1255911106dfSjm }
1256911106dfSjm 
1257911106dfSjm 
1258911106dfSjm /*
1259911106dfSjm  * vs_adm_unparse_host
1260911106dfSjm  *
1261911106dfSjm  * Unparses an ip address for a scan engine in native data
1262911106dfSjm  * form into a user-readable string.
1263911106dfSjm  *
1264911106dfSjm  * Returns: 0 success
1265911106dfSjm  *         -1 on failure.
1266911106dfSjm  */
1267911106dfSjm /* ARGSUSED */
1268911106dfSjm static int
vs_adm_unparse_host(const void * vp,char * buf,size_t len)1269911106dfSjm vs_adm_unparse_host(const void *vp, char *buf, size_t len)
1270911106dfSjm {
1271911106dfSjm 	const vs_props_se_t *sep = vp;
1272911106dfSjm 
1273911106dfSjm 	(void) strlcpy(buf, sep->vep_host, len);
1274911106dfSjm 
1275911106dfSjm 	return (0);
1276911106dfSjm }
1277911106dfSjm 
1278911106dfSjm 
1279911106dfSjm /*
1280911106dfSjm  * vs_adm_unparse_port
1281911106dfSjm  *
1282911106dfSjm  * Unparses a port value for a scan engine in native data
1283911106dfSjm  * form into a user-readable string.
1284911106dfSjm  */
1285911106dfSjm /* ARGSUSED */
1286911106dfSjm static int
vs_adm_unparse_port(const void * vp,char * buf,size_t len)1287911106dfSjm vs_adm_unparse_port(const void *vp, char *buf, size_t len)
1288911106dfSjm {
1289911106dfSjm 	const vs_props_se_t *sep = vp;
1290911106dfSjm 
1291911106dfSjm 	(void) snprintf(buf, len, "%hu", sep->vep_port);
1292911106dfSjm 
1293911106dfSjm 	return (0);
1294911106dfSjm }
1295911106dfSjm 
1296911106dfSjm 
1297911106dfSjm /*
1298911106dfSjm  * vs_adm_unparse_maxconn
1299911106dfSjm  *
1300911106dfSjm  * Unparses a max connecctions for a scan engine in native data
1301911106dfSjm  * form into a user-readable string.
1302911106dfSjm  *
1303911106dfSjm  */
1304911106dfSjm /* ARGSUSED */
1305911106dfSjm static int
vs_adm_unparse_maxconn(const void * vp,char * buf,size_t len)1306911106dfSjm vs_adm_unparse_maxconn(const void *vp, char *buf, size_t len)
1307911106dfSjm {
1308911106dfSjm 	const vs_props_se_t *sep = vp;
1309911106dfSjm 
1310911106dfSjm 	(void) snprintf(buf, len, "%lld", sep->vep_maxconn);
1311911106dfSjm 
1312911106dfSjm 	return (0);
1313911106dfSjm }
1314