1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * ns_fnutils.c
23  *
24  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <synch.h>
33 #include <rpc/rpc.h>
34 #include <xfn/xfn.h>
35 #include "automount.h"
36 #include "ns_fnutils.h"
37 
38 
39 /*
40  * FNS file system reference and address types.  Each array is indexed
41  * using the corresponding enumeration (reftype_t or addrtype_t).
42  */
43 const char *reftypes[] = {
44 	"onc_fn_fs",
45 };
46 
47 const char *addrtypes[] = {
48 	"onc_fn_fs_mount",
49 	"onc_fn_fs_host",
50 	"onc_fn_fs_user",
51 };
52 
53 
54 FN_string_t		*empty_string = NULL;
55 FN_composite_name_t	*empty_cname = NULL;
56 FN_composite_name_t	*slash_cname = NULL;
57 
58 
59 int
init_fn(void)60 init_fn(void)
61 {
62 	static mutex_t	init_lock = DEFAULTMUTEX;
63 
64 	if (slash_cname != NULL) {
65 		return (0);
66 	}
67 
68 	mutex_lock(&init_lock);
69 
70 	if (empty_string == NULL) {
71 		if ((empty_string = fn_string_create()) == NULL) {
72 			log_mem_failure();
73 			goto unlock;
74 		}
75 	}
76 	if (empty_cname == NULL) {
77 		if ((empty_cname = new_cname("")) == NULL) {
78 			goto unlock;
79 		}
80 	}
81 	if (slash_cname == NULL) {
82 		if ((slash_cname = new_cname("/")) == NULL) {
83 			goto unlock;
84 		}
85 	}
86 unlock:
87 	mutex_unlock(&init_lock);
88 	return ((slash_cname != NULL) ? 0 : -1);
89 }
90 
91 
92 FN_composite_name_t *
new_cname(const char * str)93 new_cname(const char *str)
94 {
95 	FN_string_t		*string;
96 	FN_composite_name_t	*cname;
97 
98 	string = fn_string_from_str((unsigned char *)str);
99 	if (string == NULL) {
100 		if (verbose) {
101 			syslog(LOG_ERR, "Could not create FNS string object");
102 		}
103 		return (NULL);
104 	}
105 	cname = fn_composite_name_from_string(string);
106 	fn_string_destroy(string);
107 	if ((cname == NULL) && verbose) {
108 		syslog(LOG_ERR, "Could not create FNS composite name object");
109 	}
110 	return (cname);
111 }
112 
113 
114 reftype_t
reftype(const FN_ref_t * ref)115 reftype(const FN_ref_t *ref)
116 {
117 	reftype_t	rtype;
118 
119 	for (rtype = 0; rtype < NUM_REFTYPES; rtype++) {
120 		if (ident_str_equal(fn_ref_type(ref), reftypes[rtype])) {
121 			break;
122 		}
123 	}
124 	return (rtype);
125 }
126 
127 
128 addrtype_t
addrtype(const FN_ref_addr_t * addr)129 addrtype(const FN_ref_addr_t *addr)
130 {
131 	addrtype_t		atype;
132 	const FN_identifier_t	*ident = fn_ref_addr_type(addr);
133 
134 	for (atype = 0; atype < NUM_ADDRTYPES; atype++) {
135 		if (ident_str_equal(ident, addrtypes[atype])) {
136 			break;
137 		}
138 	}
139 	return (atype);
140 }
141 
142 
143 bool_t
ident_equal(const FN_identifier_t * id1,const FN_identifier_t * id2)144 ident_equal(const FN_identifier_t *id1, const FN_identifier_t *id2)
145 {
146 	return ((id1->format == id2->format) &&
147 	    (id1->length == id2->length) &&
148 	    (memcmp(id1->contents, id2->contents, id1->length) == 0));
149 }
150 
151 
152 bool_t
ident_str_equal(const FN_identifier_t * id,const char * str)153 ident_str_equal(const FN_identifier_t *id, const char *str)
154 {
155 	return ((id->format == FN_ID_STRING) &&
156 	    (id->length == strlen(str)) &&
157 	    (strncmp(str, id->contents, id->length) == 0));
158 }
159 
160 
161 void
logstat(const FN_status_t * status,const char * msg1,const char * msg2)162 logstat(const FN_status_t *status, const char *msg1, const char *msg2)
163 {
164 	FN_string_t	*desc_string;
165 	const char	*desc = NULL;
166 
167 	if (verbose) {
168 		desc_string = fn_status_description(status, DETAIL, NULL);
169 		if (desc_string != NULL) {
170 			desc = (const char *)fn_string_str(desc_string, NULL);
171 		}
172 		if (desc == NULL) {
173 			desc = "(no status description)";
174 		}
175 		syslog(LOG_ERR, "FNS %s %s: %s (%u)",
176 		    msg1, msg2, desc, fn_status_code(status));
177 		fn_string_destroy(desc_string);
178 	}
179 }
180 
181 
182 bool_t
transient(const FN_status_t * status)183 transient(const FN_status_t *status)
184 {
185 	unsigned int statcode;
186 
187 	statcode = fn_status_code(status);
188 	if (statcode == FN_E_LINK_ERROR) {
189 		statcode = fn_status_link_code(status);
190 	}
191 	switch (statcode) {
192 	case FN_E_COMMUNICATION_FAILURE:
193 	case FN_E_CTX_UNAVAILABLE:
194 	case FN_E_INSUFFICIENT_RESOURCES:
195 	case FN_E_INVALID_ENUM_HANDLE:
196 	case FN_E_PARTIAL_RESULT:
197 	case FN_E_UNSPECIFIED_ERROR:
198 		return (TRUE);
199 	default:
200 		return (FALSE);
201 	}
202 }
203 
204 
205 void
log_mem_failure(void)206 log_mem_failure(void)
207 {
208 	if (verbose) {
209 		syslog(LOG_ERR, "Memory allocation failed");
210 	}
211 }
212