1*3147Sxc151355 /*
2*3147Sxc151355  * CDDL HEADER START
3*3147Sxc151355  *
4*3147Sxc151355  * The contents of this file are subject to the terms of the
5*3147Sxc151355  * Common Development and Distribution License (the "License").
6*3147Sxc151355  * You may not use this file except in compliance with the License.
7*3147Sxc151355  *
8*3147Sxc151355  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3147Sxc151355  * or http://www.opensolaris.org/os/licensing.
10*3147Sxc151355  * See the License for the specific language governing permissions
11*3147Sxc151355  * and limitations under the License.
12*3147Sxc151355  *
13*3147Sxc151355  * When distributing Covered Code, include this CDDL HEADER in each
14*3147Sxc151355  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3147Sxc151355  * If applicable, add the following below this CDDL HEADER, with the
16*3147Sxc151355  * fields enclosed by brackets "[]" replaced with your own identifying
17*3147Sxc151355  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3147Sxc151355  *
19*3147Sxc151355  * CDDL HEADER END
20*3147Sxc151355  */
21*3147Sxc151355 /*
22*3147Sxc151355  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*3147Sxc151355  * Use is subject to license terms.
24*3147Sxc151355  */
25*3147Sxc151355 
26*3147Sxc151355 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*3147Sxc151355 
28*3147Sxc151355 #include <unistd.h>
29*3147Sxc151355 #include <stdlib.h>
30*3147Sxc151355 #include <strings.h>
31*3147Sxc151355 #include <errno.h>
32*3147Sxc151355 #include <ctype.h>
33*3147Sxc151355 #include <fcntl.h>
34*3147Sxc151355 #include <sys/stat.h>
35*3147Sxc151355 #include <sys/dld.h>
36*3147Sxc151355 #include <libinetutil.h>
37*3147Sxc151355 #include <libdladm_impl.h>
38*3147Sxc151355 
39*3147Sxc151355 static dladm_status_t	i_dladm_set_secobj_db(const char *,
40*3147Sxc151355 			    dladm_secobj_class_t, uint8_t *, uint_t);
41*3147Sxc151355 static dladm_status_t	i_dladm_get_secobj_db(const char *,
42*3147Sxc151355 			    dladm_secobj_class_t *, uint8_t *, uint_t *);
43*3147Sxc151355 static dladm_status_t	i_dladm_unset_secobj_db(const char *);
44*3147Sxc151355 static dladm_status_t	i_dladm_walk_secobj_db(void *,
45*3147Sxc151355 			    boolean_t (*)(void *, const char *));
46*3147Sxc151355 
47*3147Sxc151355 typedef struct secobj_class_info {
48*3147Sxc151355 	const char		*sc_name;
49*3147Sxc151355 	dld_secobj_class_t	sc_dldclass;
50*3147Sxc151355 } secobj_class_info_t;
51*3147Sxc151355 
52*3147Sxc151355 static secobj_class_info_t secobj_class_table[] = {
53*3147Sxc151355 	{"wep",	DLD_SECOBJ_CLASS_WEP}
54*3147Sxc151355 };
55*3147Sxc151355 
56*3147Sxc151355 #define	NSECOBJCLASS \
57*3147Sxc151355 	(sizeof (secobj_class_table) / sizeof (secobj_class_info_t))
58*3147Sxc151355 
59*3147Sxc151355 static boolean_t
60*3147Sxc151355 dladm_check_secobjclass(dladm_secobj_class_t class)
61*3147Sxc151355 {
62*3147Sxc151355 	return (class >= 0 && class < NSECOBJCLASS);
63*3147Sxc151355 }
64*3147Sxc151355 
65*3147Sxc151355 dladm_status_t
66*3147Sxc151355 dladm_str2secobjclass(const char *str, dladm_secobj_class_t *class)
67*3147Sxc151355 {
68*3147Sxc151355 	int			i;
69*3147Sxc151355 	secobj_class_info_t	*sp;
70*3147Sxc151355 
71*3147Sxc151355 	for (i = 0; i < NSECOBJCLASS; i++) {
72*3147Sxc151355 		sp = &secobj_class_table[i];
73*3147Sxc151355 		if (strcasecmp(str, sp->sc_name) == 0) {
74*3147Sxc151355 			*class = i;
75*3147Sxc151355 			return (DLADM_STATUS_OK);
76*3147Sxc151355 		}
77*3147Sxc151355 	}
78*3147Sxc151355 	return (DLADM_STATUS_BADARG);
79*3147Sxc151355 }
80*3147Sxc151355 
81*3147Sxc151355 const char *
82*3147Sxc151355 dladm_secobjclass2str(dladm_secobj_class_t class, char *buf)
83*3147Sxc151355 {
84*3147Sxc151355 	const char		*s;
85*3147Sxc151355 
86*3147Sxc151355 	if (!dladm_check_secobjclass(class))
87*3147Sxc151355 		s = "";
88*3147Sxc151355 	else
89*3147Sxc151355 		s = secobj_class_table[class].sc_name;
90*3147Sxc151355 
91*3147Sxc151355 	(void) snprintf(buf, DLADM_STRSIZE, "%s", s);
92*3147Sxc151355 	return (buf);
93*3147Sxc151355 }
94*3147Sxc151355 
95*3147Sxc151355 static boolean_t
96*3147Sxc151355 dladm_convert_secobjclass(dladm_secobj_class_t class,
97*3147Sxc151355     dld_secobj_class_t *dldclass)
98*3147Sxc151355 {
99*3147Sxc151355 	if (!dladm_check_secobjclass(class))
100*3147Sxc151355 		return (B_FALSE);
101*3147Sxc151355 
102*3147Sxc151355 	*dldclass = secobj_class_table[class].sc_dldclass;
103*3147Sxc151355 	return (B_TRUE);
104*3147Sxc151355 }
105*3147Sxc151355 
106*3147Sxc151355 static boolean_t
107*3147Sxc151355 dladm_convert_dldsecobjclass(dld_secobj_class_t dldclass,
108*3147Sxc151355     dladm_secobj_class_t *class)
109*3147Sxc151355 {
110*3147Sxc151355 	int			i;
111*3147Sxc151355 	secobj_class_info_t	*sp;
112*3147Sxc151355 
113*3147Sxc151355 	for (i = 0; i < NSECOBJCLASS; i++) {
114*3147Sxc151355 		sp = &secobj_class_table[i];
115*3147Sxc151355 		if (dldclass == sp->sc_dldclass) {
116*3147Sxc151355 			*class = i;
117*3147Sxc151355 			return (B_TRUE);
118*3147Sxc151355 		}
119*3147Sxc151355 	}
120*3147Sxc151355 	return (B_FALSE);
121*3147Sxc151355 }
122*3147Sxc151355 
123*3147Sxc151355 dladm_status_t
124*3147Sxc151355 dladm_set_secobj(const char *obj_name, dladm_secobj_class_t class,
125*3147Sxc151355     uint8_t *obj_val, uint_t obj_len, uint_t flags)
126*3147Sxc151355 {
127*3147Sxc151355 	int			fd;
128*3147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
129*3147Sxc151355 	dld_ioc_secobj_set_t	secobj_set;
130*3147Sxc151355 	dld_secobj_t		*objp;
131*3147Sxc151355 
132*3147Sxc151355 	if (!dladm_check_secobjclass(class) || flags == 0 ||
133*3147Sxc151355 	    obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
134*3147Sxc151355 	    obj_val == NULL || obj_len == 0 || obj_len > DLD_SECOBJ_VAL_MAX)
135*3147Sxc151355 		return (DLADM_STATUS_BADARG);
136*3147Sxc151355 
137*3147Sxc151355 	if ((flags & DLADM_OPT_TEMP) == 0)
138*3147Sxc151355 		goto persist;
139*3147Sxc151355 
140*3147Sxc151355 	bzero(&secobj_set, sizeof (secobj_set));
141*3147Sxc151355 	objp = &secobj_set.ss_obj;
142*3147Sxc151355 	if (!dladm_convert_secobjclass(class, &objp->so_class))
143*3147Sxc151355 		return (DLADM_STATUS_BADARG);
144*3147Sxc151355 
145*3147Sxc151355 	(void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
146*3147Sxc151355 	bcopy(obj_val, objp->so_val, obj_len);
147*3147Sxc151355 	objp->so_len = obj_len;
148*3147Sxc151355 
149*3147Sxc151355 	if ((flags & DLADM_OPT_CREATE) != 0)
150*3147Sxc151355 		secobj_set.ss_flags = DLD_SECOBJ_OPT_CREATE;
151*3147Sxc151355 
152*3147Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
153*3147Sxc151355 		return (dladm_errno2status(errno));
154*3147Sxc151355 
155*3147Sxc151355 	if (i_dladm_ioctl(fd, DLDIOCSECOBJSET, &secobj_set,
156*3147Sxc151355 	    sizeof (secobj_set)) < 0)
157*3147Sxc151355 		status = dladm_errno2status(errno);
158*3147Sxc151355 
159*3147Sxc151355 	(void) close(fd);
160*3147Sxc151355 	if (status != DLADM_STATUS_OK)
161*3147Sxc151355 		return (status);
162*3147Sxc151355 
163*3147Sxc151355 persist:
164*3147Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0) {
165*3147Sxc151355 		status = i_dladm_set_secobj_db(obj_name, class,
166*3147Sxc151355 		    obj_val, obj_len);
167*3147Sxc151355 	}
168*3147Sxc151355 	return (status);
169*3147Sxc151355 }
170*3147Sxc151355 
171*3147Sxc151355 dladm_status_t
172*3147Sxc151355 dladm_get_secobj(const char *obj_name, dladm_secobj_class_t *classp,
173*3147Sxc151355     uint8_t *obj_val, uint_t *obj_lenp, uint_t flags)
174*3147Sxc151355 {
175*3147Sxc151355 	int			fd;
176*3147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
177*3147Sxc151355 	dld_ioc_secobj_get_t	secobj_get;
178*3147Sxc151355 	dld_secobj_t		*objp;
179*3147Sxc151355 
180*3147Sxc151355 	if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
181*3147Sxc151355 	    obj_val == NULL || obj_lenp == NULL || *obj_lenp == 0 ||
182*3147Sxc151355 	    *obj_lenp > DLD_SECOBJ_VAL_MAX)
183*3147Sxc151355 		return (DLADM_STATUS_BADARG);
184*3147Sxc151355 
185*3147Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0) {
186*3147Sxc151355 		return (i_dladm_get_secobj_db(obj_name, classp,
187*3147Sxc151355 		    obj_val, obj_lenp));
188*3147Sxc151355 	}
189*3147Sxc151355 
190*3147Sxc151355 	bzero(&secobj_get, sizeof (secobj_get));
191*3147Sxc151355 	objp = &secobj_get.sg_obj;
192*3147Sxc151355 	(void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
193*3147Sxc151355 
194*3147Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
195*3147Sxc151355 		return (dladm_errno2status(errno));
196*3147Sxc151355 
197*3147Sxc151355 	if (i_dladm_ioctl(fd, DLDIOCSECOBJGET, &secobj_get,
198*3147Sxc151355 	    sizeof (secobj_get)) < 0)
199*3147Sxc151355 		status = dladm_errno2status(errno);
200*3147Sxc151355 
201*3147Sxc151355 	(void) close(fd);
202*3147Sxc151355 	if (objp->so_len > *obj_lenp)
203*3147Sxc151355 		return (DLADM_STATUS_TOOSMALL);
204*3147Sxc151355 
205*3147Sxc151355 	if (!dladm_convert_dldsecobjclass(objp->so_class, classp))
206*3147Sxc151355 		return (DLADM_STATUS_FAILED);
207*3147Sxc151355 
208*3147Sxc151355 	*obj_lenp = objp->so_len;
209*3147Sxc151355 	bcopy(objp->so_val, obj_val, *obj_lenp);
210*3147Sxc151355 	return (status);
211*3147Sxc151355 }
212*3147Sxc151355 
213*3147Sxc151355 dladm_status_t
214*3147Sxc151355 dladm_unset_secobj(const char *obj_name, uint_t flags)
215*3147Sxc151355 {
216*3147Sxc151355 	int			fd;
217*3147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
218*3147Sxc151355 	dld_ioc_secobj_unset_t	secobj_unset;
219*3147Sxc151355 
220*3147Sxc151355 	if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
221*3147Sxc151355 	    flags == 0)
222*3147Sxc151355 		return (DLADM_STATUS_BADARG);
223*3147Sxc151355 
224*3147Sxc151355 	if ((flags & DLADM_OPT_TEMP) == 0)
225*3147Sxc151355 		goto persist;
226*3147Sxc151355 
227*3147Sxc151355 	bzero(&secobj_unset, sizeof (secobj_unset));
228*3147Sxc151355 	(void) strlcpy(secobj_unset.su_name, obj_name, DLD_SECOBJ_NAME_MAX);
229*3147Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
230*3147Sxc151355 		return (dladm_errno2status(errno));
231*3147Sxc151355 
232*3147Sxc151355 	if (i_dladm_ioctl(fd, DLDIOCSECOBJUNSET, &secobj_unset,
233*3147Sxc151355 	    sizeof (secobj_unset)) < 0)
234*3147Sxc151355 		status = dladm_errno2status(errno);
235*3147Sxc151355 
236*3147Sxc151355 	(void) close(fd);
237*3147Sxc151355 	if (status != DLADM_STATUS_OK)
238*3147Sxc151355 		return (status);
239*3147Sxc151355 
240*3147Sxc151355 persist:
241*3147Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0)
242*3147Sxc151355 		status = i_dladm_unset_secobj_db(obj_name);
243*3147Sxc151355 
244*3147Sxc151355 	return (status);
245*3147Sxc151355 }
246*3147Sxc151355 
247*3147Sxc151355 #define	SECOBJ_BUFSZ	65536
248*3147Sxc151355 dladm_status_t
249*3147Sxc151355 dladm_walk_secobj(void *arg, boolean_t (*func)(void *, const char *),
250*3147Sxc151355     uint_t flags)
251*3147Sxc151355 {
252*3147Sxc151355 	int			fd = -1;
253*3147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
254*3147Sxc151355 	dld_ioc_secobj_get_t	*secobj_getp;
255*3147Sxc151355 	dld_secobj_t		*objp;
256*3147Sxc151355 
257*3147Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0)
258*3147Sxc151355 		return (i_dladm_walk_secobj_db(arg, func));
259*3147Sxc151355 
260*3147Sxc151355 	secobj_getp = calloc(1, SECOBJ_BUFSZ);
261*3147Sxc151355 	if (secobj_getp == NULL)
262*3147Sxc151355 		return (DLADM_STATUS_NOMEM);
263*3147Sxc151355 
264*3147Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
265*3147Sxc151355 		status = dladm_errno2status(errno);
266*3147Sxc151355 		goto done;
267*3147Sxc151355 	}
268*3147Sxc151355 	if (i_dladm_ioctl(fd, DLDIOCSECOBJGET, secobj_getp,
269*3147Sxc151355 	    SECOBJ_BUFSZ) < 0) {
270*3147Sxc151355 		status = dladm_errno2status(errno);
271*3147Sxc151355 		goto done;
272*3147Sxc151355 	}
273*3147Sxc151355 
274*3147Sxc151355 	objp = (dld_secobj_t *)(secobj_getp + 1);
275*3147Sxc151355 	while (secobj_getp->sg_count > 0) {
276*3147Sxc151355 		if (!func(arg, objp->so_name))
277*3147Sxc151355 			goto done;
278*3147Sxc151355 		secobj_getp->sg_count--;
279*3147Sxc151355 		objp++;
280*3147Sxc151355 	}
281*3147Sxc151355 done:
282*3147Sxc151355 	(void) close(fd);
283*3147Sxc151355 	free(secobj_getp);
284*3147Sxc151355 	return (status);
285*3147Sxc151355 }
286*3147Sxc151355 
287*3147Sxc151355 /*
288*3147Sxc151355  * Data structures used for implementing persistent secure objects
289*3147Sxc151355  */
290*3147Sxc151355 typedef struct secobj_info {
291*3147Sxc151355 	const char		*si_name;
292*3147Sxc151355 	dladm_secobj_class_t	*si_classp;
293*3147Sxc151355 	uint8_t			*si_val;
294*3147Sxc151355 	uint_t			*si_lenp;
295*3147Sxc151355 } secobj_info_t;
296*3147Sxc151355 
297*3147Sxc151355 typedef struct secobj_name {
298*3147Sxc151355 	char			*sn_name;
299*3147Sxc151355 	struct secobj_name	*sn_next;
300*3147Sxc151355 } secobj_name_t;
301*3147Sxc151355 
302*3147Sxc151355 typedef struct secobj_db_state	secobj_db_state_t;
303*3147Sxc151355 
304*3147Sxc151355 typedef boolean_t (*secobj_db_op_t)(struct secobj_db_state *, char *,
305*3147Sxc151355     secobj_info_t *, dladm_status_t *);
306*3147Sxc151355 
307*3147Sxc151355 struct secobj_db_state {
308*3147Sxc151355 	secobj_db_op_t		ss_op;
309*3147Sxc151355 	secobj_info_t		ss_info;
310*3147Sxc151355 	secobj_name_t		**ss_namelist;
311*3147Sxc151355 };
312*3147Sxc151355 
313*3147Sxc151355 /*
314*3147Sxc151355  * Update or generate a secobj entry using the info in ssp->ss_info.
315*3147Sxc151355  */
316*3147Sxc151355 /* ARGSUSED */
317*3147Sxc151355 static boolean_t
318*3147Sxc151355 process_secobj_set(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
319*3147Sxc151355     dladm_status_t *statusp)
320*3147Sxc151355 {
321*3147Sxc151355 	char	tmpbuf[MAXLINELEN];
322*3147Sxc151355 	char	classbuf[DLADM_STRSIZE];
323*3147Sxc151355 	char	*ptr = tmpbuf, *lim = tmpbuf + MAXLINELEN;
324*3147Sxc151355 	int	i;
325*3147Sxc151355 
326*3147Sxc151355 	sip = &ssp->ss_info;
327*3147Sxc151355 
328*3147Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", sip->si_name);
329*3147Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t",
330*3147Sxc151355 	    dladm_secobjclass2str(*sip->si_classp, classbuf));
331*3147Sxc151355 
332*3147Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "0x");
333*3147Sxc151355 	for (i = 0; i < *sip->si_lenp; i++) {
334*3147Sxc151355 		ptr += snprintf(ptr, BUFLEN(lim, ptr), "%02x",
335*3147Sxc151355 		    sip->si_val[i] & 0xff);
336*3147Sxc151355 	}
337*3147Sxc151355 	if (ptr > lim) {
338*3147Sxc151355 		*statusp = DLADM_STATUS_TOOSMALL;
339*3147Sxc151355 		return (B_FALSE);
340*3147Sxc151355 	}
341*3147Sxc151355 	(void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
342*3147Sxc151355 	return (B_FALSE);
343*3147Sxc151355 }
344*3147Sxc151355 
345*3147Sxc151355 /* ARGSUSED */
346*3147Sxc151355 static boolean_t
347*3147Sxc151355 process_secobj_get(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
348*3147Sxc151355     dladm_status_t *statusp)
349*3147Sxc151355 {
350*3147Sxc151355 	if (*sip->si_lenp > *ssp->ss_info.si_lenp) {
351*3147Sxc151355 		*statusp = DLADM_STATUS_TOOSMALL;
352*3147Sxc151355 		return (B_FALSE);
353*3147Sxc151355 	}
354*3147Sxc151355 	bcopy(sip->si_val, ssp->ss_info.si_val, *sip->si_lenp);
355*3147Sxc151355 	*ssp->ss_info.si_lenp = *sip->si_lenp;
356*3147Sxc151355 	*ssp->ss_info.si_classp = *sip->si_classp;
357*3147Sxc151355 	return (B_FALSE);
358*3147Sxc151355 }
359*3147Sxc151355 
360*3147Sxc151355 /* ARGSUSED */
361*3147Sxc151355 static boolean_t
362*3147Sxc151355 process_secobj_unset(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
363*3147Sxc151355     dladm_status_t *statusp)
364*3147Sxc151355 {
365*3147Sxc151355 	/*
366*3147Sxc151355 	 * Delete line.
367*3147Sxc151355 	 */
368*3147Sxc151355 	buf[0] = '\0';
369*3147Sxc151355 	return (B_FALSE);
370*3147Sxc151355 }
371*3147Sxc151355 
372*3147Sxc151355 /* ARGSUSED */
373*3147Sxc151355 static boolean_t
374*3147Sxc151355 process_secobj_walk(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
375*3147Sxc151355     dladm_status_t *statusp)
376*3147Sxc151355 {
377*3147Sxc151355 	secobj_name_t	*snp;
378*3147Sxc151355 
379*3147Sxc151355 	if ((snp = malloc(sizeof (*snp))) == NULL)
380*3147Sxc151355 		return (B_TRUE);
381*3147Sxc151355 
382*3147Sxc151355 	if ((snp->sn_name = strdup(sip->si_name)) == NULL) {
383*3147Sxc151355 		free(snp);
384*3147Sxc151355 		return (B_TRUE);
385*3147Sxc151355 	}
386*3147Sxc151355 
387*3147Sxc151355 	snp->sn_next = NULL;
388*3147Sxc151355 	*ssp->ss_namelist = snp;
389*3147Sxc151355 	ssp->ss_namelist = &snp->sn_next;
390*3147Sxc151355 	return (B_TRUE);
391*3147Sxc151355 }
392*3147Sxc151355 
393*3147Sxc151355 /* ARGSUSED */
394*3147Sxc151355 static boolean_t
395*3147Sxc151355 process_secobj_init(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
396*3147Sxc151355     dladm_status_t *statusp)
397*3147Sxc151355 {
398*3147Sxc151355 	*statusp = dladm_set_secobj(sip->si_name, *sip->si_classp, sip->si_val,
399*3147Sxc151355 	    *sip->si_lenp, DLADM_OPT_TEMP | DLADM_OPT_CREATE);
400*3147Sxc151355 	return (B_TRUE);
401*3147Sxc151355 }
402*3147Sxc151355 
403*3147Sxc151355 static int
404*3147Sxc151355 parse_secobj_val(char *buf, secobj_info_t *sip)
405*3147Sxc151355 {
406*3147Sxc151355 	if (strncmp(buf, "0x", 2) != 0)
407*3147Sxc151355 		return (EINVAL);
408*3147Sxc151355 
409*3147Sxc151355 	return (hexascii_to_octet(buf + 2, strlen(buf) - 2,
410*3147Sxc151355 	    sip->si_val, sip->si_lenp));
411*3147Sxc151355 }
412*3147Sxc151355 
413*3147Sxc151355 static boolean_t
414*3147Sxc151355 process_secobj_line(secobj_db_state_t *ssp, char *buf,
415*3147Sxc151355     dladm_status_t *statusp)
416*3147Sxc151355 {
417*3147Sxc151355 	secobj_info_t		sinfo;
418*3147Sxc151355 	dladm_secobj_class_t	class;
419*3147Sxc151355 	uint8_t			val[DLADM_SECOBJ_VAL_MAX];
420*3147Sxc151355 	uint_t			vlen;
421*3147Sxc151355 	int			i, len, nlen;
422*3147Sxc151355 	char			*str, *lasts;
423*3147Sxc151355 
424*3147Sxc151355 	/*
425*3147Sxc151355 	 * Skip leading spaces, blank lines, and comments.
426*3147Sxc151355 	 */
427*3147Sxc151355 	len = strlen(buf);
428*3147Sxc151355 	for (i = 0; i < len; i++) {
429*3147Sxc151355 		if (!isspace(buf[i]))
430*3147Sxc151355 			break;
431*3147Sxc151355 	}
432*3147Sxc151355 	if (i == len || buf[i] == '#')
433*3147Sxc151355 		return (B_TRUE);
434*3147Sxc151355 
435*3147Sxc151355 	str = buf + i;
436*3147Sxc151355 	if (ssp->ss_info.si_name != NULL) {
437*3147Sxc151355 		/*
438*3147Sxc151355 		 * Skip objects we're not interested in.
439*3147Sxc151355 		 */
440*3147Sxc151355 		nlen = strlen(ssp->ss_info.si_name);
441*3147Sxc151355 		if (strncmp(str, ssp->ss_info.si_name, nlen) != 0 ||
442*3147Sxc151355 		    !isspace(str[nlen]))
443*3147Sxc151355 			return (B_TRUE);
444*3147Sxc151355 
445*3147Sxc151355 		sinfo.si_name = ssp->ss_info.si_name;
446*3147Sxc151355 	} else {
447*3147Sxc151355 		/*
448*3147Sxc151355 		 * If an object is not specified, find the object name
449*3147Sxc151355 		 * and assign it to sinfo.si_name.
450*3147Sxc151355 		 */
451*3147Sxc151355 		if (strtok_r(str, " \n\t", &lasts) == NULL)
452*3147Sxc151355 			goto fail;
453*3147Sxc151355 
454*3147Sxc151355 		nlen = strlen(str);
455*3147Sxc151355 		sinfo.si_name = str;
456*3147Sxc151355 	}
457*3147Sxc151355 	str += nlen + 1;
458*3147Sxc151355 	if (str >= buf + len)
459*3147Sxc151355 		goto fail;
460*3147Sxc151355 
461*3147Sxc151355 	/*
462*3147Sxc151355 	 * Find the class name.
463*3147Sxc151355 	 */
464*3147Sxc151355 	if ((str = strtok_r(str, " \n\t", &lasts)) == NULL)
465*3147Sxc151355 		goto fail;
466*3147Sxc151355 
467*3147Sxc151355 	*statusp = dladm_str2secobjclass(str, &class);
468*3147Sxc151355 	if (*statusp != DLADM_STATUS_OK)
469*3147Sxc151355 		goto fail;
470*3147Sxc151355 
471*3147Sxc151355 	/*
472*3147Sxc151355 	 * Find the object value.
473*3147Sxc151355 	 */
474*3147Sxc151355 	if ((str = strtok_r(NULL, " \n\t", &lasts)) == NULL)
475*3147Sxc151355 		goto fail;
476*3147Sxc151355 
477*3147Sxc151355 	vlen = DLADM_SECOBJ_VAL_MAX;
478*3147Sxc151355 	sinfo.si_classp = &class;
479*3147Sxc151355 	sinfo.si_val = val;
480*3147Sxc151355 	sinfo.si_lenp = &vlen;
481*3147Sxc151355 	if (parse_secobj_val(str, &sinfo) != 0)
482*3147Sxc151355 		goto fail;
483*3147Sxc151355 
484*3147Sxc151355 	return ((*ssp->ss_op)(ssp, buf, &sinfo, statusp));
485*3147Sxc151355 
486*3147Sxc151355 fail:
487*3147Sxc151355 	/*
488*3147Sxc151355 	 * Delete corrupted line.
489*3147Sxc151355 	 */
490*3147Sxc151355 	buf[0] = '\0';
491*3147Sxc151355 	return (B_TRUE);
492*3147Sxc151355 }
493*3147Sxc151355 
494*3147Sxc151355 static dladm_status_t
495*3147Sxc151355 process_secobj_db(void *arg, FILE *fp, FILE *nfp)
496*3147Sxc151355 {
497*3147Sxc151355 	secobj_db_state_t	*ssp = arg;
498*3147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
499*3147Sxc151355 	char			buf[MAXLINELEN];
500*3147Sxc151355 	boolean_t		cont = B_TRUE;
501*3147Sxc151355 
502*3147Sxc151355 	/*
503*3147Sxc151355 	 * This loop processes each line of the configuration file.
504*3147Sxc151355 	 * buf can potentially be modified by process_secobj_line().
505*3147Sxc151355 	 * If this is a write operation and buf is not truncated, buf will
506*3147Sxc151355 	 * be written to disk. process_secobj_line() will no longer be
507*3147Sxc151355 	 * called after it returns B_FALSE; at which point the remainder
508*3147Sxc151355 	 * of the file will continue to be read and, if necessary, written
509*3147Sxc151355 	 * to disk as well.
510*3147Sxc151355 	 */
511*3147Sxc151355 	while (fgets(buf, MAXLINELEN, fp) != NULL) {
512*3147Sxc151355 		if (cont)
513*3147Sxc151355 			cont = process_secobj_line(ssp, buf, &status);
514*3147Sxc151355 
515*3147Sxc151355 		if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) {
516*3147Sxc151355 			status = dladm_errno2status(errno);
517*3147Sxc151355 			break;
518*3147Sxc151355 		}
519*3147Sxc151355 	}
520*3147Sxc151355 	if (status != DLADM_STATUS_OK || !cont)
521*3147Sxc151355 		return (status);
522*3147Sxc151355 
523*3147Sxc151355 	if (ssp->ss_op == process_secobj_set) {
524*3147Sxc151355 		/*
525*3147Sxc151355 		 * If the specified object is not found above, we add the
526*3147Sxc151355 		 * object to the configuration file.
527*3147Sxc151355 		 */
528*3147Sxc151355 		(void) (*ssp->ss_op)(ssp, buf, NULL, &status);
529*3147Sxc151355 		if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF)
530*3147Sxc151355 			status = dladm_errno2status(errno);
531*3147Sxc151355 	}
532*3147Sxc151355 
533*3147Sxc151355 	if (ssp->ss_op == process_secobj_unset ||
534*3147Sxc151355 	    ssp->ss_op == process_secobj_get)
535*3147Sxc151355 		status = DLADM_STATUS_NOTFOUND;
536*3147Sxc151355 
537*3147Sxc151355 	return (status);
538*3147Sxc151355 }
539*3147Sxc151355 
540*3147Sxc151355 #define	SECOBJ_RW_DB(statep, writeop) \
541*3147Sxc151355 	(i_dladm_rw_db("/etc/dladm/secobj.conf", S_IRUSR | S_IWUSR, \
542*3147Sxc151355 	process_secobj_db, (statep), (writeop)))
543*3147Sxc151355 
544*3147Sxc151355 static dladm_status_t
545*3147Sxc151355 i_dladm_set_secobj_db(const char *obj_name, dladm_secobj_class_t class,
546*3147Sxc151355     uint8_t *obj_val, uint_t obj_len)
547*3147Sxc151355 {
548*3147Sxc151355 	secobj_db_state_t	state;
549*3147Sxc151355 
550*3147Sxc151355 	state.ss_op = process_secobj_set;
551*3147Sxc151355 	state.ss_info.si_name = obj_name;
552*3147Sxc151355 	state.ss_info.si_classp = &class;
553*3147Sxc151355 	state.ss_info.si_val = obj_val;
554*3147Sxc151355 	state.ss_info.si_lenp = &obj_len;
555*3147Sxc151355 	state.ss_namelist = NULL;
556*3147Sxc151355 
557*3147Sxc151355 	return (SECOBJ_RW_DB(&state, B_TRUE));
558*3147Sxc151355 }
559*3147Sxc151355 
560*3147Sxc151355 static dladm_status_t
561*3147Sxc151355 i_dladm_get_secobj_db(const char *obj_name, dladm_secobj_class_t *classp,
562*3147Sxc151355     uint8_t *obj_val, uint_t *obj_lenp)
563*3147Sxc151355 {
564*3147Sxc151355 	secobj_db_state_t	state;
565*3147Sxc151355 
566*3147Sxc151355 	state.ss_op = process_secobj_get;
567*3147Sxc151355 	state.ss_info.si_name = obj_name;
568*3147Sxc151355 	state.ss_info.si_classp = classp;
569*3147Sxc151355 	state.ss_info.si_val = obj_val;
570*3147Sxc151355 	state.ss_info.si_lenp = obj_lenp;
571*3147Sxc151355 	state.ss_namelist = NULL;
572*3147Sxc151355 
573*3147Sxc151355 	return (SECOBJ_RW_DB(&state, B_FALSE));
574*3147Sxc151355 }
575*3147Sxc151355 
576*3147Sxc151355 static dladm_status_t
577*3147Sxc151355 i_dladm_unset_secobj_db(const char *obj_name)
578*3147Sxc151355 {
579*3147Sxc151355 	secobj_db_state_t	state;
580*3147Sxc151355 
581*3147Sxc151355 	state.ss_op = process_secobj_unset;
582*3147Sxc151355 	state.ss_info.si_name = obj_name;
583*3147Sxc151355 	state.ss_info.si_classp = NULL;
584*3147Sxc151355 	state.ss_info.si_val = NULL;
585*3147Sxc151355 	state.ss_info.si_lenp = NULL;
586*3147Sxc151355 	state.ss_namelist = NULL;
587*3147Sxc151355 
588*3147Sxc151355 	return (SECOBJ_RW_DB(&state, B_TRUE));
589*3147Sxc151355 }
590*3147Sxc151355 
591*3147Sxc151355 static dladm_status_t
592*3147Sxc151355 i_dladm_walk_secobj_db(void *arg, boolean_t (*func)(void *, const char *))
593*3147Sxc151355 {
594*3147Sxc151355 	secobj_db_state_t	state;
595*3147Sxc151355 	secobj_name_t		*snp = NULL, *fsnp;
596*3147Sxc151355 	dladm_status_t		status;
597*3147Sxc151355 	boolean_t		cont = B_TRUE;
598*3147Sxc151355 
599*3147Sxc151355 	state.ss_op = process_secobj_walk;
600*3147Sxc151355 	state.ss_info.si_name = NULL;
601*3147Sxc151355 	state.ss_info.si_classp = NULL;
602*3147Sxc151355 	state.ss_info.si_val = NULL;
603*3147Sxc151355 	state.ss_info.si_lenp = NULL;
604*3147Sxc151355 	state.ss_namelist = &snp;
605*3147Sxc151355 
606*3147Sxc151355 	status = SECOBJ_RW_DB(&state, B_FALSE);
607*3147Sxc151355 	if (status != DLADM_STATUS_OK)
608*3147Sxc151355 		return (status);
609*3147Sxc151355 
610*3147Sxc151355 	while (snp != NULL) {
611*3147Sxc151355 		fsnp = snp;
612*3147Sxc151355 		snp = snp->sn_next;
613*3147Sxc151355 		if (cont)
614*3147Sxc151355 			cont = func(arg, fsnp->sn_name);
615*3147Sxc151355 		free(fsnp->sn_name);
616*3147Sxc151355 		free(fsnp);
617*3147Sxc151355 	}
618*3147Sxc151355 	return (status);
619*3147Sxc151355 }
620*3147Sxc151355 
621*3147Sxc151355 dladm_status_t
622*3147Sxc151355 dladm_init_secobj(void)
623*3147Sxc151355 {
624*3147Sxc151355 	secobj_db_state_t	state;
625*3147Sxc151355 
626*3147Sxc151355 	state.ss_op = process_secobj_init;
627*3147Sxc151355 	state.ss_info.si_name = NULL;
628*3147Sxc151355 	state.ss_info.si_classp = NULL;
629*3147Sxc151355 	state.ss_info.si_val = NULL;
630*3147Sxc151355 	state.ss_info.si_lenp = NULL;
631*3147Sxc151355 	state.ss_namelist = NULL;
632*3147Sxc151355 
633*3147Sxc151355 	return (SECOBJ_RW_DB(&state, B_FALSE));
634*3147Sxc151355 }
635