xref: /illumos-gate/usr/src/common/smbsrv/smb_netbios_util.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
1*da6c28aaSamw /*
2*da6c28aaSamw  * CDDL HEADER START
3*da6c28aaSamw  *
4*da6c28aaSamw  * The contents of this file are subject to the terms of the
5*da6c28aaSamw  * Common Development and Distribution License (the "License").
6*da6c28aaSamw  * You may not use this file except in compliance with the License.
7*da6c28aaSamw  *
8*da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10*da6c28aaSamw  * See the License for the specific language governing permissions
11*da6c28aaSamw  * and limitations under the License.
12*da6c28aaSamw  *
13*da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14*da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16*da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17*da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*da6c28aaSamw  *
19*da6c28aaSamw  * CDDL HEADER END
20*da6c28aaSamw  */
21*da6c28aaSamw /*
22*da6c28aaSamw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*da6c28aaSamw  * Use is subject to license terms.
24*da6c28aaSamw  */
25*da6c28aaSamw 
26*da6c28aaSamw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*da6c28aaSamw 
28*da6c28aaSamw #ifdef _KERNEL
29*da6c28aaSamw #include <sys/types.h>
30*da6c28aaSamw #include <sys/sunddi.h>
31*da6c28aaSamw #else
32*da6c28aaSamw #include <string.h>
33*da6c28aaSamw #endif
34*da6c28aaSamw #include <smbsrv/string.h>
35*da6c28aaSamw #include <smbsrv/ctype.h>
36*da6c28aaSamw #include <smbsrv/netbios.h>
37*da6c28aaSamw 
38*da6c28aaSamw static int domainname_is_valid(char *domain_name);
39*da6c28aaSamw 
40*da6c28aaSamw /*
41*da6c28aaSamw  * Routines than support name compression.
42*da6c28aaSamw  *
43*da6c28aaSamw  *   The NetBIOS name representation in all NetBIOS packets (for NAME,
44*da6c28aaSamw  *   SESSION, and DATAGRAM services) is defined in the Domain Name
45*da6c28aaSamw  *   Service RFC 883[3] as "compressed" name messages.  This format is
46*da6c28aaSamw  *   called "second-level encoding" in the section entitled
47*da6c28aaSamw  *   "Representation of NetBIOS Names" in the Concepts and Methods
48*da6c28aaSamw  *   document.
49*da6c28aaSamw  *
50*da6c28aaSamw  *   For ease of description, the first two paragraphs from page 31,
51*da6c28aaSamw  *   the section titled "Domain name representation and compression",
52*da6c28aaSamw  *   of RFC 883 are replicated here:
53*da6c28aaSamw  *
54*da6c28aaSamw  *        Domain names messages are expressed in terms of a sequence
55*da6c28aaSamw  *        of labels.  Each label is represented as a one octet length
56*da6c28aaSamw  *        field followed by that number of octets.  Since every domain
57*da6c28aaSamw  *        name ends with the null label of the root, a compressed
58*da6c28aaSamw  *        domain name is terminated by a length byte of zero.  The
59*da6c28aaSamw  *        high order two bits of the length field must be zero, and
60*da6c28aaSamw  *        the remaining six bits of the length field limit the label
61*da6c28aaSamw  *        to 63 octets or less.
62*da6c28aaSamw  *
63*da6c28aaSamw  *        To simplify implementations, the total length of label
64*da6c28aaSamw  *        octets and label length octets that make up a domain name is
65*da6c28aaSamw  *        restricted to 255 octets or less.
66*da6c28aaSamw  *
67*da6c28aaSamw  *   The following is the uncompressed representation of the NetBIOS name
68*da6c28aaSamw  *   "FRED ", which is the 4 ASCII characters, F, R, E, D, followed by 12
69*da6c28aaSamw  *   space characters (0x20).  This name has the SCOPE_ID: "NETBIOS.COM"
70*da6c28aaSamw  *
71*da6c28aaSamw  *           EGFCEFEECACACACACACACACACACACACA.NETBIOS.COM
72*da6c28aaSamw  *
73*da6c28aaSamw  *   This uncompressed representation of names is called "first-level
74*da6c28aaSamw  *   encoding" in the section entitled "Representation of NetBIOS Names"
75*da6c28aaSamw  *   in the Concepts and Methods document.
76*da6c28aaSamw  *
77*da6c28aaSamw  *   The following is a pictographic representation of the compressed
78*da6c28aaSamw  *   representation of the previous uncompressed Domain Name
79*da6c28aaSamw  *   representation.
80*da6c28aaSamw  *
81*da6c28aaSamw  *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
82*da6c28aaSamw  *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
83*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84*da6c28aaSamw  *   |      0x20     |    E (0x45)   |    G (0x47)   |    F (0x46)   |
85*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86*da6c28aaSamw  *   |    C (0x43)   |    E (0x45)   |    F (0x46)   |    E (0x45)   |
87*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88*da6c28aaSamw  *   |    E (0x45)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
89*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90*da6c28aaSamw  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
91*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92*da6c28aaSamw  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
93*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94*da6c28aaSamw  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
95*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96*da6c28aaSamw  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
97*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98*da6c28aaSamw  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
99*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100*da6c28aaSamw  *   |    A (0X41)   |      0x07     |    N (0x4E)   |    E (0x45)   |
101*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102*da6c28aaSamw  *   |    T (0x54)   |    B (0x42)   |    I (0x49)   |    O (0x4F)   |
103*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104*da6c28aaSamw  *   |    S (0x53)   |      0x03     |    C (0x43)   |    O (0x4F)   |
105*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106*da6c28aaSamw  *   |    M (0x4D)   |      0x00     |
107*da6c28aaSamw  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108*da6c28aaSamw  *
109*da6c28aaSamw  *   Each section of a domain name is called a label [7 (page 31)].  A
110*da6c28aaSamw  *   label can be a maximum of 63 bytes.  The first byte of a label in
111*da6c28aaSamw  *   compressed representation is the number of bytes in the label.  For
112*da6c28aaSamw  *   the above example, the first 0x20 is the number of bytes in the
113*da6c28aaSamw  *   left-most label, EGFCEFEECACACACACACACACACACACACA, of the domain
114*da6c28aaSamw  *   name.  The bytes following the label length count are the characters
115*da6c28aaSamw  *   of the label.  The following labels are in sequence after the first
116*da6c28aaSamw  *   label, which is the encoded NetBIOS name, until a zero (0x00) length
117*da6c28aaSamw  *   count.  The zero length count represents the root label, which is
118*da6c28aaSamw  *   always null.
119*da6c28aaSamw  *
120*da6c28aaSamw  *   A label length count is actually a 6-bit field in the label length
121*da6c28aaSamw  *   field.  The most significant 2 bits of the field, bits 7 and 6, are
122*da6c28aaSamw  *   flags allowing an escape from the above compressed representation.
123*da6c28aaSamw  *   If bits 7 and 6 are both set (11), the following 14 bits are an
124*da6c28aaSamw  *   offset pointer into the full message to the actual label string from
125*da6c28aaSamw  *   another domain name that belongs in this name.  This label pointer
126*da6c28aaSamw  *   allows for a further compression of a domain name in a packet.
127*da6c28aaSamw  *
128*da6c28aaSamw  *   NetBIOS implementations can only use label string pointers in Name
129*da6c28aaSamw  *   Service packets.  They cannot be used in Session or Datagram Service
130*da6c28aaSamw  *   packets.
131*da6c28aaSamw  *
132*da6c28aaSamw  *   The other two possible values for bits 7 and 6 (01 and 10) of a label
133*da6c28aaSamw  *   length field are reserved for future use by RFC 883[2 (page 32)].
134*da6c28aaSamw  *
135*da6c28aaSamw  *   Note that the first octet of a compressed name must contain one of
136*da6c28aaSamw  *   the following bit patterns.  (An "x" indicates a bit whose value may
137*da6c28aaSamw  *   be either 0 or 1.):
138*da6c28aaSamw  *
139*da6c28aaSamw  *           00100000 -  Netbios name, length must be 32 (decimal)
140*da6c28aaSamw  *           11xxxxxx -  Label string pointer
141*da6c28aaSamw  *           10xxxxxx -  Reserved
142*da6c28aaSamw  *           01xxxxxx -  Reserved
143*da6c28aaSamw  */
144*da6c28aaSamw 
145*da6c28aaSamw /*
146*da6c28aaSamw  * netbios_first_level_name_encode
147*da6c28aaSamw  *
148*da6c28aaSamw  * Put test description here.
149*da6c28aaSamw  *
150*da6c28aaSamw  * Inputs:
151*da6c28aaSamw  *	char *	in	-> Name to encode
152*da6c28aaSamw  *	char *	out	-> Buffer to encode into.
153*da6c28aaSamw  *	int	length	-> # of bytes to encode.
154*da6c28aaSamw  *
155*da6c28aaSamw  * Returns:
156*da6c28aaSamw  *	Nothing
157*da6c28aaSamw  */
158*da6c28aaSamw int
159*da6c28aaSamw netbios_first_level_name_encode(unsigned char *name, unsigned char *scope,
160*da6c28aaSamw     unsigned char *out, int max_out)
161*da6c28aaSamw {
162*da6c28aaSamw 	unsigned char	ch, len;
163*da6c28aaSamw 	unsigned char	 *in;
164*da6c28aaSamw 	unsigned char	 *lp;
165*da6c28aaSamw 	unsigned char	 *op = out;
166*da6c28aaSamw 
167*da6c28aaSamw 	if (max_out < 0x21)
168*da6c28aaSamw 		return (-1);
169*da6c28aaSamw 
170*da6c28aaSamw 	in = name;
171*da6c28aaSamw 	*op++ = 0x20;
172*da6c28aaSamw 	for (len = 0; len < NETBIOS_NAME_SZ; len++) {
173*da6c28aaSamw 		ch = *in++;
174*da6c28aaSamw 		*op++ = 'A' + ((ch >> 4) & 0xF);
175*da6c28aaSamw 		*op++ = 'A' + ((ch) & 0xF);
176*da6c28aaSamw 	}
177*da6c28aaSamw 
178*da6c28aaSamw 	max_out -= 0x21;
179*da6c28aaSamw 
180*da6c28aaSamw 	in = scope;
181*da6c28aaSamw 	len = 0;
182*da6c28aaSamw 	lp = op++;
183*da6c28aaSamw 	while (((ch = *in++) != 0) && (max_out-- > 1)) {
184*da6c28aaSamw 		if (ch == 0) {
185*da6c28aaSamw 			if ((*lp = len) != 0)
186*da6c28aaSamw 				*op++ = 0;
187*da6c28aaSamw 			break;
188*da6c28aaSamw 		}
189*da6c28aaSamw 		if (ch == '.') {
190*da6c28aaSamw 			*lp = len;
191*da6c28aaSamw 			lp = op++;
192*da6c28aaSamw 			len = 0;
193*da6c28aaSamw 		} else {
194*da6c28aaSamw 			*op++ = ch;
195*da6c28aaSamw 			len++;
196*da6c28aaSamw 		}
197*da6c28aaSamw 	}
198*da6c28aaSamw 	*lp = len;
199*da6c28aaSamw 	if (len != 0)
200*da6c28aaSamw 		*op = 0;
201*da6c28aaSamw 
202*da6c28aaSamw 	/*LINTED E_PTRDIFF_OVERFLOW*/
203*da6c28aaSamw 	return (op - out);
204*da6c28aaSamw }
205*da6c28aaSamw 
206*da6c28aaSamw /*
207*da6c28aaSamw  * smb_first_level_name_decode
208*da6c28aaSamw  *
209*da6c28aaSamw  * The null terminated string "in" is the name to decode. The output
210*da6c28aaSamw  * is placed in the name_entry structure "name".
211*da6c28aaSamw  *
212*da6c28aaSamw  * The scope field is a series of length designated labels as described
213*da6c28aaSamw  * in the "Domain name representation and compression" section of RFC883.
214*da6c28aaSamw  * The two high order two bits of the length field must be zero, the
215*da6c28aaSamw  * remaining six bits contain the field length. The total length of the
216*da6c28aaSamw  * domain name is restricted to 255 octets but note that the trailing
217*da6c28aaSamw  * root label and its dot are not printed. When converting the labels,
218*da6c28aaSamw  * the length fields are replaced by dots.
219*da6c28aaSamw  *
220*da6c28aaSamw  * Returns the number of bytes scanned or -1 to indicate an error.
221*da6c28aaSamw  */
222*da6c28aaSamw int
223*da6c28aaSamw netbios_first_level_name_decode(char *in, char *name, char *scope)
224*da6c28aaSamw {
225*da6c28aaSamw 	unsigned int	length, bytes;
226*da6c28aaSamw 	char		c1, c2;
227*da6c28aaSamw 	char		*cp;
228*da6c28aaSamw 	char		*out;
229*da6c28aaSamw 
230*da6c28aaSamw 	cp = in;
231*da6c28aaSamw 
232*da6c28aaSamw 	if ((length = *cp++) != 0x20) {
233*da6c28aaSamw 		return (-1);
234*da6c28aaSamw 	}
235*da6c28aaSamw 
236*da6c28aaSamw 	out = name;
237*da6c28aaSamw 	while (length > 0) {
238*da6c28aaSamw 		c1 = *cp++;
239*da6c28aaSamw 		c2 = *cp++;
240*da6c28aaSamw 
241*da6c28aaSamw 		if ('A' <= c1 && c1 <= 'P' && 'A' <= c2 && c2 <= 'P') {
242*da6c28aaSamw 			c1 -= 'A';
243*da6c28aaSamw 			c2 -= 'A';
244*da6c28aaSamw 			*out++ = (c1 << 4) | (c2);
245*da6c28aaSamw 		} else {
246*da6c28aaSamw 			return (-1);		/* conversion error */
247*da6c28aaSamw 		}
248*da6c28aaSamw 		length -= 2;
249*da6c28aaSamw 	}
250*da6c28aaSamw 
251*da6c28aaSamw 	out = scope;
252*da6c28aaSamw 	bytes = 0;
253*da6c28aaSamw 	for (length = *cp++; length != 0; length = *cp++) {
254*da6c28aaSamw 		if ((length & 0xc0) != 0x00) {
255*da6c28aaSamw 			/*
256*da6c28aaSamw 			 * This is a pointer or a reserved field. If it's
257*da6c28aaSamw 			 * a pointer (16-bits) we have to skip the next byte.
258*da6c28aaSamw 			 */
259*da6c28aaSamw 			if ((length & 0xc0) == 0xc0) {
260*da6c28aaSamw 				cp++;
261*da6c28aaSamw 				continue;
262*da6c28aaSamw 			}
263*da6c28aaSamw 		}
264*da6c28aaSamw 
265*da6c28aaSamw 		/*
266*da6c28aaSamw 		 * Replace the length with a '.', except for the first one.
267*da6c28aaSamw 		 */
268*da6c28aaSamw 		if (out != scope) {
269*da6c28aaSamw 			*out++ = '.';
270*da6c28aaSamw 			bytes++;
271*da6c28aaSamw 		}
272*da6c28aaSamw 
273*da6c28aaSamw 		while (length-- > 0) {
274*da6c28aaSamw 			if (bytes++ >= (NETBIOS_DOMAIN_NAME_MAX - 1)) {
275*da6c28aaSamw 				return (-1);
276*da6c28aaSamw 			}
277*da6c28aaSamw 			*out++ = *cp++;
278*da6c28aaSamw 		}
279*da6c28aaSamw 	}
280*da6c28aaSamw 	*out = 0;
281*da6c28aaSamw 
282*da6c28aaSamw 	/*
283*da6c28aaSamw 	 * We are supposed to preserve all 8-bits of the domain name
284*da6c28aaSamw 	 * but due to the single byte representation in the name cache
285*da6c28aaSamw 	 * and UTF-8 encoding everywhere else, we restrict domain names
286*da6c28aaSamw 	 * to Appendix 1 - Domain Name Syntax Specification in RFC883.
287*da6c28aaSamw 	 */
288*da6c28aaSamw 	if (domainname_is_valid(scope))	{
289*da6c28aaSamw 		(void) utf8_strupr(scope);
290*da6c28aaSamw 		/*LINTED E_PTRDIFF_OVERFLOW*/
291*da6c28aaSamw 		return (cp - in);
292*da6c28aaSamw 	}
293*da6c28aaSamw 
294*da6c28aaSamw 	scope[0] = '\0';
295*da6c28aaSamw 	return (-1);
296*da6c28aaSamw }
297*da6c28aaSamw 
298*da6c28aaSamw /*
299*da6c28aaSamw  * smb_netbios_name_isvalid
300*da6c28aaSamw  *
301*da6c28aaSamw  * This function is provided to be used by session service
302*da6c28aaSamw  * which runs in kernel in order to hide name_entry definition.
303*da6c28aaSamw  *
304*da6c28aaSamw  * It returns the decoded name in the provided buffer as 'out'
305*da6c28aaSamw  * if it's not null.
306*da6c28aaSamw  *
307*da6c28aaSamw  * Returns 0 if decode fails, 1 if it succeeds.
308*da6c28aaSamw  */
309*da6c28aaSamw int
310*da6c28aaSamw netbios_name_isvalid(char *in, char *out)
311*da6c28aaSamw {
312*da6c28aaSamw 	char name[NETBIOS_NAME_SZ];
313*da6c28aaSamw 	char scope[NETBIOS_DOMAIN_NAME_MAX];
314*da6c28aaSamw 
315*da6c28aaSamw 	if (netbios_first_level_name_decode(in, name, scope) < 0)
316*da6c28aaSamw 		return (0);
317*da6c28aaSamw 
318*da6c28aaSamw 	if (out)
319*da6c28aaSamw 		(void) strlcpy(out, name, NETBIOS_NAME_SZ);
320*da6c28aaSamw 
321*da6c28aaSamw 	return (1);
322*da6c28aaSamw }
323*da6c28aaSamw 
324*da6c28aaSamw /*
325*da6c28aaSamw  * Characters that we allow in DNS domain names, in addition to
326*da6c28aaSamw  * alphanumeric characters. This is not quite consistent with
327*da6c28aaSamw  * RFC883. This is global so that it can be patched if there is
328*da6c28aaSamw  * a need to change the valid characters in the field.
329*da6c28aaSamw  */
330*da6c28aaSamw unsigned char *dns_allowed = (unsigned char *)"-_";
331*da6c28aaSamw 
332*da6c28aaSamw /*
333*da6c28aaSamw  * dns_is_allowed
334*da6c28aaSamw  *
335*da6c28aaSamw  * Check the dns_allowed characters and return true (1) if the character
336*da6c28aaSamw  * is in the table. Otherwise return false (0).
337*da6c28aaSamw  */
338*da6c28aaSamw static int
339*da6c28aaSamw dns_is_allowed(unsigned char c)
340*da6c28aaSamw {
341*da6c28aaSamw 	unsigned char *p = dns_allowed;
342*da6c28aaSamw 
343*da6c28aaSamw 	while (*p) {
344*da6c28aaSamw 		if (c == *p++)
345*da6c28aaSamw 			return (1);
346*da6c28aaSamw 	}
347*da6c28aaSamw 
348*da6c28aaSamw 	return (0);
349*da6c28aaSamw }
350*da6c28aaSamw 
351*da6c28aaSamw 
352*da6c28aaSamw /*
353*da6c28aaSamw  * domainname_is_valid
354*da6c28aaSamw  *
355*da6c28aaSamw  * Check the specified domain name for mostly compliance with RFC883
356*da6c28aaSamw  * Appendix 1. Names may contain alphanumeric characters, hyphens,
357*da6c28aaSamw  * underscores and dots. The first character after a dot must be an
358*da6c28aaSamw  * alphabetic character. RFC883 doesn't mention underscores but we
359*da6c28aaSamw  * allow it due to common use, and we don't check that labels end
360*da6c28aaSamw  * with an alphanumeric character.
361*da6c28aaSamw  *
362*da6c28aaSamw  * Returns true (1) if the name is valid. Otherwise returns false (0).
363*da6c28aaSamw  */
364*da6c28aaSamw static int
365*da6c28aaSamw domainname_is_valid(char *domain_name)
366*da6c28aaSamw {
367*da6c28aaSamw 	char *name;
368*da6c28aaSamw 	int first_char = 1;
369*da6c28aaSamw 
370*da6c28aaSamw 	if (domain_name == 0)
371*da6c28aaSamw 		return (0);
372*da6c28aaSamw 
373*da6c28aaSamw 	for (name = domain_name; *name != 0; ++name) {
374*da6c28aaSamw 		if (*name == '.') {
375*da6c28aaSamw 			first_char = 1;
376*da6c28aaSamw 			continue;
377*da6c28aaSamw 		}
378*da6c28aaSamw 
379*da6c28aaSamw 		if (first_char)	{
380*da6c28aaSamw 			if (mts_isalpha_ascii(*name) == 0)
381*da6c28aaSamw 				return (0);
382*da6c28aaSamw 
383*da6c28aaSamw 			first_char = 0;
384*da6c28aaSamw 			continue;
385*da6c28aaSamw 		}
386*da6c28aaSamw 
387*da6c28aaSamw 		if (mts_isalnum_ascii(*name) || dns_is_allowed(*name))
388*da6c28aaSamw 			continue;
389*da6c28aaSamw 
390*da6c28aaSamw 		return (0);
391*da6c28aaSamw 	}
392*da6c28aaSamw 
393*da6c28aaSamw 	return (1);
394*da6c28aaSamw }
395