xref: /onnv-gate/usr/src/cmd/datadm/datadm.c (revision 12163:f0cf0084e756)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57354SGiri.Adari@Sun.COM  * Common Development and Distribution License (the "License").
67354SGiri.Adari@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12163SRamaswamy.Tummala@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <unistd.h>
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/socket.h>
280Sstevel@tonic-gate #include <sys/sockio.h>
29*12163SRamaswamy.Tummala@Sun.COM #include <sys/stat.h>
300Sstevel@tonic-gate #include <netinet/in.h>
310Sstevel@tonic-gate #include <arpa/inet.h>
320Sstevel@tonic-gate #include <net/if.h>
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <stdlib.h>
350Sstevel@tonic-gate #include <strings.h>
360Sstevel@tonic-gate #include <ctype.h>
370Sstevel@tonic-gate #include <errno.h>
380Sstevel@tonic-gate #include <libintl.h>
390Sstevel@tonic-gate #include <locale.h>
40*12163SRamaswamy.Tummala@Sun.COM #include <fcntl.h>
41*12163SRamaswamy.Tummala@Sun.COM #include <libdlpi.h>
42*12163SRamaswamy.Tummala@Sun.COM #include <libdladm.h>
43*12163SRamaswamy.Tummala@Sun.COM #include <libdlib.h>
44*12163SRamaswamy.Tummala@Sun.COM #include <libdllink.h>
45*12163SRamaswamy.Tummala@Sun.COM #include <sys/ib/ibnex/ibnex_devctl.h>
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #define	DATADM_OP_VIEW		0x0000
480Sstevel@tonic-gate #define	DATADM_OP_UPDATE	0x0001
490Sstevel@tonic-gate #define	DATADM_OP_ADD		0x0002
500Sstevel@tonic-gate #define	DATADM_OP_REMOVE	0x0003
510Sstevel@tonic-gate #define	DATADM_NUM_OPS		0x0004
520Sstevel@tonic-gate #define	DATADM_DAT_CONF		"/etc/dat/dat.conf"
530Sstevel@tonic-gate #define	DATADM_LINESZ		1024
540Sstevel@tonic-gate #define	DATADM_NUM_SP_TOKENS	7
550Sstevel@tonic-gate #define	DATADM_NUM_DAT_TOKENS	8
560Sstevel@tonic-gate #define	DATADM_DRV_NAME		"driver_name"
570Sstevel@tonic-gate #define	DATADM_MAX_TOKENS	16
580Sstevel@tonic-gate 
590Sstevel@tonic-gate /*
600Sstevel@tonic-gate  * generic entry
610Sstevel@tonic-gate  * placed at the top of all entry types
620Sstevel@tonic-gate  */
630Sstevel@tonic-gate typedef struct datadm_entry {
640Sstevel@tonic-gate 	struct datadm_entry	*de_next;
650Sstevel@tonic-gate } datadm_entry_t;
660Sstevel@tonic-gate 
670Sstevel@tonic-gate /*
680Sstevel@tonic-gate  * list structure
690Sstevel@tonic-gate  * can be manipulated using datadm_walk_list or
700Sstevel@tonic-gate  * datadm_enqueue_entry
710Sstevel@tonic-gate  */
720Sstevel@tonic-gate typedef struct datadm_list {
730Sstevel@tonic-gate 	datadm_entry_t		*dl_head;
740Sstevel@tonic-gate 	datadm_entry_t		*dl_tail;
750Sstevel@tonic-gate 	uint_t			dl_count;
760Sstevel@tonic-gate } datadm_list_t;
770Sstevel@tonic-gate 
780Sstevel@tonic-gate /*
790Sstevel@tonic-gate  * internal representation of the version string in
800Sstevel@tonic-gate  * dat.conf or service_provider.conf. the format is
810Sstevel@tonic-gate  * <dv_name><dv_major>.<dv_minor>
820Sstevel@tonic-gate  */
830Sstevel@tonic-gate typedef struct datadm_version {
840Sstevel@tonic-gate 	char	*dv_name;
850Sstevel@tonic-gate 	uint_t	dv_major;
860Sstevel@tonic-gate 	uint_t	dv_minor;
870Sstevel@tonic-gate } datadm_version_t;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate /*
900Sstevel@tonic-gate  * each sp_entry corresponds to an entry in dat.conf or
910Sstevel@tonic-gate  * service_provider.conf. an sp_entry is processed by the
920Sstevel@tonic-gate  * function datadm_process_sp_entry.
930Sstevel@tonic-gate  */
940Sstevel@tonic-gate typedef struct datadm_sp_entry {
950Sstevel@tonic-gate 	datadm_entry_t		spe_header;
960Sstevel@tonic-gate 	char			*spe_devname;
970Sstevel@tonic-gate 	datadm_version_t	spe_api_version;
980Sstevel@tonic-gate 	int			spe_threadsafe;
990Sstevel@tonic-gate 	int			spe_default;
1000Sstevel@tonic-gate 	char			*spe_libpath;
1010Sstevel@tonic-gate 	datadm_version_t	spe_sp_version;
1020Sstevel@tonic-gate 	char			*spe_sp_data;
1030Sstevel@tonic-gate 	int			spe_invalid;
1040Sstevel@tonic-gate } datadm_sp_entry_t;
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate /*
1070Sstevel@tonic-gate  * an hca_entry is created whenever a new hca device is
1080Sstevel@tonic-gate  * encountered during sp_entry processing. this structure
1090Sstevel@tonic-gate  * contains two lists. the sp_list holds sp entries that
1100Sstevel@tonic-gate  * are added when sp entry processing occurs. duplicate
1110Sstevel@tonic-gate  * sp entries are not added to this list. the ia_list may
1120Sstevel@tonic-gate  * be built statically using the information in dat.conf or
113*12163SRamaswamy.Tummala@Sun.COM  * dynamically. similar to the sp_list,
1140Sstevel@tonic-gate  * the ia_list contains only unique entries.
1150Sstevel@tonic-gate  */
1160Sstevel@tonic-gate typedef struct datadm_hca_entry {
1170Sstevel@tonic-gate 	datadm_entry_t		he_header;
1180Sstevel@tonic-gate 	char			*he_name;
1190Sstevel@tonic-gate 	datadm_list_t		he_sp_list;
1200Sstevel@tonic-gate 	datadm_list_t		he_ia_list;
1210Sstevel@tonic-gate } datadm_hca_entry_t;
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate /*
1240Sstevel@tonic-gate  * an ia_entry is created when a new ia name is encountered
1250Sstevel@tonic-gate  * during sp_entry processing or when a new ia name is
126*12163SRamaswamy.Tummala@Sun.COM  * discovered by datadm_build_ia_lists. ia_entry holds the ia
1270Sstevel@tonic-gate  * device's instance number.
1280Sstevel@tonic-gate  */
1290Sstevel@tonic-gate typedef struct datadm_ia_entry {
1300Sstevel@tonic-gate 	datadm_entry_t		iae_header;
131*12163SRamaswamy.Tummala@Sun.COM 	char			iae_name[MAXLINKNAMELEN];
1320Sstevel@tonic-gate } datadm_ia_entry_t;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate /*
1350Sstevel@tonic-gate  * a comment entry represents one of the comment lines at the
1360Sstevel@tonic-gate  * top of dat.conf. a list of these lines are saved during the
1370Sstevel@tonic-gate  * parsing of dat.conf. these lines are written back to dat.conf
1380Sstevel@tonic-gate  * when dat.conf gets regenerated.
1390Sstevel@tonic-gate  */
1400Sstevel@tonic-gate typedef struct datadm_cmnt_entry {
1410Sstevel@tonic-gate 	datadm_entry_t		cmnt_header;
1420Sstevel@tonic-gate 	char			*cmnt_line;
1430Sstevel@tonic-gate } datadm_cmnt_entry_t;
1440Sstevel@tonic-gate 
145*12163SRamaswamy.Tummala@Sun.COM typedef struct datadm_hca_find_by_name {
146*12163SRamaswamy.Tummala@Sun.COM 	char			*hf_name;
147*12163SRamaswamy.Tummala@Sun.COM 	datadm_hca_entry_t	*hf_hca_entry;
148*12163SRamaswamy.Tummala@Sun.COM } datadm_hca_find_by_name_t;
149*12163SRamaswamy.Tummala@Sun.COM 
1500Sstevel@tonic-gate /*
1510Sstevel@tonic-gate  * 2nd argument to datadm_hca_entry_find.
1520Sstevel@tonic-gate  * hf_hca_entry is filled in if an hca_entry with
1530Sstevel@tonic-gate  * a matching he_name is found.
1540Sstevel@tonic-gate  */
1550Sstevel@tonic-gate typedef struct datadm_hca_find {
1560Sstevel@tonic-gate 	datadm_sp_entry_t	*hf_sp_entry;
1570Sstevel@tonic-gate 	datadm_hca_entry_t	*hf_hca_entry;
1580Sstevel@tonic-gate } datadm_hca_find_t;
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate /*
1610Sstevel@tonic-gate  * 2nd argument to datadm_ia_entry_find.
1620Sstevel@tonic-gate  * if_ia_entry is filled in if an ia_entry with
163*12163SRamaswamy.Tummala@Sun.COM  * a matching ia_name is found.
1640Sstevel@tonic-gate  */
1650Sstevel@tonic-gate typedef struct datadm_ia_find {
166*12163SRamaswamy.Tummala@Sun.COM 	char			*if_ia_name;
1670Sstevel@tonic-gate 	datadm_ia_entry_t	*if_ia_entry;
1680Sstevel@tonic-gate } datadm_ia_find_t;
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate /*
171*12163SRamaswamy.Tummala@Sun.COM  * this gets passed to datadm_add_plink.
1720Sstevel@tonic-gate  */
1730Sstevel@tonic-gate typedef struct datadm_fill_ia_list {
174*12163SRamaswamy.Tummala@Sun.COM 	datadm_list_t		*ia_hca_list;
175*12163SRamaswamy.Tummala@Sun.COM 	dladm_handle_t		ia_dlh;
176*12163SRamaswamy.Tummala@Sun.COM 	int			ia_ibnex_fd;
1770Sstevel@tonic-gate 	int			ia_sock_fd_v4;
1780Sstevel@tonic-gate 	int			ia_sock_fd_v6;
1790Sstevel@tonic-gate } datadm_fill_ia_list_t;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate /*
1820Sstevel@tonic-gate  * this defines the commandline parameters specified
1830Sstevel@tonic-gate  * by the user.
1840Sstevel@tonic-gate  */
1850Sstevel@tonic-gate typedef struct datadm_args {
1860Sstevel@tonic-gate 	char			*da_sp_conf;
1870Sstevel@tonic-gate 	char			*da_dat_conf;
1880Sstevel@tonic-gate 	int			da_op_type;
1890Sstevel@tonic-gate } datadm_args_t;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate static datadm_args_t		datadm_args;
1920Sstevel@tonic-gate static datadm_list_t		datadm_conf_header;
1930Sstevel@tonic-gate static char			*datadm_conf_header_default =
1940Sstevel@tonic-gate 	"#\n"
195*12163SRamaswamy.Tummala@Sun.COM 	"# Copyright (c) 2003, 2010, Oracle and/or its affiliates. "
196*12163SRamaswamy.Tummala@Sun.COM 	"All rights reserved.\n"
1970Sstevel@tonic-gate 	"#\n"
1980Sstevel@tonic-gate 	"# DAT configuration file.\n"
1990Sstevel@tonic-gate 	"#\n"
2000Sstevel@tonic-gate 	"# This file is updated using the datadm(1) command.\n"
2010Sstevel@tonic-gate 	"# Do not hand edit this file.\n"
2020Sstevel@tonic-gate 	"# See datadm(1) man page for more details.\n"
2030Sstevel@tonic-gate 	"#\n"
2040Sstevel@tonic-gate 	"# The fields in this file are -\n"
2050Sstevel@tonic-gate 	"#\n"
2060Sstevel@tonic-gate 	"# IAname version threadsafe default library-path provider-version \\\n"
2070Sstevel@tonic-gate 	"# instance-data platform-information\n"
2080Sstevel@tonic-gate 	"#\n";
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate /*
2110Sstevel@tonic-gate  * common parsing functions.
2120Sstevel@tonic-gate  */
2130Sstevel@tonic-gate typedef int (*datadm_parse_func_t)(char *, void *);
2140Sstevel@tonic-gate static int datadm_parse_line(char *, char *[], int *);
2150Sstevel@tonic-gate static int datadm_parse_generic_str(char *, char **);
2160Sstevel@tonic-gate static int datadm_parse_nonnull_str(char *, char **);
2170Sstevel@tonic-gate static int datadm_parse_version(char *, datadm_version_t *);
2180Sstevel@tonic-gate static int datadm_parse_devname(char *, datadm_sp_entry_t *);
2190Sstevel@tonic-gate static int datadm_parse_api_version(char *, datadm_sp_entry_t *);
2200Sstevel@tonic-gate static int datadm_parse_threadsafe(char *, datadm_sp_entry_t *);
2210Sstevel@tonic-gate static int datadm_parse_default(char *, datadm_sp_entry_t *);
2220Sstevel@tonic-gate static int datadm_parse_libpath(char *, datadm_sp_entry_t *);
2230Sstevel@tonic-gate static int datadm_parse_sp_version(char *, datadm_sp_entry_t *);
2240Sstevel@tonic-gate static int datadm_parse_sp_data(char *, datadm_sp_entry_t *);
225*12163SRamaswamy.Tummala@Sun.COM static int datadm_parse_ia_name(char *, char *);
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate /*
2280Sstevel@tonic-gate  * utility functions
2290Sstevel@tonic-gate  */
2300Sstevel@tonic-gate static void datadm_enqueue_entry(datadm_list_t *, datadm_entry_t *);
2310Sstevel@tonic-gate static int datadm_walk_list(datadm_list_t *,
2320Sstevel@tonic-gate     int (*)(datadm_entry_t *, void *), void *);
2330Sstevel@tonic-gate static int datadm_str_match(char *, char *);
2340Sstevel@tonic-gate static int datadm_version_match(datadm_version_t *, datadm_version_t *);
2350Sstevel@tonic-gate static int datadm_sp_entry_match(datadm_sp_entry_t *, datadm_sp_entry_t *);
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate  * entry allocation/deallocation
2390Sstevel@tonic-gate  */
2400Sstevel@tonic-gate static datadm_sp_entry_t *datadm_alloc_sp_entry(void);
2410Sstevel@tonic-gate static datadm_ia_entry_t *datadm_alloc_ia_entry(void);
2420Sstevel@tonic-gate static datadm_hca_entry_t *datadm_alloc_hca_entry(void);
2430Sstevel@tonic-gate static datadm_cmnt_entry_t *datadm_alloc_cmnt_entry(void);
2440Sstevel@tonic-gate static void datadm_free_sp_entry(datadm_sp_entry_t *);
2450Sstevel@tonic-gate static void datadm_free_ia_entry(datadm_ia_entry_t *);
2460Sstevel@tonic-gate static void datadm_free_hca_entry(datadm_hca_entry_t *);
2470Sstevel@tonic-gate static void datadm_free_cmnt_entry(datadm_cmnt_entry_t *);
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate /*
2510Sstevel@tonic-gate  * high level parsing functions
2520Sstevel@tonic-gate  */
2530Sstevel@tonic-gate static int datadm_parse_sp_conf(datadm_list_t *);
2540Sstevel@tonic-gate static int datadm_parse_dat_conf(datadm_list_t *);
255*12163SRamaswamy.Tummala@Sun.COM static int datadm_process_sp_entry(datadm_list_t *, datadm_sp_entry_t *,
256*12163SRamaswamy.Tummala@Sun.COM     char *);
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate /*
2590Sstevel@tonic-gate  * ia devices discovery
2600Sstevel@tonic-gate  */
2610Sstevel@tonic-gate static int datadm_build_ia_lists(datadm_list_t *);
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate /*
2640Sstevel@tonic-gate  * helper function for OP_REMOVE
2650Sstevel@tonic-gate  */
2660Sstevel@tonic-gate static void datadm_invalidate_common_sp_entries(datadm_list_t *,
2670Sstevel@tonic-gate     datadm_list_t *);
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate /*
2700Sstevel@tonic-gate  * output generation
2710Sstevel@tonic-gate  */
2720Sstevel@tonic-gate static int datadm_generate_dat_conf(datadm_list_t *);
2730Sstevel@tonic-gate static int datadm_generate_conf_header(FILE *);
2740Sstevel@tonic-gate static int datadm_generate_conf_entry(FILE *, datadm_ia_entry_t *,
2750Sstevel@tonic-gate     datadm_sp_entry_t *);
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate /*
2780Sstevel@tonic-gate  * datadm operations
2790Sstevel@tonic-gate  */
2800Sstevel@tonic-gate static int datadm_view(void);
2810Sstevel@tonic-gate static int datadm_update(void);
2820Sstevel@tonic-gate static int datadm_add(void);
2830Sstevel@tonic-gate static int datadm_remove(void);
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate /*
2860Sstevel@tonic-gate  * usage
2870Sstevel@tonic-gate  */
2880Sstevel@tonic-gate static void datadm_usage(void);
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate /*
2920Sstevel@tonic-gate  * parse function tables
2930Sstevel@tonic-gate  */
2940Sstevel@tonic-gate static datadm_parse_func_t datadm_sp_parse_funcs[DATADM_NUM_SP_TOKENS] = {
2950Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_devname,
2960Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_api_version,
2970Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_threadsafe,
2980Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_default,
2990Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_libpath,
3000Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_sp_version,
3010Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_sp_data
3020Sstevel@tonic-gate };
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate static datadm_parse_func_t datadm_dat_parse_funcs[DATADM_NUM_DAT_TOKENS] = {
3050Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_ia_name,
3060Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_api_version,
3070Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_threadsafe,
3080Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_default,
3090Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_libpath,
3100Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_sp_version,
3110Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_sp_data,
3120Sstevel@tonic-gate 	(datadm_parse_func_t)datadm_parse_devname
3130Sstevel@tonic-gate };
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate /*
3160Sstevel@tonic-gate  * operation table
3170Sstevel@tonic-gate  */
3180Sstevel@tonic-gate static int (*datadm_ops[DATADM_NUM_OPS])(void) = {
3190Sstevel@tonic-gate 	datadm_view,
3200Sstevel@tonic-gate 	datadm_update,
3210Sstevel@tonic-gate 	datadm_add,
3220Sstevel@tonic-gate 	datadm_remove
3230Sstevel@tonic-gate };
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate static void
datadm_usage(void)3260Sstevel@tonic-gate datadm_usage(void)
3270Sstevel@tonic-gate {
3280Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
3290Sstevel@tonic-gate 	    "usage: datadm -v\n"
3300Sstevel@tonic-gate 	    "              -u\n"
3310Sstevel@tonic-gate 	    "              -a <service_provider.conf>\n"
3320Sstevel@tonic-gate 	    "              -r <service_provider.conf>\n"));
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate static int
datadm_parse_generic_str(char * str,char ** strptr)3360Sstevel@tonic-gate datadm_parse_generic_str(char *str, char **strptr)
3370Sstevel@tonic-gate {
3380Sstevel@tonic-gate 	int	len;
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	len = strlen(str);
3410Sstevel@tonic-gate 	*strptr = (char *)malloc(len + 1);
3420Sstevel@tonic-gate 	if (*strptr == NULL) {
3430Sstevel@tonic-gate 		return (-1);
3440Sstevel@tonic-gate 	}
3450Sstevel@tonic-gate 	(void) strcpy(*strptr, str);
3460Sstevel@tonic-gate 	return (0);
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate /*
3500Sstevel@tonic-gate  * this function strips off leading and trailing
3510Sstevel@tonic-gate  * whitespaces and returns an error for null or
3520Sstevel@tonic-gate  * empty strings.
3530Sstevel@tonic-gate  */
3540Sstevel@tonic-gate static int
datadm_parse_nonnull_str(char * str,char ** strptr)3550Sstevel@tonic-gate datadm_parse_nonnull_str(char *str, char **strptr)
3560Sstevel@tonic-gate {
3570Sstevel@tonic-gate 	int	len, i;
3580Sstevel@tonic-gate 	char	*start;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	if (str[0] == '\0') {
3610Sstevel@tonic-gate 		return (-1);
3620Sstevel@tonic-gate 	}
3630Sstevel@tonic-gate 	start = str;
3640Sstevel@tonic-gate 	for (i = 0; str[i] != '\0'; i++) {
3650Sstevel@tonic-gate 		if (!isspace(str[i])) {
3660Sstevel@tonic-gate 			start = &str[i];
3670Sstevel@tonic-gate 			break;
3680Sstevel@tonic-gate 		}
3690Sstevel@tonic-gate 	}
3700Sstevel@tonic-gate 	for (; str[i] != '\0'; i++) {
3710Sstevel@tonic-gate 		if (isspace(str[i])) {
3720Sstevel@tonic-gate 			str[i] = '\0';
3730Sstevel@tonic-gate 		}
3740Sstevel@tonic-gate 	}
3750Sstevel@tonic-gate 	len = strlen(start);
3760Sstevel@tonic-gate 	*strptr = (char *)malloc(len + 1);
3770Sstevel@tonic-gate 	if (*strptr == NULL) {
3780Sstevel@tonic-gate 		return (-1);
3790Sstevel@tonic-gate 	}
3800Sstevel@tonic-gate 	(void) strcpy(*strptr, start);
3810Sstevel@tonic-gate 	return (0);
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate /*
3850Sstevel@tonic-gate  * parses the api_version and sp_version fields in
3860Sstevel@tonic-gate  * dat.conf and service_provider.conf
3870Sstevel@tonic-gate  */
3880Sstevel@tonic-gate static int
datadm_parse_version(char * str,datadm_version_t * version)3890Sstevel@tonic-gate datadm_parse_version(char *str, datadm_version_t *version)
3900Sstevel@tonic-gate {
3910Sstevel@tonic-gate 	int	i = 0, len;
3920Sstevel@tonic-gate 	int	major_idx, minor_idx;
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 	len = strlen(str);
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
3970Sstevel@tonic-gate 		if (isdigit(str[i])) break;
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate 	if (i == len) {
4000Sstevel@tonic-gate 		return (-1);
4010Sstevel@tonic-gate 	}
4020Sstevel@tonic-gate 	if (i > 0) {
4030Sstevel@tonic-gate 		version->dv_name = (char *)malloc(i + 1);
4040Sstevel@tonic-gate 		bcopy(str, version->dv_name, i);
4050Sstevel@tonic-gate 		version->dv_name[i] = '\0';
4060Sstevel@tonic-gate 	} else {
4070Sstevel@tonic-gate 		version->dv_name = NULL;
4080Sstevel@tonic-gate 	}
4090Sstevel@tonic-gate 	major_idx = i;
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	for (; i < len; i++) {
4120Sstevel@tonic-gate 		if (!isdigit(str[i])) break;
4130Sstevel@tonic-gate 	}
4140Sstevel@tonic-gate 	if (i == len) {
4150Sstevel@tonic-gate 		return (-1);
4160Sstevel@tonic-gate 	}
4170Sstevel@tonic-gate 	if (str[i] != '.') {
4180Sstevel@tonic-gate 		return (-1);
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 	minor_idx = ++i;
4210Sstevel@tonic-gate 	if (i == len) {
4220Sstevel@tonic-gate 		return (-1);
4230Sstevel@tonic-gate 	}
4240Sstevel@tonic-gate 	for (; i < len; i++) {
4250Sstevel@tonic-gate 		if (!isdigit(str[i])) break;
4260Sstevel@tonic-gate 	}
4270Sstevel@tonic-gate 	if (i != len) {
4280Sstevel@tonic-gate 		return (-1);
4290Sstevel@tonic-gate 	}
4300Sstevel@tonic-gate 	version->dv_major = atoi(str + major_idx);
4310Sstevel@tonic-gate 	version->dv_minor = atoi(str + minor_idx);
4320Sstevel@tonic-gate 	return (0);
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate /*
4360Sstevel@tonic-gate  * parses the ia_name field in dat.conf
4370Sstevel@tonic-gate  */
4380Sstevel@tonic-gate static int
datadm_parse_ia_name(char * str,char * ia_name)439*12163SRamaswamy.Tummala@Sun.COM datadm_parse_ia_name(char *str, char *ia_name)
4400Sstevel@tonic-gate {
441*12163SRamaswamy.Tummala@Sun.COM 	if (strlen(str) >= MAXLINKNAMELEN)
4420Sstevel@tonic-gate 		return (-1);
443*12163SRamaswamy.Tummala@Sun.COM 	(void) strlcpy(ia_name, str, MAXLINKNAMELEN);
4440Sstevel@tonic-gate 	return (0);
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate /*
4480Sstevel@tonic-gate  * parses the device name, strips leading and trailing spaces.
4490Sstevel@tonic-gate  * the format should be "driver_name=<dev_name>"
4500Sstevel@tonic-gate  */
4510Sstevel@tonic-gate static int
datadm_parse_devname(char * str,datadm_sp_entry_t * sp_entry)4520Sstevel@tonic-gate datadm_parse_devname(char *str, datadm_sp_entry_t *sp_entry)
4530Sstevel@tonic-gate {
4540Sstevel@tonic-gate 	int	len, dlen, i, j = 0;
4550Sstevel@tonic-gate 	char	*drv_name = DATADM_DRV_NAME;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	len = strlen(str);
4580Sstevel@tonic-gate 	dlen = strlen(drv_name);
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	/*
4610Sstevel@tonic-gate 	 * strip out leading spaces and try to match
4620Sstevel@tonic-gate 	 * the expected string
4630Sstevel@tonic-gate 	 */
4640Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
4650Sstevel@tonic-gate 		if (isspace(str[i]) && j == 0) {
4660Sstevel@tonic-gate 			continue;
4670Sstevel@tonic-gate 		} else {
4680Sstevel@tonic-gate 			if (str[i] == drv_name[j]) {
4690Sstevel@tonic-gate 				j++;
4700Sstevel@tonic-gate 				if (j == dlen) {
4710Sstevel@tonic-gate 					break;
4720Sstevel@tonic-gate 				} else {
4730Sstevel@tonic-gate 					continue;
4740Sstevel@tonic-gate 				}
4750Sstevel@tonic-gate 			} else {
4760Sstevel@tonic-gate 				break;
4770Sstevel@tonic-gate 			}
4780Sstevel@tonic-gate 		}
4790Sstevel@tonic-gate 	}
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	/*
4820Sstevel@tonic-gate 	 * j must be dlen if the matching string is found
4830Sstevel@tonic-gate 	 */
4840Sstevel@tonic-gate 	if (j != dlen) {
4850Sstevel@tonic-gate 		return (-1);
4860Sstevel@tonic-gate 	}
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	/*
4890Sstevel@tonic-gate 	 * skip past the last char of drv_name
4900Sstevel@tonic-gate 	 */
4910Sstevel@tonic-gate 	i++;
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 	/*
4940Sstevel@tonic-gate 	 * strip the spaces before the '='
4950Sstevel@tonic-gate 	 */
4960Sstevel@tonic-gate 	for (; i < len; i++) {
4970Sstevel@tonic-gate 		if (!isspace(str[i])) {
4980Sstevel@tonic-gate 			break;
4990Sstevel@tonic-gate 		}
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	/*
5030Sstevel@tonic-gate 	 * return if the string is too long or if
5040Sstevel@tonic-gate 	 * the '=' isn't found
5050Sstevel@tonic-gate 	 */
5060Sstevel@tonic-gate 	if (i >= len || str[i] != '=') {
5070Sstevel@tonic-gate 		return (-1);
5080Sstevel@tonic-gate 	}
5090Sstevel@tonic-gate 	i++;
5100Sstevel@tonic-gate 	if (i >= len) {
5110Sstevel@tonic-gate 		/*
5120Sstevel@tonic-gate 		 * no string after the equal
5130Sstevel@tonic-gate 		 */
5140Sstevel@tonic-gate 		return (-1);
5150Sstevel@tonic-gate 	}
5160Sstevel@tonic-gate 	return (datadm_parse_nonnull_str(str + i, &sp_entry->spe_devname));
5170Sstevel@tonic-gate }
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate static int
datadm_parse_api_version(char * str,datadm_sp_entry_t * sp_entry)5200Sstevel@tonic-gate datadm_parse_api_version(char *str, datadm_sp_entry_t *sp_entry)
5210Sstevel@tonic-gate {
5220Sstevel@tonic-gate 	return (datadm_parse_version(str, &sp_entry->spe_api_version));
5230Sstevel@tonic-gate }
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate static int
datadm_parse_threadsafe(char * str,datadm_sp_entry_t * sp_entry)5260Sstevel@tonic-gate datadm_parse_threadsafe(char *str, datadm_sp_entry_t *sp_entry)
5270Sstevel@tonic-gate {
5280Sstevel@tonic-gate 	int retval = 0;
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	if (strcmp(str, "threadsafe") == 0) {
5310Sstevel@tonic-gate 		sp_entry->spe_threadsafe = 1;
5320Sstevel@tonic-gate 	} else if (strcmp(str, "nonthreadsafe") == 0) {
5330Sstevel@tonic-gate 		sp_entry->spe_threadsafe = 0;
5340Sstevel@tonic-gate 	} else {
5350Sstevel@tonic-gate 		retval = -1;
5360Sstevel@tonic-gate 	}
5370Sstevel@tonic-gate 	return (retval);
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate static int
datadm_parse_default(char * str,datadm_sp_entry_t * sp_entry)5410Sstevel@tonic-gate datadm_parse_default(char *str, datadm_sp_entry_t *sp_entry)
5420Sstevel@tonic-gate {
5430Sstevel@tonic-gate 	int retval = 0;
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 	if (strcmp(str, "default") == 0) {
5460Sstevel@tonic-gate 		sp_entry->spe_default = 1;
5470Sstevel@tonic-gate 	} else if (strcmp(str, "nondefault") == 0) {
5480Sstevel@tonic-gate 		sp_entry->spe_default = 0;
5490Sstevel@tonic-gate 	} else {
5500Sstevel@tonic-gate 		retval = -1;
5510Sstevel@tonic-gate 	}
5520Sstevel@tonic-gate 	return (retval);
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate static int
datadm_parse_libpath(char * str,datadm_sp_entry_t * sp_entry)5560Sstevel@tonic-gate datadm_parse_libpath(char *str, datadm_sp_entry_t *sp_entry)
5570Sstevel@tonic-gate {
5580Sstevel@tonic-gate 	return (datadm_parse_nonnull_str(str, &sp_entry->spe_libpath));
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate static int
datadm_parse_sp_version(char * str,datadm_sp_entry_t * sp_entry)5620Sstevel@tonic-gate datadm_parse_sp_version(char *str, datadm_sp_entry_t *sp_entry)
5630Sstevel@tonic-gate {
5640Sstevel@tonic-gate 	return (datadm_parse_version(str, &sp_entry->spe_sp_version));
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate static int
datadm_parse_sp_data(char * str,datadm_sp_entry_t * sp_entry)5680Sstevel@tonic-gate datadm_parse_sp_data(char *str, datadm_sp_entry_t *sp_entry)
5690Sstevel@tonic-gate {
5700Sstevel@tonic-gate 	return (datadm_parse_generic_str(str, &sp_entry->spe_sp_data));
5710Sstevel@tonic-gate }
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate static void
datadm_enqueue_entry(datadm_list_t * list,datadm_entry_t * entry)5740Sstevel@tonic-gate datadm_enqueue_entry(datadm_list_t *list, datadm_entry_t *entry)
5750Sstevel@tonic-gate {
5760Sstevel@tonic-gate 	if (list->dl_head == NULL) {
5770Sstevel@tonic-gate 		list->dl_head = entry;
5780Sstevel@tonic-gate 		list->dl_tail = entry;
5790Sstevel@tonic-gate 		list->dl_count = 1;
5800Sstevel@tonic-gate 	} else {
5810Sstevel@tonic-gate 		list->dl_tail->de_next = entry;
5820Sstevel@tonic-gate 		list->dl_tail = entry;
5830Sstevel@tonic-gate 		list->dl_count++;
5840Sstevel@tonic-gate 	}
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate /*
5880Sstevel@tonic-gate  * iterates through the list applying func on each element.
5890Sstevel@tonic-gate  * break and return if func returns non-zero.
5900Sstevel@tonic-gate  */
5910Sstevel@tonic-gate static int
datadm_walk_list(datadm_list_t * list,int (* func)(datadm_entry_t *,void *),void * arg)5920Sstevel@tonic-gate datadm_walk_list(datadm_list_t *list, int (*func)(datadm_entry_t *, void *),
5930Sstevel@tonic-gate 	void *arg)
5940Sstevel@tonic-gate {
5950Sstevel@tonic-gate 	datadm_entry_t	*entry;
5960Sstevel@tonic-gate 	int		retval = 0;
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	entry = list->dl_head;
5990Sstevel@tonic-gate 	while (entry != NULL) {
6000Sstevel@tonic-gate 		retval = (*func)(entry, arg);
6010Sstevel@tonic-gate 		if (retval != 0) break;
6020Sstevel@tonic-gate 		entry = entry->de_next;
6030Sstevel@tonic-gate 	}
6040Sstevel@tonic-gate 	return (retval);
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate /*
6080Sstevel@tonic-gate  * iterates through the list applying free_func to each element.
6090Sstevel@tonic-gate  * list becomes empty when the function returns.
6100Sstevel@tonic-gate  */
6110Sstevel@tonic-gate static void
datadm_free_list(datadm_list_t * list,void (* free_func)(datadm_entry_t *))6120Sstevel@tonic-gate datadm_free_list(datadm_list_t *list, void (*free_func)(datadm_entry_t *))
6130Sstevel@tonic-gate {
6140Sstevel@tonic-gate 	while (list->dl_head != NULL) {
6150Sstevel@tonic-gate 		datadm_entry_t	*entry;
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 		entry = list->dl_head;
6180Sstevel@tonic-gate 		list->dl_head = entry->de_next;
6190Sstevel@tonic-gate 		(*free_func)(entry);
6200Sstevel@tonic-gate 	}
6210Sstevel@tonic-gate 	list->dl_count = 0;
6220Sstevel@tonic-gate 	list->dl_tail = NULL;
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate static datadm_sp_entry_t *
datadm_alloc_sp_entry(void)6260Sstevel@tonic-gate datadm_alloc_sp_entry(void)
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate 	datadm_sp_entry_t	*sp_entry;
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate 	sp_entry = (datadm_sp_entry_t *)malloc(sizeof (*sp_entry));
6310Sstevel@tonic-gate 	if (sp_entry == NULL) {
6320Sstevel@tonic-gate 		return (NULL);
6330Sstevel@tonic-gate 	}
6340Sstevel@tonic-gate 	bzero(sp_entry, sizeof (*sp_entry));
6350Sstevel@tonic-gate 	return (sp_entry);
6360Sstevel@tonic-gate }
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate static void
datadm_free_sp_entry(datadm_sp_entry_t * sp_entry)6390Sstevel@tonic-gate datadm_free_sp_entry(datadm_sp_entry_t *sp_entry)
6400Sstevel@tonic-gate {
6410Sstevel@tonic-gate 	if (sp_entry->spe_devname != NULL) {
6420Sstevel@tonic-gate 		free(sp_entry->spe_devname);
6430Sstevel@tonic-gate 		sp_entry->spe_devname = NULL;
6440Sstevel@tonic-gate 	}
6450Sstevel@tonic-gate 	if (sp_entry->spe_api_version.dv_name != NULL) {
6460Sstevel@tonic-gate 		free(sp_entry->spe_api_version.dv_name);
6470Sstevel@tonic-gate 		sp_entry->spe_api_version.dv_name = NULL;
6480Sstevel@tonic-gate 	}
6490Sstevel@tonic-gate 	sp_entry->spe_api_version.dv_major = 0;
6500Sstevel@tonic-gate 	sp_entry->spe_api_version.dv_minor = 0;
6510Sstevel@tonic-gate 	sp_entry->spe_threadsafe = 0;
6520Sstevel@tonic-gate 	sp_entry->spe_default = 0;
6530Sstevel@tonic-gate 	if (sp_entry->spe_libpath != NULL) {
6540Sstevel@tonic-gate 		free(sp_entry->spe_libpath);
6550Sstevel@tonic-gate 		sp_entry->spe_libpath = NULL;
6560Sstevel@tonic-gate 	}
6570Sstevel@tonic-gate 	if (sp_entry->spe_sp_version.dv_name != NULL) {
6580Sstevel@tonic-gate 		free(sp_entry->spe_sp_version.dv_name);
6590Sstevel@tonic-gate 		sp_entry->spe_sp_version.dv_name = NULL;
6600Sstevel@tonic-gate 	}
6610Sstevel@tonic-gate 	sp_entry->spe_sp_version.dv_major = 0;
6620Sstevel@tonic-gate 	sp_entry->spe_sp_version.dv_minor = 0;
6630Sstevel@tonic-gate 	if (sp_entry->spe_sp_data != NULL) {
6640Sstevel@tonic-gate 		free(sp_entry->spe_sp_data);
6650Sstevel@tonic-gate 		sp_entry->spe_sp_data = NULL;
6660Sstevel@tonic-gate 	}
6670Sstevel@tonic-gate 	free(sp_entry);
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate static int
datadm_str_match(char * s1,char * s2)6710Sstevel@tonic-gate datadm_str_match(char *s1, char *s2)
6720Sstevel@tonic-gate {
6730Sstevel@tonic-gate 	if (s1 == NULL || s2 == NULL) {
6740Sstevel@tonic-gate 		if (s1 != s2) {
6750Sstevel@tonic-gate 			return (0);
6760Sstevel@tonic-gate 		}
6770Sstevel@tonic-gate 	} else {
6780Sstevel@tonic-gate 		if (strcmp(s1, s2) != 0) {
6790Sstevel@tonic-gate 			return (0);
6800Sstevel@tonic-gate 		}
6810Sstevel@tonic-gate 	}
6820Sstevel@tonic-gate 	return (1);
6830Sstevel@tonic-gate }
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate static int
datadm_version_match(datadm_version_t * v1,datadm_version_t * v2)6860Sstevel@tonic-gate datadm_version_match(datadm_version_t *v1, datadm_version_t *v2)
6870Sstevel@tonic-gate {
6880Sstevel@tonic-gate 	if (!datadm_str_match(v1->dv_name, v2->dv_name)) {
6890Sstevel@tonic-gate 		return (0);
6900Sstevel@tonic-gate 	}
6910Sstevel@tonic-gate 	if (v1->dv_major != v2->dv_major) {
6920Sstevel@tonic-gate 		return (0);
6930Sstevel@tonic-gate 	}
6940Sstevel@tonic-gate 	if (v1->dv_minor != v2->dv_minor) {
6950Sstevel@tonic-gate 		return (0);
6960Sstevel@tonic-gate 	}
6970Sstevel@tonic-gate 	return (1);
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate static int
datadm_sp_entry_match(datadm_sp_entry_t * sp1,datadm_sp_entry_t * sp2)7010Sstevel@tonic-gate datadm_sp_entry_match(datadm_sp_entry_t *sp1, datadm_sp_entry_t *sp2)
7020Sstevel@tonic-gate {
7030Sstevel@tonic-gate 	if (!datadm_str_match(sp1->spe_devname, sp2->spe_devname)) {
7040Sstevel@tonic-gate 		return (0);
7050Sstevel@tonic-gate 	}
7060Sstevel@tonic-gate 	if (!datadm_version_match(&sp1->spe_api_version,
7070Sstevel@tonic-gate 	    &sp2->spe_api_version)) {
7080Sstevel@tonic-gate 		return (0);
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate 	if (sp1->spe_threadsafe != sp2->spe_threadsafe) {
7110Sstevel@tonic-gate 		return (0);
7120Sstevel@tonic-gate 	}
7130Sstevel@tonic-gate 	if (sp2->spe_default != sp2->spe_default) {
7140Sstevel@tonic-gate 		return (0);
7150Sstevel@tonic-gate 	}
7160Sstevel@tonic-gate 	if (!datadm_str_match(sp1->spe_libpath, sp2->spe_libpath)) {
7170Sstevel@tonic-gate 		return (0);
7180Sstevel@tonic-gate 	}
7190Sstevel@tonic-gate 	if (!datadm_version_match(&sp1->spe_sp_version,
7200Sstevel@tonic-gate 	    &sp2->spe_sp_version)) {
7210Sstevel@tonic-gate 		return (0);
7220Sstevel@tonic-gate 	}
7230Sstevel@tonic-gate 	if (!datadm_str_match(sp1->spe_sp_data, sp2->spe_sp_data)) {
7240Sstevel@tonic-gate 		return (0);
7250Sstevel@tonic-gate 	}
7260Sstevel@tonic-gate 	return (1);
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate static datadm_ia_entry_t *
datadm_alloc_ia_entry(void)7300Sstevel@tonic-gate datadm_alloc_ia_entry(void)
7310Sstevel@tonic-gate {
7320Sstevel@tonic-gate 	datadm_ia_entry_t	*ia_entry;
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	ia_entry = (datadm_ia_entry_t *)malloc(sizeof (*ia_entry));
7350Sstevel@tonic-gate 	if (ia_entry == NULL) {
7360Sstevel@tonic-gate 		return (NULL);
7370Sstevel@tonic-gate 	}
7380Sstevel@tonic-gate 	bzero(ia_entry, sizeof (*ia_entry));
7390Sstevel@tonic-gate 	return (ia_entry);
7400Sstevel@tonic-gate }
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate static void
datadm_free_ia_entry(datadm_ia_entry_t * ia_entry)7430Sstevel@tonic-gate datadm_free_ia_entry(datadm_ia_entry_t *ia_entry)
7440Sstevel@tonic-gate {
7450Sstevel@tonic-gate 	free(ia_entry);
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate static datadm_hca_entry_t *
datadm_alloc_hca_entry(void)7490Sstevel@tonic-gate datadm_alloc_hca_entry(void)
7500Sstevel@tonic-gate {
7510Sstevel@tonic-gate 	datadm_hca_entry_t	*hca_entry;
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 	hca_entry = (datadm_hca_entry_t *)malloc(sizeof (*hca_entry));
7540Sstevel@tonic-gate 	if (hca_entry == NULL) {
7550Sstevel@tonic-gate 		return (NULL);
7560Sstevel@tonic-gate 	}
7570Sstevel@tonic-gate 	bzero(hca_entry, sizeof (*hca_entry));
7580Sstevel@tonic-gate 	return (hca_entry);
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate static void
datadm_free_hca_entry(datadm_hca_entry_t * hca_entry)7620Sstevel@tonic-gate datadm_free_hca_entry(datadm_hca_entry_t *hca_entry)
7630Sstevel@tonic-gate {
7640Sstevel@tonic-gate 	if (hca_entry->he_name != NULL) {
7650Sstevel@tonic-gate 		free(hca_entry->he_name);
7660Sstevel@tonic-gate 		hca_entry->he_name = NULL;
7670Sstevel@tonic-gate 	}
7680Sstevel@tonic-gate 	datadm_free_list(&hca_entry->he_sp_list,
7690Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_sp_entry);
7700Sstevel@tonic-gate 	datadm_free_list(&hca_entry->he_ia_list,
7710Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_ia_entry);
7720Sstevel@tonic-gate 	free(hca_entry);
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate static int
datadm_hca_entry_match(datadm_hca_entry_t * h1,datadm_hca_entry_t * h2)7760Sstevel@tonic-gate datadm_hca_entry_match(datadm_hca_entry_t *h1, datadm_hca_entry_t *h2)
7770Sstevel@tonic-gate {
7780Sstevel@tonic-gate 	if (!datadm_str_match(h1->he_name, h2->he_name)) {
7790Sstevel@tonic-gate 		return (0);
7800Sstevel@tonic-gate 	}
7810Sstevel@tonic-gate 	return (1);
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate static int
datadm_hca_entry_find(datadm_hca_entry_t * h1,datadm_hca_find_t * hf)7850Sstevel@tonic-gate datadm_hca_entry_find(datadm_hca_entry_t *h1, datadm_hca_find_t *hf)
7860Sstevel@tonic-gate {
7870Sstevel@tonic-gate 	if (datadm_str_match(h1->he_name, hf->hf_sp_entry->spe_devname)) {
7880Sstevel@tonic-gate 		hf->hf_hca_entry = h1;
7890Sstevel@tonic-gate 		return (1);
7900Sstevel@tonic-gate 	}
7910Sstevel@tonic-gate 	return (0);
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate static int
datadm_ia_entry_find(datadm_ia_entry_t * i1,datadm_ia_find_t * iaf)7950Sstevel@tonic-gate datadm_ia_entry_find(datadm_ia_entry_t *i1, datadm_ia_find_t *iaf)
7960Sstevel@tonic-gate {
797*12163SRamaswamy.Tummala@Sun.COM 	if (strcmp(i1->iae_name, iaf->if_ia_name) == 0) {
7980Sstevel@tonic-gate 		iaf->if_ia_entry = i1;
7990Sstevel@tonic-gate 		return (1);
8000Sstevel@tonic-gate 	}
8010Sstevel@tonic-gate 	return (0);
8020Sstevel@tonic-gate }
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate static datadm_cmnt_entry_t *
datadm_alloc_cmnt_entry(void)8050Sstevel@tonic-gate datadm_alloc_cmnt_entry(void)
8060Sstevel@tonic-gate {
8070Sstevel@tonic-gate 	datadm_cmnt_entry_t	*cmnt_entry;
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	cmnt_entry = (datadm_cmnt_entry_t *)malloc(sizeof (*cmnt_entry));
8100Sstevel@tonic-gate 	if (cmnt_entry == NULL) {
8110Sstevel@tonic-gate 		return (NULL);
8120Sstevel@tonic-gate 	}
8130Sstevel@tonic-gate 	bzero(cmnt_entry, sizeof (*cmnt_entry));
8140Sstevel@tonic-gate 	return (cmnt_entry);
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate static void
datadm_free_cmnt_entry(datadm_cmnt_entry_t * cmnt_entry)8180Sstevel@tonic-gate datadm_free_cmnt_entry(datadm_cmnt_entry_t *cmnt_entry)
8190Sstevel@tonic-gate {
8200Sstevel@tonic-gate 	if (cmnt_entry->cmnt_line != NULL) {
8210Sstevel@tonic-gate 		free(cmnt_entry->cmnt_line);
8220Sstevel@tonic-gate 		cmnt_entry->cmnt_line = NULL;
8230Sstevel@tonic-gate 	}
8240Sstevel@tonic-gate 	free(cmnt_entry);
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate /*
8280Sstevel@tonic-gate  * tokenizes a line and strips off the quotes from quoted strings
8290Sstevel@tonic-gate  */
8300Sstevel@tonic-gate static int
datadm_parse_line(char * line_buf,char * tokens[],int * token_count)8310Sstevel@tonic-gate datadm_parse_line(char *line_buf, char *tokens[], int *token_count)
8320Sstevel@tonic-gate {
8330Sstevel@tonic-gate 	int			len, i;
8340Sstevel@tonic-gate 	int			count = 0;
8350Sstevel@tonic-gate 	char			*start = NULL;
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate 	/* the line must not be longer than DATADM_LINESZ */
8380Sstevel@tonic-gate 	len = strlen(line_buf);
8390Sstevel@tonic-gate 	if (line_buf[len - 1] != '\n') {
8400Sstevel@tonic-gate 		return (-1);
8410Sstevel@tonic-gate 	}
8420Sstevel@tonic-gate 	/* discard blank lines and comments */
8430Sstevel@tonic-gate 	if (len == 1) {
8440Sstevel@tonic-gate 		*token_count = 0;
8450Sstevel@tonic-gate 		return (0);
8460Sstevel@tonic-gate 	}
8470Sstevel@tonic-gate 	if (len >= 2 && line_buf[0] == '#') {
8480Sstevel@tonic-gate 		*token_count = 0;
8490Sstevel@tonic-gate 		return (0);
8500Sstevel@tonic-gate 	}
8510Sstevel@tonic-gate 	/* removes the new line */
8520Sstevel@tonic-gate 	line_buf[len - 1] = '\0';
8530Sstevel@tonic-gate 	len--;
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
8560Sstevel@tonic-gate 		if (start != NULL) {
8570Sstevel@tonic-gate 			/*
8580Sstevel@tonic-gate 			 * start points to the start of
8590Sstevel@tonic-gate 			 * a new token. if start is '"',
8600Sstevel@tonic-gate 			 * we should expect a quoted
8610Sstevel@tonic-gate 			 * string.
8620Sstevel@tonic-gate 			 */
8630Sstevel@tonic-gate 			if (*start == '\"') {
8640Sstevel@tonic-gate 				/*
8650Sstevel@tonic-gate 				 * keep scanning until we
8660Sstevel@tonic-gate 				 * hit the end quote.
8670Sstevel@tonic-gate 				 */
8680Sstevel@tonic-gate 				if (line_buf[i] != '\"') {
8690Sstevel@tonic-gate 					continue;
8700Sstevel@tonic-gate 				}
8710Sstevel@tonic-gate 				/*
8720Sstevel@tonic-gate 				 * skip past the start quote
8730Sstevel@tonic-gate 				 */
8740Sstevel@tonic-gate 				start++;
8750Sstevel@tonic-gate 			} else {
8760Sstevel@tonic-gate 				/*
8770Sstevel@tonic-gate 				 * our token is not a quoted
8780Sstevel@tonic-gate 				 * string. our token ends only
8790Sstevel@tonic-gate 				 * when we hit a whitespace.
8800Sstevel@tonic-gate 				 */
8810Sstevel@tonic-gate 				if (!isspace(line_buf[i])) {
8820Sstevel@tonic-gate 					continue;
8830Sstevel@tonic-gate 				}
8840Sstevel@tonic-gate 			}
8850Sstevel@tonic-gate 			/*
8860Sstevel@tonic-gate 			 * nullify the end quote (if any)
8870Sstevel@tonic-gate 			 * and update the tokens array.
8880Sstevel@tonic-gate 			 */
8890Sstevel@tonic-gate 			line_buf[i] = '\0';
8900Sstevel@tonic-gate 			tokens[count] = start;
8910Sstevel@tonic-gate 			start = NULL;
8920Sstevel@tonic-gate 			count++;
8930Sstevel@tonic-gate 		} else {
8940Sstevel@tonic-gate 			/*
8950Sstevel@tonic-gate 			 * skip whitespaces
8960Sstevel@tonic-gate 			 */
8970Sstevel@tonic-gate 			if (isspace(line_buf[i])) {
8980Sstevel@tonic-gate 				continue;
8990Sstevel@tonic-gate 			} else {
9000Sstevel@tonic-gate 				start = &line_buf[i];
9010Sstevel@tonic-gate 			}
9020Sstevel@tonic-gate 		}
9030Sstevel@tonic-gate 		if (count == DATADM_MAX_TOKENS) {
9040Sstevel@tonic-gate 			start = NULL;
9050Sstevel@tonic-gate 			break;
9060Sstevel@tonic-gate 		}
9070Sstevel@tonic-gate 	}
9080Sstevel@tonic-gate 	if (start != NULL) {
9090Sstevel@tonic-gate 		tokens[count] = start;
9100Sstevel@tonic-gate 		start = NULL;
9110Sstevel@tonic-gate 		count++;
9120Sstevel@tonic-gate 	}
9130Sstevel@tonic-gate 	*token_count = count;
9140Sstevel@tonic-gate 	return (0);
9150Sstevel@tonic-gate }
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate /*
9180Sstevel@tonic-gate  * attempts to save sp_entry into hca_list.
9190Sstevel@tonic-gate  * becomes no-op if sp entry already exists.
9200Sstevel@tonic-gate  * new hca entries and ia entries are created as needed.
9210Sstevel@tonic-gate  */
9220Sstevel@tonic-gate static int
datadm_process_sp_entry(datadm_list_t * hca_list,datadm_sp_entry_t * sp_entry,char * ia_name)9230Sstevel@tonic-gate datadm_process_sp_entry(datadm_list_t *hca_list, datadm_sp_entry_t *sp_entry,
924*12163SRamaswamy.Tummala@Sun.COM 	char *ia_name)
9250Sstevel@tonic-gate {
9260Sstevel@tonic-gate 	datadm_hca_find_t	hca_find;
9270Sstevel@tonic-gate 	datadm_ia_find_t	ia_find;
9280Sstevel@tonic-gate 	datadm_hca_entry_t	*hca_entry;
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	hca_find.hf_sp_entry = sp_entry;
9310Sstevel@tonic-gate 	hca_find.hf_hca_entry = NULL;
9320Sstevel@tonic-gate 	(void) datadm_walk_list(hca_list, (int (*)(datadm_entry_t *, void *))
9330Sstevel@tonic-gate 	    datadm_hca_entry_find, (void *)&hca_find);
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	if (hca_find.hf_hca_entry == NULL) {
9360Sstevel@tonic-gate 		int	dlen;
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate 		/*
9390Sstevel@tonic-gate 		 * hca_entry not found, need to create
9400Sstevel@tonic-gate 		 * and insert one.
9410Sstevel@tonic-gate 		 */
9420Sstevel@tonic-gate 		hca_entry = datadm_alloc_hca_entry();
9430Sstevel@tonic-gate 		if (hca_entry == NULL) {
9440Sstevel@tonic-gate 			return (-1);
9450Sstevel@tonic-gate 		}
9460Sstevel@tonic-gate 		dlen = strlen(sp_entry->spe_devname);
9470Sstevel@tonic-gate 		hca_entry->he_name = (char *)malloc(dlen + 1);
9480Sstevel@tonic-gate 		if (hca_entry->he_name == NULL) {
9490Sstevel@tonic-gate 			datadm_free_hca_entry(hca_entry);
9500Sstevel@tonic-gate 			return (-1);
9510Sstevel@tonic-gate 		}
9520Sstevel@tonic-gate 		(void) strcpy(hca_entry->he_name, sp_entry->spe_devname);
9530Sstevel@tonic-gate 		datadm_enqueue_entry(hca_list, (datadm_entry_t *)hca_entry);
9540Sstevel@tonic-gate 	} else {
9550Sstevel@tonic-gate 		hca_entry = hca_find.hf_hca_entry;
9560Sstevel@tonic-gate 	}
957*12163SRamaswamy.Tummala@Sun.COM 	if (ia_name == NULL) {
9580Sstevel@tonic-gate 		goto put_sp_entry;
9590Sstevel@tonic-gate 	}
960*12163SRamaswamy.Tummala@Sun.COM 	ia_find.if_ia_name = ia_name;
9610Sstevel@tonic-gate 	ia_find.if_ia_entry = NULL;
9620Sstevel@tonic-gate 	(void) datadm_walk_list(&hca_entry->he_ia_list,
9630Sstevel@tonic-gate 	    (int (*)(datadm_entry_t *, void *))datadm_ia_entry_find, &ia_find);
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 	if (ia_find.if_ia_entry == NULL) {
9660Sstevel@tonic-gate 		datadm_ia_entry_t	*ia_entry;
9670Sstevel@tonic-gate 
9680Sstevel@tonic-gate 		/*
9690Sstevel@tonic-gate 		 * ia_entry not found, need to create
9700Sstevel@tonic-gate 		 * and insert one.
9710Sstevel@tonic-gate 		 */
9720Sstevel@tonic-gate 		ia_entry = datadm_alloc_ia_entry();
9730Sstevel@tonic-gate 		if (ia_entry == NULL) {
9740Sstevel@tonic-gate 			return (-1);
9750Sstevel@tonic-gate 		}
976*12163SRamaswamy.Tummala@Sun.COM 		(void) strlcpy(ia_entry->iae_name, ia_name, MAXLINKNAMELEN);
9770Sstevel@tonic-gate 		datadm_enqueue_entry(&hca_entry->he_ia_list,
9780Sstevel@tonic-gate 		    (datadm_entry_t *)ia_entry);
9790Sstevel@tonic-gate 	}
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate put_sp_entry:;
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 	if (datadm_walk_list(&hca_entry->he_sp_list,
9840Sstevel@tonic-gate 	    (int (*)(datadm_entry_t *, void *))datadm_sp_entry_match,
9850Sstevel@tonic-gate 	    (void *)sp_entry)) {
9860Sstevel@tonic-gate 		return (1);
9870Sstevel@tonic-gate 	} else {
9880Sstevel@tonic-gate 		/*
9890Sstevel@tonic-gate 		 * only insert sp_entry if it is not found.
9900Sstevel@tonic-gate 		 */
9910Sstevel@tonic-gate 		datadm_enqueue_entry(&hca_entry->he_sp_list,
9920Sstevel@tonic-gate 		    (datadm_entry_t *)sp_entry);
9930Sstevel@tonic-gate 	}
9940Sstevel@tonic-gate 	return (0);
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate /*
9980Sstevel@tonic-gate  * parses service_provider.conf
9990Sstevel@tonic-gate  */
10000Sstevel@tonic-gate static int
datadm_parse_sp_conf(datadm_list_t * hca_list)10010Sstevel@tonic-gate datadm_parse_sp_conf(datadm_list_t *hca_list)
10020Sstevel@tonic-gate {
10030Sstevel@tonic-gate 	datadm_sp_entry_t	*sp_entry;
10040Sstevel@tonic-gate 	FILE			*sp_file;
10050Sstevel@tonic-gate 	char			*sp_conf = datadm_args.da_sp_conf;
10060Sstevel@tonic-gate 	char			*tokens[DATADM_MAX_TOKENS];
10070Sstevel@tonic-gate 	char			line_buf[DATADM_LINESZ];
10080Sstevel@tonic-gate 	int			retval = 0;
10090Sstevel@tonic-gate 	int			token_count = 0;
10100Sstevel@tonic-gate 	int			line_count = 0;
10110Sstevel@tonic-gate 
10120Sstevel@tonic-gate 	sp_file = fopen(sp_conf, "r");
10130Sstevel@tonic-gate 	if (sp_file == NULL) {
10140Sstevel@tonic-gate 		(void) fprintf(stderr,
10150Sstevel@tonic-gate 		    gettext("datadm: cannot open %s\n"), sp_conf);
10160Sstevel@tonic-gate 		return (-1);
10170Sstevel@tonic-gate 	}
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate 	for (;;) {
10200Sstevel@tonic-gate 		bzero(line_buf, DATADM_LINESZ);
10210Sstevel@tonic-gate 		if (fgets(line_buf, DATADM_LINESZ, sp_file) == NULL) {
10220Sstevel@tonic-gate 			break;
10230Sstevel@tonic-gate 		}
10240Sstevel@tonic-gate 		token_count = 0;
10250Sstevel@tonic-gate 		line_count++;
10260Sstevel@tonic-gate 		retval = datadm_parse_line(line_buf, tokens, &token_count);
10270Sstevel@tonic-gate 		if (retval != 0) {
10280Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
10290Sstevel@tonic-gate 			    "datadm: %s: line %d exceeded max length %d\n"),
10300Sstevel@tonic-gate 			    sp_conf, line_count, DATADM_LINESZ);
10310Sstevel@tonic-gate 			break;
10320Sstevel@tonic-gate 		}
10330Sstevel@tonic-gate 		if (token_count == 0) continue;
10340Sstevel@tonic-gate 		if (token_count == DATADM_NUM_SP_TOKENS) {
10350Sstevel@tonic-gate 			int i = 0;
10360Sstevel@tonic-gate 
10370Sstevel@tonic-gate 			sp_entry = datadm_alloc_sp_entry();
10380Sstevel@tonic-gate 			if (sp_entry == NULL) {
10390Sstevel@tonic-gate 				retval = -1;
10400Sstevel@tonic-gate 				break;
10410Sstevel@tonic-gate 			}
10420Sstevel@tonic-gate 
10430Sstevel@tonic-gate 			/*
10440Sstevel@tonic-gate 			 * sp_entry gets filled incrementally by
10450Sstevel@tonic-gate 			 * each parsing function
10460Sstevel@tonic-gate 			 */
10470Sstevel@tonic-gate 			for (i = 0; i < DATADM_NUM_SP_TOKENS &&
10480Sstevel@tonic-gate 			    retval == 0; i++) {
10490Sstevel@tonic-gate 				retval = (*datadm_sp_parse_funcs[i])
10500Sstevel@tonic-gate 				    (tokens[i], (void *)sp_entry);
10510Sstevel@tonic-gate 			}
10520Sstevel@tonic-gate 			if (retval != 0) {
10530Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
10540Sstevel@tonic-gate 				    "datadm: parse error: %s, "
10550Sstevel@tonic-gate 				    "line %d, token: %s\n"),
10560Sstevel@tonic-gate 				    sp_conf, line_count, tokens[i - 1]);
10570Sstevel@tonic-gate 				datadm_free_sp_entry(sp_entry);
10580Sstevel@tonic-gate 				sp_entry = NULL;
10590Sstevel@tonic-gate 				break;
10600Sstevel@tonic-gate 			}
10610Sstevel@tonic-gate 
10620Sstevel@tonic-gate 			retval = datadm_process_sp_entry(hca_list,
1063*12163SRamaswamy.Tummala@Sun.COM 			    sp_entry, NULL);
10640Sstevel@tonic-gate 			if (retval != 0) {
10650Sstevel@tonic-gate 				datadm_free_sp_entry(sp_entry);
10660Sstevel@tonic-gate 				if (retval == 1) {
10670Sstevel@tonic-gate 					retval = 0;
10680Sstevel@tonic-gate 				} else {
10690Sstevel@tonic-gate 					break;
10700Sstevel@tonic-gate 				}
10710Sstevel@tonic-gate 			}
10720Sstevel@tonic-gate 		} else {
10730Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
10740Sstevel@tonic-gate 			    "datadm: parse error: %s, line %d, "
10750Sstevel@tonic-gate 			    "# of tokens: %d, expected %d\n"), sp_conf,
10760Sstevel@tonic-gate 			    line_count, token_count, DATADM_NUM_SP_TOKENS);
10770Sstevel@tonic-gate 			retval = -1;
10780Sstevel@tonic-gate 			break;
10790Sstevel@tonic-gate 		}
10800Sstevel@tonic-gate 	}
10810Sstevel@tonic-gate 	if (retval != 0) {
10820Sstevel@tonic-gate 		datadm_free_list(hca_list,
10830Sstevel@tonic-gate 		    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
10840Sstevel@tonic-gate 	}
10850Sstevel@tonic-gate 	(void) fclose(sp_file);
10860Sstevel@tonic-gate 	return (retval);
10870Sstevel@tonic-gate }
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate /*
10900Sstevel@tonic-gate  * parses dat.conf
10910Sstevel@tonic-gate  */
10920Sstevel@tonic-gate static int
datadm_parse_dat_conf(datadm_list_t * hca_list)10930Sstevel@tonic-gate datadm_parse_dat_conf(datadm_list_t *hca_list)
10940Sstevel@tonic-gate {
10950Sstevel@tonic-gate 	boolean_t		save_header = B_TRUE;
10960Sstevel@tonic-gate 	datadm_sp_entry_t	*sp_entry;
10970Sstevel@tonic-gate 	FILE			*dat_file;
10980Sstevel@tonic-gate 	char			*dat_conf = datadm_args.da_dat_conf;
10990Sstevel@tonic-gate 	char			*tokens[DATADM_MAX_TOKENS];
11000Sstevel@tonic-gate 	char			line_buf[DATADM_LINESZ];
11010Sstevel@tonic-gate 	int			retval = 0;
11020Sstevel@tonic-gate 	int			token_count = 0;
11030Sstevel@tonic-gate 	int			line_count = 0;
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate 	dat_file = fopen(dat_conf, "r");
11060Sstevel@tonic-gate 	if (dat_file == NULL) {
11070Sstevel@tonic-gate 		/* dat.conf not existing is not an error for OP_ADD */
11080Sstevel@tonic-gate 		if (datadm_args.da_op_type == DATADM_OP_ADD) {
11090Sstevel@tonic-gate 			return (0);
11100Sstevel@tonic-gate 		}
11110Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("datadm: cannot open %s\n"),
11120Sstevel@tonic-gate 		    dat_conf);
11130Sstevel@tonic-gate 		return (-1);
11140Sstevel@tonic-gate 	}
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	for (;;) {
11170Sstevel@tonic-gate 		bzero(line_buf, DATADM_LINESZ);
11180Sstevel@tonic-gate 		if (fgets(line_buf, DATADM_LINESZ, dat_file) == NULL) {
11190Sstevel@tonic-gate 			break;
11200Sstevel@tonic-gate 		}
11210Sstevel@tonic-gate 		token_count = 0;
11220Sstevel@tonic-gate 		line_count++;
11230Sstevel@tonic-gate 		retval = datadm_parse_line(line_buf, tokens, &token_count);
11240Sstevel@tonic-gate 		if (retval != 0) {
11250Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
11260Sstevel@tonic-gate 			    "datadm: %s: line %d exceeded max length %d\n"),
11270Sstevel@tonic-gate 			    dat_conf, line_count, DATADM_LINESZ);
11280Sstevel@tonic-gate 			break;
11290Sstevel@tonic-gate 		}
11300Sstevel@tonic-gate 		if (token_count == 0) {
11310Sstevel@tonic-gate 			datadm_cmnt_entry_t	*cmnt_entry;
11320Sstevel@tonic-gate 			int			cmnt_len;
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate 			/*
11350Sstevel@tonic-gate 			 * comments are saved only if they are
11360Sstevel@tonic-gate 			 * at the top of dat.conf.
11370Sstevel@tonic-gate 			 */
11380Sstevel@tonic-gate 			if (!save_header) continue;
11390Sstevel@tonic-gate 			cmnt_entry = datadm_alloc_cmnt_entry();
11400Sstevel@tonic-gate 			if (cmnt_entry == NULL) {
11410Sstevel@tonic-gate 				perror("datadm: malloc");
11420Sstevel@tonic-gate 				retval = -1;
11430Sstevel@tonic-gate 				break;
11440Sstevel@tonic-gate 			}
11450Sstevel@tonic-gate 			cmnt_len = strlen(line_buf);
11460Sstevel@tonic-gate 			cmnt_entry->cmnt_line = (char *)malloc(cmnt_len + 1);
11470Sstevel@tonic-gate 			if (cmnt_entry->cmnt_line == NULL) {
11480Sstevel@tonic-gate 				perror("datadm: malloc");
11490Sstevel@tonic-gate 				datadm_free_cmnt_entry(cmnt_entry);
11500Sstevel@tonic-gate 				retval = -1;
11510Sstevel@tonic-gate 				break;
11520Sstevel@tonic-gate 			}
11530Sstevel@tonic-gate 			(void) strncpy(cmnt_entry->cmnt_line,
11540Sstevel@tonic-gate 			    line_buf, cmnt_len);
11550Sstevel@tonic-gate 			cmnt_entry->cmnt_line[cmnt_len] = '\0';
11560Sstevel@tonic-gate 			datadm_enqueue_entry(&datadm_conf_header,
11570Sstevel@tonic-gate 			    (datadm_entry_t *)cmnt_entry);
11580Sstevel@tonic-gate 			continue;
11590Sstevel@tonic-gate 		}
11600Sstevel@tonic-gate 		if (token_count == DATADM_NUM_DAT_TOKENS) {
11610Sstevel@tonic-gate 			int i = 0;
1162*12163SRamaswamy.Tummala@Sun.COM 			char ia_name[MAXLINKNAMELEN];
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate 			/*
11650Sstevel@tonic-gate 			 * we stop saving comment lines once
11660Sstevel@tonic-gate 			 * we see the first valid line.
11670Sstevel@tonic-gate 			 */
11680Sstevel@tonic-gate 			save_header = B_FALSE;
11690Sstevel@tonic-gate 			sp_entry = datadm_alloc_sp_entry();
11700Sstevel@tonic-gate 			if (sp_entry == NULL) {
11710Sstevel@tonic-gate 				retval = -1;
11720Sstevel@tonic-gate 				break;
11730Sstevel@tonic-gate 			}
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 			/*
11760Sstevel@tonic-gate 			 * sp_entry gets filled incrementally by
11770Sstevel@tonic-gate 			 * each parsing function
11780Sstevel@tonic-gate 			 */
11790Sstevel@tonic-gate 			for (i = 0; i < DATADM_NUM_DAT_TOKENS &&
11800Sstevel@tonic-gate 			    retval == 0; i++) {
11810Sstevel@tonic-gate 				void	*arg;
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate 				if (i == 0) {
11840Sstevel@tonic-gate 					/*
11850Sstevel@tonic-gate 					 * the first token (ia name)
11860Sstevel@tonic-gate 					 * does not belong to an
11870Sstevel@tonic-gate 					 * sp_entry
11880Sstevel@tonic-gate 					 */
1189*12163SRamaswamy.Tummala@Sun.COM 					arg = (void *)ia_name;
11900Sstevel@tonic-gate 				} else {
11910Sstevel@tonic-gate 					arg = (void *)sp_entry;
11920Sstevel@tonic-gate 				}
11930Sstevel@tonic-gate 				retval = (*datadm_dat_parse_funcs[i])
11940Sstevel@tonic-gate 				    (tokens[i], arg);
11950Sstevel@tonic-gate 			}
11960Sstevel@tonic-gate 			if (retval != 0) {
11970Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
11980Sstevel@tonic-gate 				    "datadm: parse error: %s, "
11990Sstevel@tonic-gate 				    "line %d, token: %s\n"), dat_conf,
12000Sstevel@tonic-gate 				    line_count, tokens[i - 1]);
12010Sstevel@tonic-gate 				datadm_free_sp_entry(sp_entry);
12020Sstevel@tonic-gate 				sp_entry = NULL;
12030Sstevel@tonic-gate 				break;
12040Sstevel@tonic-gate 			}
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate 			/*
12070Sstevel@tonic-gate 			 * we ignore the ibds in dat.conf if we are
12080Sstevel@tonic-gate 			 * doing update
12090Sstevel@tonic-gate 			 */
12100Sstevel@tonic-gate 			if (datadm_args.da_op_type == DATADM_OP_UPDATE) {
1211*12163SRamaswamy.Tummala@Sun.COM 				retval = datadm_process_sp_entry(hca_list,
1212*12163SRamaswamy.Tummala@Sun.COM 				    sp_entry, NULL);
1213*12163SRamaswamy.Tummala@Sun.COM 			} else {
1214*12163SRamaswamy.Tummala@Sun.COM 				retval = datadm_process_sp_entry(hca_list,
1215*12163SRamaswamy.Tummala@Sun.COM 				    sp_entry, ia_name);
12160Sstevel@tonic-gate 			}
12170Sstevel@tonic-gate 			if (retval != 0) {
12180Sstevel@tonic-gate 				datadm_free_sp_entry(sp_entry);
12190Sstevel@tonic-gate 				if (retval == 1) {
12200Sstevel@tonic-gate 					retval = 0;
12210Sstevel@tonic-gate 				} else {
12220Sstevel@tonic-gate 					break;
12230Sstevel@tonic-gate 				}
12240Sstevel@tonic-gate 			}
12250Sstevel@tonic-gate 		} else {
12260Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
12270Sstevel@tonic-gate 			    "datadm: parse error: %s, line %d, "
12280Sstevel@tonic-gate 			    "# of tokens: %d, expected %d\n"), dat_conf,
12290Sstevel@tonic-gate 			    line_count, token_count, DATADM_NUM_DAT_TOKENS);
12300Sstevel@tonic-gate 			retval = -1;
12310Sstevel@tonic-gate 			break;
12320Sstevel@tonic-gate 		}
12330Sstevel@tonic-gate 	}
12340Sstevel@tonic-gate 	if (retval != 0) {
12350Sstevel@tonic-gate 		datadm_free_list(&datadm_conf_header,
12360Sstevel@tonic-gate 		    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
12370Sstevel@tonic-gate 		datadm_free_list(hca_list,
12380Sstevel@tonic-gate 		    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
12390Sstevel@tonic-gate 	}
12400Sstevel@tonic-gate 	(void) fclose(dat_file);
12410Sstevel@tonic-gate 	return (retval);
12420Sstevel@tonic-gate }
12430Sstevel@tonic-gate 
12440Sstevel@tonic-gate /*
12450Sstevel@tonic-gate  * used by OP_REMOVE to invalidate common sp entries between hl1 and hl2.
12460Sstevel@tonic-gate  * invalid sp entries will be ignored by datadm_generate_dat_conf.
12470Sstevel@tonic-gate  */
12480Sstevel@tonic-gate static void
datadm_invalidate_common_sp_entries(datadm_list_t * hl1,datadm_list_t * hl2)12490Sstevel@tonic-gate datadm_invalidate_common_sp_entries(datadm_list_t *hl1, datadm_list_t *hl2)
12500Sstevel@tonic-gate {
12510Sstevel@tonic-gate 	datadm_entry_t	*he1, *he2;
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 	he1 = hl1->dl_head;
12540Sstevel@tonic-gate 	while (he1 != NULL) {
12550Sstevel@tonic-gate 		he2 = hl2->dl_head;
12560Sstevel@tonic-gate 		while (he2 != NULL) {
12570Sstevel@tonic-gate 			datadm_entry_t	*se1, *se2;
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate 			if (!datadm_hca_entry_match(
12600Sstevel@tonic-gate 			    (datadm_hca_entry_t *)he1,
12610Sstevel@tonic-gate 			    (datadm_hca_entry_t *)he2)) {
12620Sstevel@tonic-gate 				he2 = he2->de_next;
12630Sstevel@tonic-gate 				continue;
12640Sstevel@tonic-gate 			}
12650Sstevel@tonic-gate 			se1 = ((datadm_hca_entry_t *)he1)->he_sp_list.dl_head;
12660Sstevel@tonic-gate 			while (se1 != NULL) {
12670Sstevel@tonic-gate 				se2 = ((datadm_hca_entry_t *)he2)->
12680Sstevel@tonic-gate 				    he_sp_list.dl_head;
12690Sstevel@tonic-gate 				while (se2 != NULL) {
12700Sstevel@tonic-gate 					if (!datadm_sp_entry_match(
12710Sstevel@tonic-gate 					    (datadm_sp_entry_t *)se1,
12720Sstevel@tonic-gate 					    (datadm_sp_entry_t *)se2)) {
12730Sstevel@tonic-gate 						se2 = se2->de_next;
12740Sstevel@tonic-gate 						continue;
12750Sstevel@tonic-gate 					}
12760Sstevel@tonic-gate 					((datadm_sp_entry_t *)se1)->
12770Sstevel@tonic-gate 					    spe_invalid = 1;
12780Sstevel@tonic-gate 					break;
12790Sstevel@tonic-gate 				}
12800Sstevel@tonic-gate 				se1 = se1->de_next;
12810Sstevel@tonic-gate 			}
12820Sstevel@tonic-gate 			break;
12830Sstevel@tonic-gate 		}
12840Sstevel@tonic-gate 		he1 = he1->de_next;
12850Sstevel@tonic-gate 	}
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate 
1288*12163SRamaswamy.Tummala@Sun.COM static int
datadm_hca_entry_find_by_name(datadm_hca_entry_t * h1,datadm_hca_find_by_name_t * hf)1289*12163SRamaswamy.Tummala@Sun.COM datadm_hca_entry_find_by_name(datadm_hca_entry_t *h1,
1290*12163SRamaswamy.Tummala@Sun.COM     datadm_hca_find_by_name_t *hf)
1291*12163SRamaswamy.Tummala@Sun.COM {
1292*12163SRamaswamy.Tummala@Sun.COM 	if (datadm_str_match(h1->he_name, hf->hf_name)) {
1293*12163SRamaswamy.Tummala@Sun.COM 		hf->hf_hca_entry = h1;
1294*12163SRamaswamy.Tummala@Sun.COM 		return (1);
1295*12163SRamaswamy.Tummala@Sun.COM 	}
1296*12163SRamaswamy.Tummala@Sun.COM 	return (0);
1297*12163SRamaswamy.Tummala@Sun.COM }
1298*12163SRamaswamy.Tummala@Sun.COM 
1299*12163SRamaswamy.Tummala@Sun.COM datadm_hca_entry_t *
datadm_hca_lookup_by_name(datadm_list_t * hca_list,char * hca_driver_name)1300*12163SRamaswamy.Tummala@Sun.COM datadm_hca_lookup_by_name(datadm_list_t *hca_list, char *hca_driver_name)
1301*12163SRamaswamy.Tummala@Sun.COM {
1302*12163SRamaswamy.Tummala@Sun.COM 	datadm_hca_find_by_name_t	hf;
1303*12163SRamaswamy.Tummala@Sun.COM 
1304*12163SRamaswamy.Tummala@Sun.COM 	hf.hf_name = hca_driver_name;
1305*12163SRamaswamy.Tummala@Sun.COM 	hf.hf_hca_entry = NULL;
1306*12163SRamaswamy.Tummala@Sun.COM 	(void) datadm_walk_list(hca_list,
1307*12163SRamaswamy.Tummala@Sun.COM 	    (int (*)(datadm_entry_t *, void *))datadm_hca_entry_find_by_name,
1308*12163SRamaswamy.Tummala@Sun.COM 	    &hf);
1309*12163SRamaswamy.Tummala@Sun.COM 	return (hf.hf_hca_entry);
1310*12163SRamaswamy.Tummala@Sun.COM }
1311*12163SRamaswamy.Tummala@Sun.COM 
1312*12163SRamaswamy.Tummala@Sun.COM static boolean_t
datadm_add_plink(char * linkname,datadm_fill_ia_list_t * ia_args)1313*12163SRamaswamy.Tummala@Sun.COM datadm_add_plink(char *linkname, datadm_fill_ia_list_t *ia_args)
1314*12163SRamaswamy.Tummala@Sun.COM {
1315*12163SRamaswamy.Tummala@Sun.COM 	datalink_class_t	class;
1316*12163SRamaswamy.Tummala@Sun.COM 	datalink_id_t		linkid;
1317*12163SRamaswamy.Tummala@Sun.COM 	dladm_ib_attr_t		ib_attr;
1318*12163SRamaswamy.Tummala@Sun.COM 	ibnex_ctl_query_hca_t	query_hca;
1319*12163SRamaswamy.Tummala@Sun.COM 	datadm_hca_entry_t	*hca;
1320*12163SRamaswamy.Tummala@Sun.COM 	struct lifreq		req;
1321*12163SRamaswamy.Tummala@Sun.COM 	datadm_ia_find_t	ia_find;
1322*12163SRamaswamy.Tummala@Sun.COM 	datadm_ia_entry_t	*ia_entry;
1323*12163SRamaswamy.Tummala@Sun.COM 
1324*12163SRamaswamy.Tummala@Sun.COM 	if ((dladm_name2info(ia_args->ia_dlh, linkname, &linkid, NULL, &class,
1325*12163SRamaswamy.Tummala@Sun.COM 	    NULL) != DLADM_STATUS_OK) ||
1326*12163SRamaswamy.Tummala@Sun.COM 	    (class != DATALINK_CLASS_PART) ||
1327*12163SRamaswamy.Tummala@Sun.COM 	    (dladm_part_info(ia_args->ia_dlh, linkid, &ib_attr,
1328*12163SRamaswamy.Tummala@Sun.COM 	    DLADM_OPT_ACTIVE) != DLADM_STATUS_OK)) {
1329*12163SRamaswamy.Tummala@Sun.COM 		return (B_FALSE);
1330*12163SRamaswamy.Tummala@Sun.COM 	}
1331*12163SRamaswamy.Tummala@Sun.COM 
1332*12163SRamaswamy.Tummala@Sun.COM 	(void) strlcpy(req.lifr_name, linkname, sizeof (req.lifr_name));
1333*12163SRamaswamy.Tummala@Sun.COM 	/*
1334*12163SRamaswamy.Tummala@Sun.COM 	 * we don't really need to know the ip address.
1335*12163SRamaswamy.Tummala@Sun.COM 	 * we just want to check if the device is plumbed
1336*12163SRamaswamy.Tummala@Sun.COM 	 * or not.
1337*12163SRamaswamy.Tummala@Sun.COM 	 */
1338*12163SRamaswamy.Tummala@Sun.COM 	if (ioctl(ia_args->ia_sock_fd_v4, SIOCGLIFADDR, (caddr_t)&req) != 0) {
1339*12163SRamaswamy.Tummala@Sun.COM 		/*
1340*12163SRamaswamy.Tummala@Sun.COM 		 * we try v6 if the v4 address isn't found.
1341*12163SRamaswamy.Tummala@Sun.COM 		 */
1342*12163SRamaswamy.Tummala@Sun.COM 		if (ioctl(ia_args->ia_sock_fd_v6, SIOCGLIFADDR,
1343*12163SRamaswamy.Tummala@Sun.COM 		    (caddr_t)&req) != 0)
1344*12163SRamaswamy.Tummala@Sun.COM 			return (B_FALSE);
1345*12163SRamaswamy.Tummala@Sun.COM 	}
1346*12163SRamaswamy.Tummala@Sun.COM 
1347*12163SRamaswamy.Tummala@Sun.COM 	bzero(&query_hca, sizeof (query_hca));
1348*12163SRamaswamy.Tummala@Sun.COM 	query_hca.hca_guid = ib_attr.dia_hca_guid;
1349*12163SRamaswamy.Tummala@Sun.COM 	if (ioctl(ia_args->ia_ibnex_fd, IBNEX_CTL_QUERY_HCA, &query_hca) == -1)
1350*12163SRamaswamy.Tummala@Sun.COM 		return (B_FALSE);
1351*12163SRamaswamy.Tummala@Sun.COM 
1352*12163SRamaswamy.Tummala@Sun.COM 	if ((hca = datadm_hca_lookup_by_name(ia_args->ia_hca_list,
1353*12163SRamaswamy.Tummala@Sun.COM 	    query_hca.hca_info.hca_driver_name)) == NULL)
1354*12163SRamaswamy.Tummala@Sun.COM 		return (B_FALSE);
1355*12163SRamaswamy.Tummala@Sun.COM 
1356*12163SRamaswamy.Tummala@Sun.COM 	ia_find.if_ia_name = linkname;
1357*12163SRamaswamy.Tummala@Sun.COM 	ia_find.if_ia_entry = NULL;
1358*12163SRamaswamy.Tummala@Sun.COM 	(void) datadm_walk_list(&hca->he_ia_list,
1359*12163SRamaswamy.Tummala@Sun.COM 	    (int (*)(datadm_entry_t *, void *))
1360*12163SRamaswamy.Tummala@Sun.COM 	    datadm_ia_entry_find, &ia_find);
1361*12163SRamaswamy.Tummala@Sun.COM 
1362*12163SRamaswamy.Tummala@Sun.COM 	if (ia_find.if_ia_entry == NULL) {
1363*12163SRamaswamy.Tummala@Sun.COM 		/*
1364*12163SRamaswamy.Tummala@Sun.COM 		 * we insert an ia entry only if
1365*12163SRamaswamy.Tummala@Sun.COM 		 * it is unique.
1366*12163SRamaswamy.Tummala@Sun.COM 		 */
1367*12163SRamaswamy.Tummala@Sun.COM 		ia_entry = datadm_alloc_ia_entry();
1368*12163SRamaswamy.Tummala@Sun.COM 		if (ia_entry != NULL) {
1369*12163SRamaswamy.Tummala@Sun.COM 			(void) strlcpy(ia_entry->iae_name, linkname,
1370*12163SRamaswamy.Tummala@Sun.COM 			    MAXLINKNAMELEN);
1371*12163SRamaswamy.Tummala@Sun.COM 			datadm_enqueue_entry(&hca->he_ia_list,
1372*12163SRamaswamy.Tummala@Sun.COM 			    (datadm_entry_t *)ia_entry);
1373*12163SRamaswamy.Tummala@Sun.COM 		}
1374*12163SRamaswamy.Tummala@Sun.COM 	}
1375*12163SRamaswamy.Tummala@Sun.COM 
1376*12163SRamaswamy.Tummala@Sun.COM 	return (B_FALSE);
1377*12163SRamaswamy.Tummala@Sun.COM }
1378*12163SRamaswamy.Tummala@Sun.COM 
13790Sstevel@tonic-gate /*
1380*12163SRamaswamy.Tummala@Sun.COM  * build ia lists for each hca_list element
13810Sstevel@tonic-gate  */
13820Sstevel@tonic-gate static int
datadm_build_ia_lists(datadm_list_t * hca_list)13830Sstevel@tonic-gate datadm_build_ia_lists(datadm_list_t *hca_list)
13840Sstevel@tonic-gate {
1385*12163SRamaswamy.Tummala@Sun.COM 	dladm_handle_t		dlh;
13860Sstevel@tonic-gate 	datadm_fill_ia_list_t	ia_args;
1387*12163SRamaswamy.Tummala@Sun.COM 	int			rv = -1;
1388*12163SRamaswamy.Tummala@Sun.COM 	int			fd = -1;
1389*12163SRamaswamy.Tummala@Sun.COM 	int			sv4 = -1;
1390*12163SRamaswamy.Tummala@Sun.COM 	int			sv6 = -1;
13910Sstevel@tonic-gate 
1392*12163SRamaswamy.Tummala@Sun.COM 	if (dladm_open(&dlh) != DLADM_STATUS_OK)
13930Sstevel@tonic-gate 		return (-1);
1394*12163SRamaswamy.Tummala@Sun.COM 
1395*12163SRamaswamy.Tummala@Sun.COM 	if ((fd = open(IBNEX_DEVCTL_DEV, O_RDONLY)) < 0)
1396*12163SRamaswamy.Tummala@Sun.COM 		goto out;
1397*12163SRamaswamy.Tummala@Sun.COM 
1398*12163SRamaswamy.Tummala@Sun.COM 	if ((sv4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1399*12163SRamaswamy.Tummala@Sun.COM 		perror("datadm: socket");
1400*12163SRamaswamy.Tummala@Sun.COM 		goto out;
14010Sstevel@tonic-gate 	}
1402*12163SRamaswamy.Tummala@Sun.COM 
1403*12163SRamaswamy.Tummala@Sun.COM 	if ((sv6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
14040Sstevel@tonic-gate 		perror("datadm: socket");
1405*12163SRamaswamy.Tummala@Sun.COM 		goto out;
14060Sstevel@tonic-gate 	}
1407*12163SRamaswamy.Tummala@Sun.COM 
1408*12163SRamaswamy.Tummala@Sun.COM 	ia_args.ia_hca_list = hca_list;
1409*12163SRamaswamy.Tummala@Sun.COM 	ia_args.ia_dlh = dlh;
1410*12163SRamaswamy.Tummala@Sun.COM 	ia_args.ia_ibnex_fd = fd;
14110Sstevel@tonic-gate 	ia_args.ia_sock_fd_v4 = sv4;
14120Sstevel@tonic-gate 	ia_args.ia_sock_fd_v6 = sv6;
14130Sstevel@tonic-gate 
1414*12163SRamaswamy.Tummala@Sun.COM 	dlpi_walk((boolean_t (*) (const char *, void *))datadm_add_plink,
1415*12163SRamaswamy.Tummala@Sun.COM 	    &ia_args, 0);
1416*12163SRamaswamy.Tummala@Sun.COM 	rv = 0;
14170Sstevel@tonic-gate 
1418*12163SRamaswamy.Tummala@Sun.COM out:
1419*12163SRamaswamy.Tummala@Sun.COM 	if (sv4 != -1)
1420*12163SRamaswamy.Tummala@Sun.COM 		(void) close(sv4);
1421*12163SRamaswamy.Tummala@Sun.COM 	if (sv6 != -1)
1422*12163SRamaswamy.Tummala@Sun.COM 		(void) close(sv6);
1423*12163SRamaswamy.Tummala@Sun.COM 	if (fd != -1)
1424*12163SRamaswamy.Tummala@Sun.COM 		(void) close(fd);
1425*12163SRamaswamy.Tummala@Sun.COM 
1426*12163SRamaswamy.Tummala@Sun.COM 	dladm_close(dlh);
1427*12163SRamaswamy.Tummala@Sun.COM 	return (rv);
14280Sstevel@tonic-gate }
14290Sstevel@tonic-gate 
14300Sstevel@tonic-gate static int
datadm_generate_conf_entry(FILE * outfile,datadm_ia_entry_t * ia_entry,datadm_sp_entry_t * sp_entry)14310Sstevel@tonic-gate datadm_generate_conf_entry(FILE *outfile, datadm_ia_entry_t *ia_entry,
14320Sstevel@tonic-gate 	datadm_sp_entry_t *sp_entry)
14330Sstevel@tonic-gate {
14340Sstevel@tonic-gate 	int	retval;
14350Sstevel@tonic-gate 
14360Sstevel@tonic-gate 	retval = fprintf(outfile,
1437*12163SRamaswamy.Tummala@Sun.COM 	    "%s  %s%d.%d  %s  %s  %s  %s%d.%d  \"%s\"  \"%s%s%s\"\n",
1438*12163SRamaswamy.Tummala@Sun.COM 	    ia_entry->iae_name,
14390Sstevel@tonic-gate 	    (sp_entry->spe_api_version.dv_name ?
14400Sstevel@tonic-gate 	    sp_entry->spe_api_version.dv_name : ""),
14410Sstevel@tonic-gate 	    sp_entry->spe_api_version.dv_major,
14420Sstevel@tonic-gate 	    sp_entry->spe_api_version.dv_minor,
14430Sstevel@tonic-gate 	    (sp_entry->spe_threadsafe ? "threadsafe" : "nonthreadsafe"),
14440Sstevel@tonic-gate 	    (sp_entry->spe_default ? "default" : "nondefault"),
14450Sstevel@tonic-gate 	    sp_entry->spe_libpath,
14460Sstevel@tonic-gate 	    (sp_entry->spe_sp_version.dv_name ?
14470Sstevel@tonic-gate 	    sp_entry->spe_sp_version.dv_name : ""),
14480Sstevel@tonic-gate 	    sp_entry->spe_sp_version.dv_major,
14490Sstevel@tonic-gate 	    sp_entry->spe_sp_version.dv_minor,
14500Sstevel@tonic-gate 	    sp_entry->spe_sp_data,
14510Sstevel@tonic-gate 	    DATADM_DRV_NAME, "=", sp_entry->spe_devname);
14520Sstevel@tonic-gate 
14530Sstevel@tonic-gate 	if (retval < 0) {
14540Sstevel@tonic-gate 		return (-1);
14550Sstevel@tonic-gate 	}
14560Sstevel@tonic-gate 	return (0);
14570Sstevel@tonic-gate }
14580Sstevel@tonic-gate 
14590Sstevel@tonic-gate /*
14600Sstevel@tonic-gate  * generate dat.conf header
14610Sstevel@tonic-gate  */
14620Sstevel@tonic-gate static int
datadm_generate_conf_header(FILE * outfile)14630Sstevel@tonic-gate datadm_generate_conf_header(FILE *outfile)
14640Sstevel@tonic-gate {
14650Sstevel@tonic-gate 	datadm_entry_t		*cep;
14660Sstevel@tonic-gate 	datadm_cmnt_entry_t	*cmnt;
14670Sstevel@tonic-gate 	int			retval = 0;
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate 	cep = datadm_conf_header.dl_head;
14700Sstevel@tonic-gate 	if (cep == NULL) {
14710Sstevel@tonic-gate 		/*
14720Sstevel@tonic-gate 		 * if dat.conf doesn't have a header, we prepend a
14730Sstevel@tonic-gate 		 * default one.
14740Sstevel@tonic-gate 		 */
14750Sstevel@tonic-gate 		retval = fprintf(outfile, "%s", datadm_conf_header_default);
14760Sstevel@tonic-gate 		goto done;
14770Sstevel@tonic-gate 	}
14780Sstevel@tonic-gate 	while (cep != NULL) {
14790Sstevel@tonic-gate 		cmnt = (datadm_cmnt_entry_t *)cep;
14800Sstevel@tonic-gate 		if (cmnt->cmnt_line != NULL) {
14810Sstevel@tonic-gate 			int		len;
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate 			retval = fprintf(outfile, "%s", cmnt->cmnt_line);
14840Sstevel@tonic-gate 			if (retval < 0) {
14850Sstevel@tonic-gate 				break;
14860Sstevel@tonic-gate 			}
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate 			/*
14890Sstevel@tonic-gate 			 * append a newline if the comment line doesn't
14900Sstevel@tonic-gate 			 * have one.
14910Sstevel@tonic-gate 			 */
14920Sstevel@tonic-gate 			len = strlen(cmnt->cmnt_line);
14930Sstevel@tonic-gate 			if (cmnt->cmnt_line[len - 1] != '\n') {
14940Sstevel@tonic-gate 				retval = fprintf(outfile, "\n");
14950Sstevel@tonic-gate 				if (retval < 0) {
14960Sstevel@tonic-gate 					break;
14970Sstevel@tonic-gate 				}
14980Sstevel@tonic-gate 			}
14990Sstevel@tonic-gate 		}
15000Sstevel@tonic-gate 		cep = cep->de_next;
15010Sstevel@tonic-gate 	}
15020Sstevel@tonic-gate done:;
15030Sstevel@tonic-gate 	if (retval < 0) {
15040Sstevel@tonic-gate 		return (-1);
15050Sstevel@tonic-gate 	}
15060Sstevel@tonic-gate 	return (0);
15070Sstevel@tonic-gate }
15080Sstevel@tonic-gate 
15090Sstevel@tonic-gate /*
15100Sstevel@tonic-gate  * outputs dat.conf to stdout or to basedir/etc/dat/dat.conf
15110Sstevel@tonic-gate  */
15120Sstevel@tonic-gate static int
datadm_generate_dat_conf(datadm_list_t * hca_list)15130Sstevel@tonic-gate datadm_generate_dat_conf(datadm_list_t *hca_list)
15140Sstevel@tonic-gate {
15150Sstevel@tonic-gate 	FILE			*outfile = NULL;
15160Sstevel@tonic-gate 	char			*dat_conf = datadm_args.da_dat_conf;
15170Sstevel@tonic-gate 	datadm_entry_t		*hep;
15180Sstevel@tonic-gate 	int			retval = 0;
15190Sstevel@tonic-gate 
15200Sstevel@tonic-gate 	if (datadm_args.da_op_type == DATADM_OP_VIEW) {
15210Sstevel@tonic-gate 		outfile = stdout;
15220Sstevel@tonic-gate 	} else {
15230Sstevel@tonic-gate 		outfile = fopen(dat_conf, "w+");
15240Sstevel@tonic-gate 		if (outfile == NULL) {
15250Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
15260Sstevel@tonic-gate 			    "datadm: cannot open %s: %s\n"),
15270Sstevel@tonic-gate 			    dat_conf, strerror(errno));
15280Sstevel@tonic-gate 			return (-1);
15290Sstevel@tonic-gate 		}
15300Sstevel@tonic-gate 	}
15310Sstevel@tonic-gate 	if (outfile != stdout) {
15320Sstevel@tonic-gate 		/*
15330Sstevel@tonic-gate 		 * do not generate the header if we are
15340Sstevel@tonic-gate 		 * printing to the screen
15350Sstevel@tonic-gate 		 */
15360Sstevel@tonic-gate 		retval = datadm_generate_conf_header(outfile);
15370Sstevel@tonic-gate 		if (retval != 0) {
15380Sstevel@tonic-gate 			goto done;
15390Sstevel@tonic-gate 		}
15400Sstevel@tonic-gate 	}
15410Sstevel@tonic-gate 	hep = hca_list->dl_head;
15420Sstevel@tonic-gate 	while (hep != NULL) {
15430Sstevel@tonic-gate 		datadm_entry_t	*iep;
15440Sstevel@tonic-gate 
15450Sstevel@tonic-gate 		iep = ((datadm_hca_entry_t *)hep)->he_ia_list.dl_head;
15460Sstevel@tonic-gate 		while (iep != NULL) {
15470Sstevel@tonic-gate 			datadm_entry_t	*sep;
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate 			sep = ((datadm_hca_entry_t *)hep)->he_sp_list.dl_head;
15500Sstevel@tonic-gate 			while (sep != NULL) {
15510Sstevel@tonic-gate 				if (((datadm_sp_entry_t *)sep)->spe_invalid) {
15520Sstevel@tonic-gate 					sep = sep->de_next;
15530Sstevel@tonic-gate 					continue;
15540Sstevel@tonic-gate 				}
15550Sstevel@tonic-gate 				retval = datadm_generate_conf_entry(outfile,
15560Sstevel@tonic-gate 				    (datadm_ia_entry_t *)iep,
15570Sstevel@tonic-gate 				    (datadm_sp_entry_t *)sep);
15580Sstevel@tonic-gate 				if (retval != 0) {
15590Sstevel@tonic-gate 					goto done;
15600Sstevel@tonic-gate 				}
15610Sstevel@tonic-gate 				sep = sep->de_next;
15620Sstevel@tonic-gate 			}
15630Sstevel@tonic-gate 			iep = iep->de_next;
15640Sstevel@tonic-gate 		}
15650Sstevel@tonic-gate 		hep = hep->de_next;
15660Sstevel@tonic-gate 	}
15670Sstevel@tonic-gate 	retval = fflush(outfile);
15680Sstevel@tonic-gate done:;
15690Sstevel@tonic-gate 	if (outfile != stdout) {
15700Sstevel@tonic-gate 		(void) fclose(outfile);
15710Sstevel@tonic-gate 	}
15720Sstevel@tonic-gate 	if (retval < 0) {
15730Sstevel@tonic-gate 		perror("datadm: fprintf");
15740Sstevel@tonic-gate 	}
15750Sstevel@tonic-gate 	return (retval);
15760Sstevel@tonic-gate }
15770Sstevel@tonic-gate 
15780Sstevel@tonic-gate static int
datadm_view(void)15790Sstevel@tonic-gate datadm_view(void)
15800Sstevel@tonic-gate {
15810Sstevel@tonic-gate 	int			retval = 0;
15820Sstevel@tonic-gate 	datadm_list_t		hca_list;
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	bzero(&hca_list, sizeof (hca_list));
15850Sstevel@tonic-gate 
15860Sstevel@tonic-gate 	retval = datadm_parse_dat_conf(&hca_list);
15870Sstevel@tonic-gate 	if (retval != 0) {
15880Sstevel@tonic-gate 		goto cleanup;
15890Sstevel@tonic-gate 	}
15900Sstevel@tonic-gate 	retval = datadm_generate_dat_conf(&hca_list);
15910Sstevel@tonic-gate 	if (retval != 0) {
15920Sstevel@tonic-gate 		goto cleanup;
15930Sstevel@tonic-gate 	}
15940Sstevel@tonic-gate 
15950Sstevel@tonic-gate cleanup:;
15960Sstevel@tonic-gate 	datadm_free_list(&datadm_conf_header,
15970Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
15980Sstevel@tonic-gate 	datadm_free_list(&hca_list,
15990Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
16000Sstevel@tonic-gate 	return (retval);
16010Sstevel@tonic-gate }
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate static int
datadm_update(void)16040Sstevel@tonic-gate datadm_update(void)
16050Sstevel@tonic-gate {
16060Sstevel@tonic-gate 	int			retval = 0;
16070Sstevel@tonic-gate 	datadm_list_t		hca_list;
16080Sstevel@tonic-gate 
16090Sstevel@tonic-gate 	bzero(&hca_list, sizeof (hca_list));
16100Sstevel@tonic-gate 
16110Sstevel@tonic-gate 	retval = datadm_parse_dat_conf(&hca_list);
16120Sstevel@tonic-gate 	if (retval != 0) {
16130Sstevel@tonic-gate 		goto cleanup;
16140Sstevel@tonic-gate 	}
16150Sstevel@tonic-gate 	retval = datadm_build_ia_lists(&hca_list);
16160Sstevel@tonic-gate 	if (retval != 0) {
16170Sstevel@tonic-gate 		goto cleanup;
16180Sstevel@tonic-gate 	}
16190Sstevel@tonic-gate 	retval = datadm_generate_dat_conf(&hca_list);
16200Sstevel@tonic-gate 	if (retval != 0) {
16210Sstevel@tonic-gate 		goto cleanup;
16220Sstevel@tonic-gate 	}
16230Sstevel@tonic-gate 
16240Sstevel@tonic-gate cleanup:;
16250Sstevel@tonic-gate 	datadm_free_list(&datadm_conf_header,
16260Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
16270Sstevel@tonic-gate 	datadm_free_list(&hca_list,
16280Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
16290Sstevel@tonic-gate 	return (retval);
16300Sstevel@tonic-gate }
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate static int
datadm_add(void)16330Sstevel@tonic-gate datadm_add(void)
16340Sstevel@tonic-gate {
16350Sstevel@tonic-gate 	int			retval = 0;
16360Sstevel@tonic-gate 	datadm_list_t		hca_list;
16370Sstevel@tonic-gate 
16380Sstevel@tonic-gate 	bzero(&hca_list, sizeof (hca_list));
16390Sstevel@tonic-gate 
16400Sstevel@tonic-gate 	retval = datadm_parse_dat_conf(&hca_list);
16410Sstevel@tonic-gate 	if (retval != 0) {
16420Sstevel@tonic-gate 		goto cleanup;
16430Sstevel@tonic-gate 	}
16440Sstevel@tonic-gate 	retval = datadm_parse_sp_conf(&hca_list);
16450Sstevel@tonic-gate 	if (retval != 0) {
16460Sstevel@tonic-gate 		goto cleanup;
16470Sstevel@tonic-gate 	}
16480Sstevel@tonic-gate 	retval = datadm_build_ia_lists(&hca_list);
16490Sstevel@tonic-gate 	if (retval != 0) {
16500Sstevel@tonic-gate 		goto cleanup;
16510Sstevel@tonic-gate 	}
16520Sstevel@tonic-gate 	retval = datadm_generate_dat_conf(&hca_list);
16530Sstevel@tonic-gate 	if (retval != 0) {
16540Sstevel@tonic-gate 		goto cleanup;
16550Sstevel@tonic-gate 	}
16560Sstevel@tonic-gate 
16570Sstevel@tonic-gate cleanup:;
16580Sstevel@tonic-gate 	datadm_free_list(&datadm_conf_header,
16590Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
16600Sstevel@tonic-gate 	datadm_free_list(&hca_list,
16610Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
16620Sstevel@tonic-gate 	return (retval);
16630Sstevel@tonic-gate }
16640Sstevel@tonic-gate 
16650Sstevel@tonic-gate static int
datadm_remove(void)16660Sstevel@tonic-gate datadm_remove(void)
16670Sstevel@tonic-gate {
16680Sstevel@tonic-gate 	int			retval = 0;
16690Sstevel@tonic-gate 	datadm_list_t		hca_list;
16700Sstevel@tonic-gate 	datadm_list_t		hca_list2;
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 	bzero(&hca_list, sizeof (hca_list));
16730Sstevel@tonic-gate 	bzero(&hca_list2, sizeof (hca_list2));
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate 	retval = datadm_parse_dat_conf(&hca_list);
16760Sstevel@tonic-gate 	if (retval != 0) {
16770Sstevel@tonic-gate 		goto cleanup;
16780Sstevel@tonic-gate 	}
16790Sstevel@tonic-gate 	retval = datadm_parse_sp_conf(&hca_list2);
16800Sstevel@tonic-gate 	if (retval != 0) {
16810Sstevel@tonic-gate 		goto cleanup;
16820Sstevel@tonic-gate 	}
16830Sstevel@tonic-gate 	datadm_invalidate_common_sp_entries(&hca_list, &hca_list2);
16840Sstevel@tonic-gate 
16850Sstevel@tonic-gate 	retval = datadm_generate_dat_conf(&hca_list);
16860Sstevel@tonic-gate 	if (retval != 0) {
16870Sstevel@tonic-gate 		goto cleanup;
16880Sstevel@tonic-gate 	}
16890Sstevel@tonic-gate 
16900Sstevel@tonic-gate cleanup:;
16910Sstevel@tonic-gate 	datadm_free_list(&datadm_conf_header,
16920Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_cmnt_entry);
16930Sstevel@tonic-gate 	datadm_free_list(&hca_list,
16940Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
16950Sstevel@tonic-gate 	datadm_free_list(&hca_list2,
16960Sstevel@tonic-gate 	    (void (*)(datadm_entry_t *))datadm_free_hca_entry);
16970Sstevel@tonic-gate 	return (retval);
16980Sstevel@tonic-gate }
16990Sstevel@tonic-gate 
17000Sstevel@tonic-gate static int
datadm_locate_dat_conf(char * basedir)17010Sstevel@tonic-gate datadm_locate_dat_conf(char *basedir)
17020Sstevel@tonic-gate {
17030Sstevel@tonic-gate 	char		*dat_conf;
17040Sstevel@tonic-gate 
17050Sstevel@tonic-gate 	if (basedir == NULL) {
17060Sstevel@tonic-gate 		datadm_args.da_dat_conf = DATADM_DAT_CONF;
17070Sstevel@tonic-gate 		return (0);
17080Sstevel@tonic-gate 	}
17090Sstevel@tonic-gate 	dat_conf = (char *)malloc(strlen(basedir) +
17100Sstevel@tonic-gate 	    strlen(DATADM_DAT_CONF) + 1);
17110Sstevel@tonic-gate 	if (dat_conf == NULL) {
17120Sstevel@tonic-gate 		return (-1);
17130Sstevel@tonic-gate 	}
17140Sstevel@tonic-gate 	dat_conf[0] = '\0';
17150Sstevel@tonic-gate 	(void) strcat(dat_conf, basedir);
17160Sstevel@tonic-gate 	(void) strcat(dat_conf, DATADM_DAT_CONF);
17170Sstevel@tonic-gate 	datadm_args.da_dat_conf = dat_conf;
17180Sstevel@tonic-gate 	return (0);
17190Sstevel@tonic-gate }
17200Sstevel@tonic-gate 
17210Sstevel@tonic-gate int
main(int argc,char ** argv)17220Sstevel@tonic-gate main(int argc, char **argv)
17230Sstevel@tonic-gate {
17240Sstevel@tonic-gate 	extern char	*optarg;
17250Sstevel@tonic-gate 	extern int	optind;
17260Sstevel@tonic-gate 	char		*basedir = NULL;
17270Sstevel@tonic-gate 	int		c, retval;
17280Sstevel@tonic-gate 	int		op_type = -1, errflg = 0;
17290Sstevel@tonic-gate 
17300Sstevel@tonic-gate 	bzero(&datadm_args, sizeof (datadm_args));
17310Sstevel@tonic-gate 	bzero(&datadm_conf_header, sizeof (datadm_conf_header));
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
17340Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
17350Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
17360Sstevel@tonic-gate #endif
17370Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
17380Sstevel@tonic-gate 
17390Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "vua:r:b:")) != EOF) {
17400Sstevel@tonic-gate 		switch (c) {
17410Sstevel@tonic-gate 		case 'v':
17420Sstevel@tonic-gate 			if (op_type != -1) errflg = 1;
17430Sstevel@tonic-gate 			op_type = DATADM_OP_VIEW;
17440Sstevel@tonic-gate 			break;
17450Sstevel@tonic-gate 		case 'u':
17460Sstevel@tonic-gate 			if (op_type != -1) errflg = 1;
17470Sstevel@tonic-gate 			op_type = DATADM_OP_UPDATE;
17480Sstevel@tonic-gate 			break;
17490Sstevel@tonic-gate 		case 'a':
17500Sstevel@tonic-gate 			if (op_type != -1) errflg = 1;
17510Sstevel@tonic-gate 			op_type = DATADM_OP_ADD;
17520Sstevel@tonic-gate 			datadm_args.da_sp_conf = optarg;
17530Sstevel@tonic-gate 			break;
17540Sstevel@tonic-gate 		case 'r':
17550Sstevel@tonic-gate 			if (op_type != -1) errflg = 1;
17560Sstevel@tonic-gate 			op_type = DATADM_OP_REMOVE;
17570Sstevel@tonic-gate 			datadm_args.da_sp_conf = optarg;
17580Sstevel@tonic-gate 			break;
17590Sstevel@tonic-gate 		case 'b':
17600Sstevel@tonic-gate 			basedir = optarg;
17610Sstevel@tonic-gate 			break;
17620Sstevel@tonic-gate 		default:
17630Sstevel@tonic-gate 			errflg = 1;
17640Sstevel@tonic-gate 			break;
17650Sstevel@tonic-gate 		}
17660Sstevel@tonic-gate 		if (errflg != 0) {
17670Sstevel@tonic-gate 			break;
17680Sstevel@tonic-gate 		}
17690Sstevel@tonic-gate 	}
17700Sstevel@tonic-gate 	if (errflg != 0 || op_type == -1 || optind < argc) {
17710Sstevel@tonic-gate 		datadm_usage();
17720Sstevel@tonic-gate 		return (1);
17730Sstevel@tonic-gate 	}
17740Sstevel@tonic-gate 	datadm_args.da_op_type = op_type;
17750Sstevel@tonic-gate 	if (datadm_locate_dat_conf(basedir)) {
17760Sstevel@tonic-gate 		return (1);
17770Sstevel@tonic-gate 	}
17780Sstevel@tonic-gate 
17790Sstevel@tonic-gate 	retval = (*datadm_ops[op_type])();
17800Sstevel@tonic-gate 	return (retval);
17810Sstevel@tonic-gate }
1782