4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/sockio.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
44 #include <libdllink.h>
45 #include <sys/ib/ibnex/ibnex_devctl.h>
47 #define DATADM_OP_VIEW 0x0000
48 #define DATADM_OP_UPDATE 0x0001
49 #define DATADM_OP_ADD 0x0002
50 #define DATADM_OP_REMOVE 0x0003
51 #define DATADM_NUM_OPS 0x0004
52 #define DATADM_DAT_CONF "/etc/dat/dat.conf"
53 #define DATADM_LINESZ 1024
54 #define DATADM_NUM_SP_TOKENS 7
55 #define DATADM_NUM_DAT_TOKENS 8
56 #define DATADM_DRV_NAME "driver_name"
57 #define DATADM_MAX_TOKENS 16
61 * placed at the top of all entry types
63 typedef struct datadm_entry
{
64 struct datadm_entry
*de_next
;
69 * can be manipulated using datadm_walk_list or
70 * datadm_enqueue_entry
72 typedef struct datadm_list
{
73 datadm_entry_t
*dl_head
;
74 datadm_entry_t
*dl_tail
;
79 * internal representation of the version string in
80 * dat.conf or service_provider.conf. the format is
81 * <dv_name><dv_major>.<dv_minor>
83 typedef struct datadm_version
{
90 * each sp_entry corresponds to an entry in dat.conf or
91 * service_provider.conf. an sp_entry is processed by the
92 * function datadm_process_sp_entry.
94 typedef struct datadm_sp_entry
{
95 datadm_entry_t spe_header
;
97 datadm_version_t spe_api_version
;
101 datadm_version_t spe_sp_version
;
107 * an hca_entry is created whenever a new hca device is
108 * encountered during sp_entry processing. this structure
109 * contains two lists. the sp_list holds sp entries that
110 * are added when sp entry processing occurs. duplicate
111 * sp entries are not added to this list. the ia_list may
112 * be built statically using the information in dat.conf or
113 * dynamically. similar to the sp_list,
114 * the ia_list contains only unique entries.
116 typedef struct datadm_hca_entry
{
117 datadm_entry_t he_header
;
119 datadm_list_t he_sp_list
;
120 datadm_list_t he_ia_list
;
121 } datadm_hca_entry_t
;
124 * an ia_entry is created when a new ia name is encountered
125 * during sp_entry processing or when a new ia name is
126 * discovered by datadm_build_ia_lists. ia_entry holds the ia
127 * device's instance number.
129 typedef struct datadm_ia_entry
{
130 datadm_entry_t iae_header
;
131 char iae_name
[MAXLINKNAMELEN
];
135 * a comment entry represents one of the comment lines at the
136 * top of dat.conf. a list of these lines are saved during the
137 * parsing of dat.conf. these lines are written back to dat.conf
138 * when dat.conf gets regenerated.
140 typedef struct datadm_cmnt_entry
{
141 datadm_entry_t cmnt_header
;
143 } datadm_cmnt_entry_t
;
145 typedef struct datadm_hca_find_by_name
{
147 datadm_hca_entry_t
*hf_hca_entry
;
148 } datadm_hca_find_by_name_t
;
151 * 2nd argument to datadm_hca_entry_find.
152 * hf_hca_entry is filled in if an hca_entry with
153 * a matching he_name is found.
155 typedef struct datadm_hca_find
{
156 datadm_sp_entry_t
*hf_sp_entry
;
157 datadm_hca_entry_t
*hf_hca_entry
;
161 * 2nd argument to datadm_ia_entry_find.
162 * if_ia_entry is filled in if an ia_entry with
163 * a matching ia_name is found.
165 typedef struct datadm_ia_find
{
167 datadm_ia_entry_t
*if_ia_entry
;
171 * this gets passed to datadm_add_plink.
173 typedef struct datadm_fill_ia_list
{
174 datadm_list_t
*ia_hca_list
;
175 dladm_handle_t ia_dlh
;
179 } datadm_fill_ia_list_t
;
182 * this defines the commandline parameters specified
185 typedef struct datadm_args
{
191 static datadm_args_t datadm_args
;
192 static datadm_list_t datadm_conf_header
;
193 static char *datadm_conf_header_default
=
195 "# Copyright (c) 2003, 2010, Oracle and/or its affiliates. "
196 "All rights reserved.\n"
198 "# DAT configuration file.\n"
200 "# This file is updated using the datadm(1) command.\n"
201 "# Do not hand edit this file.\n"
202 "# See datadm(1) man page for more details.\n"
204 "# The fields in this file are -\n"
206 "# IAname version threadsafe default library-path provider-version \\\n"
207 "# instance-data platform-information\n"
211 * common parsing functions.
213 typedef int (*datadm_parse_func_t
)(char *, void *);
214 static int datadm_parse_line(char *, char *[], int *);
215 static int datadm_parse_generic_str(char *, char **);
216 static int datadm_parse_nonnull_str(char *, char **);
217 static int datadm_parse_version(char *, datadm_version_t
*);
218 static int datadm_parse_devname(char *, datadm_sp_entry_t
*);
219 static int datadm_parse_api_version(char *, datadm_sp_entry_t
*);
220 static int datadm_parse_threadsafe(char *, datadm_sp_entry_t
*);
221 static int datadm_parse_default(char *, datadm_sp_entry_t
*);
222 static int datadm_parse_libpath(char *, datadm_sp_entry_t
*);
223 static int datadm_parse_sp_version(char *, datadm_sp_entry_t
*);
224 static int datadm_parse_sp_data(char *, datadm_sp_entry_t
*);
225 static int datadm_parse_ia_name(char *, char *);
230 static void datadm_enqueue_entry(datadm_list_t
*, datadm_entry_t
*);
231 static int datadm_walk_list(datadm_list_t
*,
232 int (*)(datadm_entry_t
*, void *), void *);
233 static int datadm_str_match(char *, char *);
234 static int datadm_version_match(datadm_version_t
*, datadm_version_t
*);
235 static int datadm_sp_entry_match(datadm_sp_entry_t
*, datadm_sp_entry_t
*);
238 * entry allocation/deallocation
240 static datadm_sp_entry_t
*datadm_alloc_sp_entry(void);
241 static datadm_ia_entry_t
*datadm_alloc_ia_entry(void);
242 static datadm_hca_entry_t
*datadm_alloc_hca_entry(void);
243 static datadm_cmnt_entry_t
*datadm_alloc_cmnt_entry(void);
244 static void datadm_free_sp_entry(datadm_sp_entry_t
*);
245 static void datadm_free_ia_entry(datadm_ia_entry_t
*);
246 static void datadm_free_hca_entry(datadm_hca_entry_t
*);
247 static void datadm_free_cmnt_entry(datadm_cmnt_entry_t
*);
251 * high level parsing functions
253 static int datadm_parse_sp_conf(datadm_list_t
*);
254 static int datadm_parse_dat_conf(datadm_list_t
*);
255 static int datadm_process_sp_entry(datadm_list_t
*, datadm_sp_entry_t
*,
259 * ia devices discovery
261 static int datadm_build_ia_lists(datadm_list_t
*);
264 * helper function for OP_REMOVE
266 static void datadm_invalidate_common_sp_entries(datadm_list_t
*,
272 static int datadm_generate_dat_conf(datadm_list_t
*);
273 static int datadm_generate_conf_header(FILE *);
274 static int datadm_generate_conf_entry(FILE *, datadm_ia_entry_t
*,
275 datadm_sp_entry_t
*);
280 static int datadm_view(void);
281 static int datadm_update(void);
282 static int datadm_add(void);
283 static int datadm_remove(void);
288 static void datadm_usage(void);
292 * parse function tables
294 static datadm_parse_func_t datadm_sp_parse_funcs
[DATADM_NUM_SP_TOKENS
] = {
295 (datadm_parse_func_t
)datadm_parse_devname
,
296 (datadm_parse_func_t
)datadm_parse_api_version
,
297 (datadm_parse_func_t
)datadm_parse_threadsafe
,
298 (datadm_parse_func_t
)datadm_parse_default
,
299 (datadm_parse_func_t
)datadm_parse_libpath
,
300 (datadm_parse_func_t
)datadm_parse_sp_version
,
301 (datadm_parse_func_t
)datadm_parse_sp_data
304 static datadm_parse_func_t datadm_dat_parse_funcs
[DATADM_NUM_DAT_TOKENS
] = {
305 (datadm_parse_func_t
)datadm_parse_ia_name
,
306 (datadm_parse_func_t
)datadm_parse_api_version
,
307 (datadm_parse_func_t
)datadm_parse_threadsafe
,
308 (datadm_parse_func_t
)datadm_parse_default
,
309 (datadm_parse_func_t
)datadm_parse_libpath
,
310 (datadm_parse_func_t
)datadm_parse_sp_version
,
311 (datadm_parse_func_t
)datadm_parse_sp_data
,
312 (datadm_parse_func_t
)datadm_parse_devname
318 static int (*datadm_ops
[DATADM_NUM_OPS
])(void) = {
328 (void) fprintf(stderr
, gettext(
331 " -a <service_provider.conf>\n"
332 " -r <service_provider.conf>\n"));
336 datadm_parse_generic_str(char *str
, char **strptr
)
341 *strptr
= (char *)malloc(len
+ 1);
342 if (*strptr
== NULL
) {
345 (void) strcpy(*strptr
, str
);
350 * this function strips off leading and trailing
351 * whitespaces and returns an error for null or
355 datadm_parse_nonnull_str(char *str
, char **strptr
)
360 if (str
[0] == '\0') {
364 for (i
= 0; str
[i
] != '\0'; i
++) {
365 if (!isspace(str
[i
])) {
370 for (; str
[i
] != '\0'; i
++) {
371 if (isspace(str
[i
])) {
376 *strptr
= (char *)malloc(len
+ 1);
377 if (*strptr
== NULL
) {
380 (void) strcpy(*strptr
, start
);
385 * parses the api_version and sp_version fields in
386 * dat.conf and service_provider.conf
389 datadm_parse_version(char *str
, datadm_version_t
*version
)
392 int major_idx
, minor_idx
;
396 for (i
= 0; i
< len
; i
++) {
397 if (isdigit(str
[i
])) break;
403 version
->dv_name
= (char *)malloc(i
+ 1);
404 bcopy(str
, version
->dv_name
, i
);
405 version
->dv_name
[i
] = '\0';
407 version
->dv_name
= NULL
;
411 for (; i
< len
; i
++) {
412 if (!isdigit(str
[i
])) break;
424 for (; i
< len
; i
++) {
425 if (!isdigit(str
[i
])) break;
430 version
->dv_major
= atoi(str
+ major_idx
);
431 version
->dv_minor
= atoi(str
+ minor_idx
);
436 * parses the ia_name field in dat.conf
439 datadm_parse_ia_name(char *str
, char *ia_name
)
441 if (strlen(str
) >= MAXLINKNAMELEN
)
443 (void) strlcpy(ia_name
, str
, MAXLINKNAMELEN
);
448 * parses the device name, strips leading and trailing spaces.
449 * the format should be "driver_name=<dev_name>"
452 datadm_parse_devname(char *str
, datadm_sp_entry_t
*sp_entry
)
454 int len
, dlen
, i
, j
= 0;
455 char *drv_name
= DATADM_DRV_NAME
;
458 dlen
= strlen(drv_name
);
461 * strip out leading spaces and try to match
462 * the expected string
464 for (i
= 0; i
< len
; i
++) {
465 if (isspace(str
[i
]) && j
== 0) {
468 if (str
[i
] == drv_name
[j
]) {
482 * j must be dlen if the matching string is found
489 * skip past the last char of drv_name
494 * strip the spaces before the '='
496 for (; i
< len
; i
++) {
497 if (!isspace(str
[i
])) {
503 * return if the string is too long or if
504 * the '=' isn't found
506 if (i
>= len
|| str
[i
] != '=') {
512 * no string after the equal
516 return (datadm_parse_nonnull_str(str
+ i
, &sp_entry
->spe_devname
));
520 datadm_parse_api_version(char *str
, datadm_sp_entry_t
*sp_entry
)
522 return (datadm_parse_version(str
, &sp_entry
->spe_api_version
));
526 datadm_parse_threadsafe(char *str
, datadm_sp_entry_t
*sp_entry
)
530 if (strcmp(str
, "threadsafe") == 0) {
531 sp_entry
->spe_threadsafe
= 1;
532 } else if (strcmp(str
, "nonthreadsafe") == 0) {
533 sp_entry
->spe_threadsafe
= 0;
541 datadm_parse_default(char *str
, datadm_sp_entry_t
*sp_entry
)
545 if (strcmp(str
, "default") == 0) {
546 sp_entry
->spe_default
= 1;
547 } else if (strcmp(str
, "nondefault") == 0) {
548 sp_entry
->spe_default
= 0;
556 datadm_parse_libpath(char *str
, datadm_sp_entry_t
*sp_entry
)
558 return (datadm_parse_nonnull_str(str
, &sp_entry
->spe_libpath
));
562 datadm_parse_sp_version(char *str
, datadm_sp_entry_t
*sp_entry
)
564 return (datadm_parse_version(str
, &sp_entry
->spe_sp_version
));
568 datadm_parse_sp_data(char *str
, datadm_sp_entry_t
*sp_entry
)
570 return (datadm_parse_generic_str(str
, &sp_entry
->spe_sp_data
));
574 datadm_enqueue_entry(datadm_list_t
*list
, datadm_entry_t
*entry
)
576 if (list
->dl_head
== NULL
) {
577 list
->dl_head
= entry
;
578 list
->dl_tail
= entry
;
581 list
->dl_tail
->de_next
= entry
;
582 list
->dl_tail
= entry
;
588 * iterates through the list applying func on each element.
589 * break and return if func returns non-zero.
592 datadm_walk_list(datadm_list_t
*list
, int (*func
)(datadm_entry_t
*, void *),
595 datadm_entry_t
*entry
;
598 entry
= list
->dl_head
;
599 while (entry
!= NULL
) {
600 retval
= (*func
)(entry
, arg
);
601 if (retval
!= 0) break;
602 entry
= entry
->de_next
;
608 * iterates through the list applying free_func to each element.
609 * list becomes empty when the function returns.
612 datadm_free_list(datadm_list_t
*list
, void (*free_func
)(datadm_entry_t
*))
614 while (list
->dl_head
!= NULL
) {
615 datadm_entry_t
*entry
;
617 entry
= list
->dl_head
;
618 list
->dl_head
= entry
->de_next
;
622 list
->dl_tail
= NULL
;
625 static datadm_sp_entry_t
*
626 datadm_alloc_sp_entry(void)
628 datadm_sp_entry_t
*sp_entry
;
630 sp_entry
= (datadm_sp_entry_t
*)malloc(sizeof (*sp_entry
));
631 if (sp_entry
== NULL
) {
634 bzero(sp_entry
, sizeof (*sp_entry
));
639 datadm_free_sp_entry(datadm_sp_entry_t
*sp_entry
)
641 if (sp_entry
->spe_devname
!= NULL
) {
642 free(sp_entry
->spe_devname
);
643 sp_entry
->spe_devname
= NULL
;
645 if (sp_entry
->spe_api_version
.dv_name
!= NULL
) {
646 free(sp_entry
->spe_api_version
.dv_name
);
647 sp_entry
->spe_api_version
.dv_name
= NULL
;
649 sp_entry
->spe_api_version
.dv_major
= 0;
650 sp_entry
->spe_api_version
.dv_minor
= 0;
651 sp_entry
->spe_threadsafe
= 0;
652 sp_entry
->spe_default
= 0;
653 if (sp_entry
->spe_libpath
!= NULL
) {
654 free(sp_entry
->spe_libpath
);
655 sp_entry
->spe_libpath
= NULL
;
657 if (sp_entry
->spe_sp_version
.dv_name
!= NULL
) {
658 free(sp_entry
->spe_sp_version
.dv_name
);
659 sp_entry
->spe_sp_version
.dv_name
= NULL
;
661 sp_entry
->spe_sp_version
.dv_major
= 0;
662 sp_entry
->spe_sp_version
.dv_minor
= 0;
663 if (sp_entry
->spe_sp_data
!= NULL
) {
664 free(sp_entry
->spe_sp_data
);
665 sp_entry
->spe_sp_data
= NULL
;
671 datadm_str_match(char *s1
, char *s2
)
673 if (s1
== NULL
|| s2
== NULL
) {
678 if (strcmp(s1
, s2
) != 0) {
686 datadm_version_match(datadm_version_t
*v1
, datadm_version_t
*v2
)
688 if (!datadm_str_match(v1
->dv_name
, v2
->dv_name
)) {
691 if (v1
->dv_major
!= v2
->dv_major
) {
694 if (v1
->dv_minor
!= v2
->dv_minor
) {
701 datadm_sp_entry_match(datadm_sp_entry_t
*sp1
, datadm_sp_entry_t
*sp2
)
703 if (!datadm_str_match(sp1
->spe_devname
, sp2
->spe_devname
)) {
706 if (!datadm_version_match(&sp1
->spe_api_version
,
707 &sp2
->spe_api_version
)) {
710 if (sp1
->spe_threadsafe
!= sp2
->spe_threadsafe
) {
713 if (sp1
->spe_default
!= sp2
->spe_default
) {
716 if (!datadm_str_match(sp1
->spe_libpath
, sp2
->spe_libpath
)) {
719 if (!datadm_version_match(&sp1
->spe_sp_version
,
720 &sp2
->spe_sp_version
)) {
723 if (!datadm_str_match(sp1
->spe_sp_data
, sp2
->spe_sp_data
)) {
729 static datadm_ia_entry_t
*
730 datadm_alloc_ia_entry(void)
732 datadm_ia_entry_t
*ia_entry
;
734 ia_entry
= (datadm_ia_entry_t
*)malloc(sizeof (*ia_entry
));
735 if (ia_entry
== NULL
) {
738 bzero(ia_entry
, sizeof (*ia_entry
));
743 datadm_free_ia_entry(datadm_ia_entry_t
*ia_entry
)
748 static datadm_hca_entry_t
*
749 datadm_alloc_hca_entry(void)
751 datadm_hca_entry_t
*hca_entry
;
753 hca_entry
= (datadm_hca_entry_t
*)malloc(sizeof (*hca_entry
));
754 if (hca_entry
== NULL
) {
757 bzero(hca_entry
, sizeof (*hca_entry
));
762 datadm_free_hca_entry(datadm_hca_entry_t
*hca_entry
)
764 if (hca_entry
->he_name
!= NULL
) {
765 free(hca_entry
->he_name
);
766 hca_entry
->he_name
= NULL
;
768 datadm_free_list(&hca_entry
->he_sp_list
,
769 (void (*)(datadm_entry_t
*))datadm_free_sp_entry
);
770 datadm_free_list(&hca_entry
->he_ia_list
,
771 (void (*)(datadm_entry_t
*))datadm_free_ia_entry
);
776 datadm_hca_entry_match(datadm_hca_entry_t
*h1
, datadm_hca_entry_t
*h2
)
778 if (!datadm_str_match(h1
->he_name
, h2
->he_name
)) {
785 datadm_hca_entry_find(datadm_hca_entry_t
*h1
, datadm_hca_find_t
*hf
)
787 if (datadm_str_match(h1
->he_name
, hf
->hf_sp_entry
->spe_devname
)) {
788 hf
->hf_hca_entry
= h1
;
795 datadm_ia_entry_find(datadm_ia_entry_t
*i1
, datadm_ia_find_t
*iaf
)
797 if (strcmp(i1
->iae_name
, iaf
->if_ia_name
) == 0) {
798 iaf
->if_ia_entry
= i1
;
804 static datadm_cmnt_entry_t
*
805 datadm_alloc_cmnt_entry(void)
807 datadm_cmnt_entry_t
*cmnt_entry
;
809 cmnt_entry
= (datadm_cmnt_entry_t
*)malloc(sizeof (*cmnt_entry
));
810 if (cmnt_entry
== NULL
) {
813 bzero(cmnt_entry
, sizeof (*cmnt_entry
));
818 datadm_free_cmnt_entry(datadm_cmnt_entry_t
*cmnt_entry
)
820 if (cmnt_entry
->cmnt_line
!= NULL
) {
821 free(cmnt_entry
->cmnt_line
);
822 cmnt_entry
->cmnt_line
= NULL
;
828 * tokenizes a line and strips off the quotes from quoted strings
831 datadm_parse_line(char *line_buf
, char *tokens
[], int *token_count
)
837 /* the line must not be longer than DATADM_LINESZ */
838 len
= strlen(line_buf
);
839 if (line_buf
[len
- 1] != '\n') {
842 /* discard blank lines and comments */
847 if (len
>= 2 && line_buf
[0] == '#') {
851 /* removes the new line */
852 line_buf
[len
- 1] = '\0';
855 for (i
= 0; i
< len
; i
++) {
858 * start points to the start of
859 * a new token. if start is '"',
860 * we should expect a quoted
863 if (*start
== '\"') {
865 * keep scanning until we
868 if (line_buf
[i
] != '\"') {
872 * skip past the start quote
877 * our token is not a quoted
878 * string. our token ends only
879 * when we hit a whitespace.
881 if (!isspace(line_buf
[i
])) {
886 * nullify the end quote (if any)
887 * and update the tokens array.
890 tokens
[count
] = start
;
897 if (isspace(line_buf
[i
])) {
900 start
= &line_buf
[i
];
903 if (count
== DATADM_MAX_TOKENS
) {
909 tokens
[count
] = start
;
913 *token_count
= count
;
918 * attempts to save sp_entry into hca_list.
919 * becomes no-op if sp entry already exists.
920 * new hca entries and ia entries are created as needed.
923 datadm_process_sp_entry(datadm_list_t
*hca_list
, datadm_sp_entry_t
*sp_entry
,
926 datadm_hca_find_t hca_find
;
927 datadm_ia_find_t ia_find
;
928 datadm_hca_entry_t
*hca_entry
;
930 hca_find
.hf_sp_entry
= sp_entry
;
931 hca_find
.hf_hca_entry
= NULL
;
932 (void) datadm_walk_list(hca_list
, (int (*)(datadm_entry_t
*, void *))
933 datadm_hca_entry_find
, (void *)&hca_find
);
935 if (hca_find
.hf_hca_entry
== NULL
) {
939 * hca_entry not found, need to create
942 hca_entry
= datadm_alloc_hca_entry();
943 if (hca_entry
== NULL
) {
946 dlen
= strlen(sp_entry
->spe_devname
);
947 hca_entry
->he_name
= (char *)malloc(dlen
+ 1);
948 if (hca_entry
->he_name
== NULL
) {
949 datadm_free_hca_entry(hca_entry
);
952 (void) strcpy(hca_entry
->he_name
, sp_entry
->spe_devname
);
953 datadm_enqueue_entry(hca_list
, (datadm_entry_t
*)hca_entry
);
955 hca_entry
= hca_find
.hf_hca_entry
;
957 if (ia_name
== NULL
) {
960 ia_find
.if_ia_name
= ia_name
;
961 ia_find
.if_ia_entry
= NULL
;
962 (void) datadm_walk_list(&hca_entry
->he_ia_list
,
963 (int (*)(datadm_entry_t
*, void *))datadm_ia_entry_find
, &ia_find
);
965 if (ia_find
.if_ia_entry
== NULL
) {
966 datadm_ia_entry_t
*ia_entry
;
969 * ia_entry not found, need to create
972 ia_entry
= datadm_alloc_ia_entry();
973 if (ia_entry
== NULL
) {
976 (void) strlcpy(ia_entry
->iae_name
, ia_name
, MAXLINKNAMELEN
);
977 datadm_enqueue_entry(&hca_entry
->he_ia_list
,
978 (datadm_entry_t
*)ia_entry
);
983 if (datadm_walk_list(&hca_entry
->he_sp_list
,
984 (int (*)(datadm_entry_t
*, void *))datadm_sp_entry_match
,
989 * only insert sp_entry if it is not found.
991 datadm_enqueue_entry(&hca_entry
->he_sp_list
,
992 (datadm_entry_t
*)sp_entry
);
998 * parses service_provider.conf
1001 datadm_parse_sp_conf(datadm_list_t
*hca_list
)
1003 datadm_sp_entry_t
*sp_entry
;
1005 char *sp_conf
= datadm_args
.da_sp_conf
;
1006 char *tokens
[DATADM_MAX_TOKENS
];
1007 char line_buf
[DATADM_LINESZ
];
1009 int token_count
= 0;
1012 sp_file
= fopen(sp_conf
, "r");
1013 if (sp_file
== NULL
) {
1014 (void) fprintf(stderr
,
1015 gettext("datadm: cannot open %s\n"), sp_conf
);
1020 bzero(line_buf
, DATADM_LINESZ
);
1021 if (fgets(line_buf
, DATADM_LINESZ
, sp_file
) == NULL
) {
1026 retval
= datadm_parse_line(line_buf
, tokens
, &token_count
);
1028 (void) fprintf(stderr
, gettext(
1029 "datadm: %s: line %d exceeded max length %d\n"),
1030 sp_conf
, line_count
, DATADM_LINESZ
);
1033 if (token_count
== 0) continue;
1034 if (token_count
== DATADM_NUM_SP_TOKENS
) {
1037 sp_entry
= datadm_alloc_sp_entry();
1038 if (sp_entry
== NULL
) {
1044 * sp_entry gets filled incrementally by
1045 * each parsing function
1047 for (i
= 0; i
< DATADM_NUM_SP_TOKENS
&&
1049 retval
= (*datadm_sp_parse_funcs
[i
])
1050 (tokens
[i
], (void *)sp_entry
);
1053 (void) fprintf(stderr
, gettext(
1054 "datadm: parse error: %s, "
1055 "line %d, token: %s\n"),
1056 sp_conf
, line_count
, tokens
[i
- 1]);
1057 datadm_free_sp_entry(sp_entry
);
1062 retval
= datadm_process_sp_entry(hca_list
,
1065 datadm_free_sp_entry(sp_entry
);
1073 (void) fprintf(stderr
, gettext(
1074 "datadm: parse error: %s, line %d, "
1075 "# of tokens: %d, expected %d\n"), sp_conf
,
1076 line_count
, token_count
, DATADM_NUM_SP_TOKENS
);
1082 datadm_free_list(hca_list
,
1083 (void (*)(datadm_entry_t
*))datadm_free_hca_entry
);
1085 (void) fclose(sp_file
);
1093 datadm_parse_dat_conf(datadm_list_t
*hca_list
)
1095 boolean_t save_header
= B_TRUE
;
1096 datadm_sp_entry_t
*sp_entry
;
1098 char *dat_conf
= datadm_args
.da_dat_conf
;
1099 char *tokens
[DATADM_MAX_TOKENS
];
1100 char line_buf
[DATADM_LINESZ
];
1102 int token_count
= 0;
1105 dat_file
= fopen(dat_conf
, "r");
1106 if (dat_file
== NULL
) {
1107 /* dat.conf not existing is not an error for OP_ADD */
1108 if (datadm_args
.da_op_type
== DATADM_OP_ADD
) {
1111 (void) fprintf(stderr
, gettext("datadm: cannot open %s\n"),
1117 bzero(line_buf
, DATADM_LINESZ
);
1118 if (fgets(line_buf
, DATADM_LINESZ
, dat_file
) == NULL
) {
1123 retval
= datadm_parse_line(line_buf
, tokens
, &token_count
);
1125 (void) fprintf(stderr
, gettext(
1126 "datadm: %s: line %d exceeded max length %d\n"),
1127 dat_conf
, line_count
, DATADM_LINESZ
);
1130 if (token_count
== 0) {
1131 datadm_cmnt_entry_t
*cmnt_entry
;
1135 * comments are saved only if they are
1136 * at the top of dat.conf.
1138 if (!save_header
) continue;
1139 cmnt_entry
= datadm_alloc_cmnt_entry();
1140 if (cmnt_entry
== NULL
) {
1141 perror("datadm: malloc");
1145 cmnt_len
= strlen(line_buf
);
1146 cmnt_entry
->cmnt_line
= (char *)malloc(cmnt_len
+ 1);
1147 if (cmnt_entry
->cmnt_line
== NULL
) {
1148 perror("datadm: malloc");
1149 datadm_free_cmnt_entry(cmnt_entry
);
1153 (void) strncpy(cmnt_entry
->cmnt_line
,
1154 line_buf
, cmnt_len
);
1155 cmnt_entry
->cmnt_line
[cmnt_len
] = '\0';
1156 datadm_enqueue_entry(&datadm_conf_header
,
1157 (datadm_entry_t
*)cmnt_entry
);
1160 if (token_count
== DATADM_NUM_DAT_TOKENS
) {
1162 char ia_name
[MAXLINKNAMELEN
];
1165 * we stop saving comment lines once
1166 * we see the first valid line.
1168 save_header
= B_FALSE
;
1169 sp_entry
= datadm_alloc_sp_entry();
1170 if (sp_entry
== NULL
) {
1176 * sp_entry gets filled incrementally by
1177 * each parsing function
1179 for (i
= 0; i
< DATADM_NUM_DAT_TOKENS
&&
1185 * the first token (ia name)
1186 * does not belong to an
1189 arg
= (void *)ia_name
;
1191 arg
= (void *)sp_entry
;
1193 retval
= (*datadm_dat_parse_funcs
[i
])
1197 (void) fprintf(stderr
, gettext(
1198 "datadm: parse error: %s, "
1199 "line %d, token: %s\n"), dat_conf
,
1200 line_count
, tokens
[i
- 1]);
1201 datadm_free_sp_entry(sp_entry
);
1207 * we ignore the ibds in dat.conf if we are
1210 if (datadm_args
.da_op_type
== DATADM_OP_UPDATE
) {
1211 retval
= datadm_process_sp_entry(hca_list
,
1214 retval
= datadm_process_sp_entry(hca_list
,
1218 datadm_free_sp_entry(sp_entry
);
1226 (void) fprintf(stderr
, gettext(
1227 "datadm: parse error: %s, line %d, "
1228 "# of tokens: %d, expected %d\n"), dat_conf
,
1229 line_count
, token_count
, DATADM_NUM_DAT_TOKENS
);
1235 datadm_free_list(&datadm_conf_header
,
1236 (void (*)(datadm_entry_t
*))datadm_free_cmnt_entry
);
1237 datadm_free_list(hca_list
,
1238 (void (*)(datadm_entry_t
*))datadm_free_hca_entry
);
1240 (void) fclose(dat_file
);
1245 * used by OP_REMOVE to invalidate common sp entries between hl1 and hl2.
1246 * invalid sp entries will be ignored by datadm_generate_dat_conf.
1249 datadm_invalidate_common_sp_entries(datadm_list_t
*hl1
, datadm_list_t
*hl2
)
1251 datadm_entry_t
*he1
, *he2
;
1254 while (he1
!= NULL
) {
1256 while (he2
!= NULL
) {
1257 datadm_entry_t
*se1
, *se2
;
1259 if (!datadm_hca_entry_match(
1260 (datadm_hca_entry_t
*)he1
,
1261 (datadm_hca_entry_t
*)he2
)) {
1265 se1
= ((datadm_hca_entry_t
*)he1
)->he_sp_list
.dl_head
;
1266 while (se1
!= NULL
) {
1267 se2
= ((datadm_hca_entry_t
*)he2
)->
1269 while (se2
!= NULL
) {
1270 if (!datadm_sp_entry_match(
1271 (datadm_sp_entry_t
*)se1
,
1272 (datadm_sp_entry_t
*)se2
)) {
1276 ((datadm_sp_entry_t
*)se1
)->
1289 datadm_hca_entry_find_by_name(datadm_hca_entry_t
*h1
,
1290 datadm_hca_find_by_name_t
*hf
)
1292 if (datadm_str_match(h1
->he_name
, hf
->hf_name
)) {
1293 hf
->hf_hca_entry
= h1
;
1299 datadm_hca_entry_t
*
1300 datadm_hca_lookup_by_name(datadm_list_t
*hca_list
, char *hca_driver_name
)
1302 datadm_hca_find_by_name_t hf
;
1304 hf
.hf_name
= hca_driver_name
;
1305 hf
.hf_hca_entry
= NULL
;
1306 (void) datadm_walk_list(hca_list
,
1307 (int (*)(datadm_entry_t
*, void *))datadm_hca_entry_find_by_name
,
1309 return (hf
.hf_hca_entry
);
1313 datadm_add_plink(char *linkname
, datadm_fill_ia_list_t
*ia_args
)
1315 datalink_class_t
class;
1316 datalink_id_t linkid
;
1317 dladm_ib_attr_t ib_attr
;
1318 ibnex_ctl_query_hca_t query_hca
;
1319 datadm_hca_entry_t
*hca
;
1321 datadm_ia_find_t ia_find
;
1322 datadm_ia_entry_t
*ia_entry
;
1324 if ((dladm_name2info(ia_args
->ia_dlh
, linkname
, &linkid
, NULL
, &class,
1325 NULL
) != DLADM_STATUS_OK
) ||
1326 (class != DATALINK_CLASS_PART
) ||
1327 (dladm_part_info(ia_args
->ia_dlh
, linkid
, &ib_attr
,
1328 DLADM_OPT_ACTIVE
) != DLADM_STATUS_OK
)) {
1332 (void) strlcpy(req
.lifr_name
, linkname
, sizeof (req
.lifr_name
));
1334 * we don't really need to know the ip address.
1335 * we just want to check if the device is plumbed
1338 if (ioctl(ia_args
->ia_sock_fd_v4
, SIOCGLIFADDR
, (caddr_t
)&req
) != 0) {
1340 * we try v6 if the v4 address isn't found.
1342 if (ioctl(ia_args
->ia_sock_fd_v6
, SIOCGLIFADDR
,
1343 (caddr_t
)&req
) != 0)
1347 bzero(&query_hca
, sizeof (query_hca
));
1348 query_hca
.hca_guid
= ib_attr
.dia_hca_guid
;
1349 if (ioctl(ia_args
->ia_ibnex_fd
, IBNEX_CTL_QUERY_HCA
, &query_hca
) == -1)
1352 if ((hca
= datadm_hca_lookup_by_name(ia_args
->ia_hca_list
,
1353 query_hca
.hca_info
.hca_driver_name
)) == NULL
)
1356 ia_find
.if_ia_name
= linkname
;
1357 ia_find
.if_ia_entry
= NULL
;
1358 (void) datadm_walk_list(&hca
->he_ia_list
,
1359 (int (*)(datadm_entry_t
*, void *))
1360 datadm_ia_entry_find
, &ia_find
);
1362 if (ia_find
.if_ia_entry
== NULL
) {
1364 * we insert an ia entry only if
1367 ia_entry
= datadm_alloc_ia_entry();
1368 if (ia_entry
!= NULL
) {
1369 (void) strlcpy(ia_entry
->iae_name
, linkname
,
1371 datadm_enqueue_entry(&hca
->he_ia_list
,
1372 (datadm_entry_t
*)ia_entry
);
1380 * build ia lists for each hca_list element
1383 datadm_build_ia_lists(datadm_list_t
*hca_list
)
1386 datadm_fill_ia_list_t ia_args
;
1392 if (dladm_open(&dlh
) != DLADM_STATUS_OK
)
1395 if ((fd
= open(IBNEX_DEVCTL_DEV
, O_RDONLY
)) < 0)
1398 if ((sv4
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
1399 perror("datadm: socket");
1403 if ((sv6
= socket(AF_INET6
, SOCK_DGRAM
, 0)) < 0) {
1404 perror("datadm: socket");
1408 ia_args
.ia_hca_list
= hca_list
;
1409 ia_args
.ia_dlh
= dlh
;
1410 ia_args
.ia_ibnex_fd
= fd
;
1411 ia_args
.ia_sock_fd_v4
= sv4
;
1412 ia_args
.ia_sock_fd_v6
= sv6
;
1414 dlpi_walk((boolean_t (*) (const char *, void *))datadm_add_plink
,
1431 datadm_generate_conf_entry(FILE *outfile
, datadm_ia_entry_t
*ia_entry
,
1432 datadm_sp_entry_t
*sp_entry
)
1436 retval
= fprintf(outfile
,
1437 "%s %s%d.%d %s %s %s %s%d.%d \"%s\" \"%s%s%s\"\n",
1439 (sp_entry
->spe_api_version
.dv_name
?
1440 sp_entry
->spe_api_version
.dv_name
: ""),
1441 sp_entry
->spe_api_version
.dv_major
,
1442 sp_entry
->spe_api_version
.dv_minor
,
1443 (sp_entry
->spe_threadsafe
? "threadsafe" : "nonthreadsafe"),
1444 (sp_entry
->spe_default
? "default" : "nondefault"),
1445 sp_entry
->spe_libpath
,
1446 (sp_entry
->spe_sp_version
.dv_name
?
1447 sp_entry
->spe_sp_version
.dv_name
: ""),
1448 sp_entry
->spe_sp_version
.dv_major
,
1449 sp_entry
->spe_sp_version
.dv_minor
,
1450 sp_entry
->spe_sp_data
,
1451 DATADM_DRV_NAME
, "=", sp_entry
->spe_devname
);
1460 * generate dat.conf header
1463 datadm_generate_conf_header(FILE *outfile
)
1465 datadm_entry_t
*cep
;
1466 datadm_cmnt_entry_t
*cmnt
;
1469 cep
= datadm_conf_header
.dl_head
;
1472 * if dat.conf doesn't have a header, we prepend a
1475 retval
= fprintf(outfile
, "%s", datadm_conf_header_default
);
1478 while (cep
!= NULL
) {
1479 cmnt
= (datadm_cmnt_entry_t
*)cep
;
1480 if (cmnt
->cmnt_line
!= NULL
) {
1483 retval
= fprintf(outfile
, "%s", cmnt
->cmnt_line
);
1489 * append a newline if the comment line doesn't
1492 len
= strlen(cmnt
->cmnt_line
);
1493 if (cmnt
->cmnt_line
[len
- 1] != '\n') {
1494 retval
= fprintf(outfile
, "\n");
1510 * outputs dat.conf to stdout or to basedir/etc/dat/dat.conf
1513 datadm_generate_dat_conf(datadm_list_t
*hca_list
)
1515 FILE *outfile
= NULL
;
1516 char *dat_conf
= datadm_args
.da_dat_conf
;
1517 datadm_entry_t
*hep
;
1520 if (datadm_args
.da_op_type
== DATADM_OP_VIEW
) {
1523 outfile
= fopen(dat_conf
, "w+");
1524 if (outfile
== NULL
) {
1525 (void) fprintf(stderr
, gettext(
1526 "datadm: cannot open %s: %s\n"),
1527 dat_conf
, strerror(errno
));
1531 if (outfile
!= stdout
) {
1533 * do not generate the header if we are
1534 * printing to the screen
1536 retval
= datadm_generate_conf_header(outfile
);
1541 hep
= hca_list
->dl_head
;
1542 while (hep
!= NULL
) {
1543 datadm_entry_t
*iep
;
1545 iep
= ((datadm_hca_entry_t
*)hep
)->he_ia_list
.dl_head
;
1546 while (iep
!= NULL
) {
1547 datadm_entry_t
*sep
;
1549 sep
= ((datadm_hca_entry_t
*)hep
)->he_sp_list
.dl_head
;
1550 while (sep
!= NULL
) {
1551 if (((datadm_sp_entry_t
*)sep
)->spe_invalid
) {
1555 retval
= datadm_generate_conf_entry(outfile
,
1556 (datadm_ia_entry_t
*)iep
,
1557 (datadm_sp_entry_t
*)sep
);
1567 retval
= fflush(outfile
);
1569 if (outfile
!= stdout
) {
1570 (void) fclose(outfile
);
1573 perror("datadm: fprintf");
1582 datadm_list_t hca_list
;
1584 bzero(&hca_list
, sizeof (hca_list
));
1586 retval
= datadm_parse_dat_conf(&hca_list
);
1590 retval
= datadm_generate_dat_conf(&hca_list
);
1596 datadm_free_list(&datadm_conf_header
,
1597 (void (*)(datadm_entry_t
*))datadm_free_cmnt_entry
);
1598 datadm_free_list(&hca_list
,
1599 (void (*)(datadm_entry_t
*))datadm_free_hca_entry
);
1607 datadm_list_t hca_list
;
1609 bzero(&hca_list
, sizeof (hca_list
));
1611 retval
= datadm_parse_dat_conf(&hca_list
);
1615 retval
= datadm_build_ia_lists(&hca_list
);
1619 retval
= datadm_generate_dat_conf(&hca_list
);
1625 datadm_free_list(&datadm_conf_header
,
1626 (void (*)(datadm_entry_t
*))datadm_free_cmnt_entry
);
1627 datadm_free_list(&hca_list
,
1628 (void (*)(datadm_entry_t
*))datadm_free_hca_entry
);
1636 datadm_list_t hca_list
;
1638 bzero(&hca_list
, sizeof (hca_list
));
1640 retval
= datadm_parse_dat_conf(&hca_list
);
1644 retval
= datadm_parse_sp_conf(&hca_list
);
1648 retval
= datadm_build_ia_lists(&hca_list
);
1652 retval
= datadm_generate_dat_conf(&hca_list
);
1658 datadm_free_list(&datadm_conf_header
,
1659 (void (*)(datadm_entry_t
*))datadm_free_cmnt_entry
);
1660 datadm_free_list(&hca_list
,
1661 (void (*)(datadm_entry_t
*))datadm_free_hca_entry
);
1669 datadm_list_t hca_list
;
1670 datadm_list_t hca_list2
;
1672 bzero(&hca_list
, sizeof (hca_list
));
1673 bzero(&hca_list2
, sizeof (hca_list2
));
1675 retval
= datadm_parse_dat_conf(&hca_list
);
1679 retval
= datadm_parse_sp_conf(&hca_list2
);
1683 datadm_invalidate_common_sp_entries(&hca_list
, &hca_list2
);
1685 retval
= datadm_generate_dat_conf(&hca_list
);
1691 datadm_free_list(&datadm_conf_header
,
1692 (void (*)(datadm_entry_t
*))datadm_free_cmnt_entry
);
1693 datadm_free_list(&hca_list
,
1694 (void (*)(datadm_entry_t
*))datadm_free_hca_entry
);
1695 datadm_free_list(&hca_list2
,
1696 (void (*)(datadm_entry_t
*))datadm_free_hca_entry
);
1701 datadm_locate_dat_conf(char *basedir
)
1705 if (basedir
== NULL
) {
1706 datadm_args
.da_dat_conf
= DATADM_DAT_CONF
;
1709 dat_conf
= (char *)malloc(strlen(basedir
) +
1710 strlen(DATADM_DAT_CONF
) + 1);
1711 if (dat_conf
== NULL
) {
1715 (void) strcat(dat_conf
, basedir
);
1716 (void) strcat(dat_conf
, DATADM_DAT_CONF
);
1717 datadm_args
.da_dat_conf
= dat_conf
;
1722 main(int argc
, char **argv
)
1724 extern char *optarg
;
1726 char *basedir
= NULL
;
1728 int op_type
= -1, errflg
= 0;
1730 bzero(&datadm_args
, sizeof (datadm_args
));
1731 bzero(&datadm_conf_header
, sizeof (datadm_conf_header
));
1733 (void) setlocale(LC_ALL
, "");
1734 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
1735 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
1737 (void) textdomain(TEXT_DOMAIN
);
1739 while ((c
= getopt(argc
, argv
, "vua:r:b:")) != EOF
) {
1742 if (op_type
!= -1) errflg
= 1;
1743 op_type
= DATADM_OP_VIEW
;
1746 if (op_type
!= -1) errflg
= 1;
1747 op_type
= DATADM_OP_UPDATE
;
1750 if (op_type
!= -1) errflg
= 1;
1751 op_type
= DATADM_OP_ADD
;
1752 datadm_args
.da_sp_conf
= optarg
;
1755 if (op_type
!= -1) errflg
= 1;
1756 op_type
= DATADM_OP_REMOVE
;
1757 datadm_args
.da_sp_conf
= optarg
;
1770 if (errflg
!= 0 || op_type
== -1 || optind
< argc
) {
1774 datadm_args
.da_op_type
= op_type
;
1775 if (datadm_locate_dat_conf(basedir
)) {
1779 retval
= (*datadm_ops
[op_type
])();