xref: /titanic_44/usr/src/lib/libsmbfs/smb/nb.c (revision 4bff34e37def8a90f9194d81bc345c52ba20086a)
1*4bff34e3Sthurlow /*
2*4bff34e3Sthurlow  * Copyright (c) 2000, 2001 Boris Popov
3*4bff34e3Sthurlow  * All rights reserved.
4*4bff34e3Sthurlow  *
5*4bff34e3Sthurlow  * Redistribution and use in source and binary forms, with or without
6*4bff34e3Sthurlow  * modification, are permitted provided that the following conditions
7*4bff34e3Sthurlow  * are met:
8*4bff34e3Sthurlow  * 1. Redistributions of source code must retain the above copyright
9*4bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer.
10*4bff34e3Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
11*4bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer in the
12*4bff34e3Sthurlow  *    documentation and/or other materials provided with the distribution.
13*4bff34e3Sthurlow  * 3. All advertising materials mentioning features or use of this software
14*4bff34e3Sthurlow  *    must display the following acknowledgement:
15*4bff34e3Sthurlow  *    This product includes software developed by Boris Popov.
16*4bff34e3Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
17*4bff34e3Sthurlow  *    may be used to endorse or promote products derived from this software
18*4bff34e3Sthurlow  *    without specific prior written permission.
19*4bff34e3Sthurlow  *
20*4bff34e3Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21*4bff34e3Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*4bff34e3Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*4bff34e3Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24*4bff34e3Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25*4bff34e3Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26*4bff34e3Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*4bff34e3Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28*4bff34e3Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29*4bff34e3Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30*4bff34e3Sthurlow  * SUCH DAMAGE.
31*4bff34e3Sthurlow  *
32*4bff34e3Sthurlow  * $Id: nb.c,v 1.1.1.2 2001/07/06 22:38:42 conrad Exp $
33*4bff34e3Sthurlow  */
34*4bff34e3Sthurlow 
35*4bff34e3Sthurlow #pragma ident	"%Z%%M%	%I%	%E% SMI"
36*4bff34e3Sthurlow 
37*4bff34e3Sthurlow #include <sys/param.h>
38*4bff34e3Sthurlow #include <sys/socket.h>
39*4bff34e3Sthurlow 
40*4bff34e3Sthurlow #include <ctype.h>
41*4bff34e3Sthurlow #include <netdb.h>
42*4bff34e3Sthurlow #include <errno.h>
43*4bff34e3Sthurlow #include <stdlib.h>
44*4bff34e3Sthurlow #include <string.h>
45*4bff34e3Sthurlow #include <strings.h>
46*4bff34e3Sthurlow #include <stdio.h>
47*4bff34e3Sthurlow #include <unistd.h>
48*4bff34e3Sthurlow #include <libintl.h>
49*4bff34e3Sthurlow 
50*4bff34e3Sthurlow #include <netinet/in.h>
51*4bff34e3Sthurlow #include <arpa/inet.h>
52*4bff34e3Sthurlow 
53*4bff34e3Sthurlow #include <netsmb/netbios.h>
54*4bff34e3Sthurlow #include <netsmb/smb_lib.h>
55*4bff34e3Sthurlow #include <netsmb/nb_lib.h>
56*4bff34e3Sthurlow 
57*4bff34e3Sthurlow #include <cflib.h>
58*4bff34e3Sthurlow 
59*4bff34e3Sthurlow int
60*4bff34e3Sthurlow nb_ctx_create(struct nb_ctx **ctxpp)
61*4bff34e3Sthurlow {
62*4bff34e3Sthurlow 	struct nb_ctx *ctx;
63*4bff34e3Sthurlow 
64*4bff34e3Sthurlow 	ctx = malloc(sizeof (struct nb_ctx));
65*4bff34e3Sthurlow 	if (ctx == NULL)
66*4bff34e3Sthurlow 		return (ENOMEM);
67*4bff34e3Sthurlow 	bzero(ctx, sizeof (struct nb_ctx));
68*4bff34e3Sthurlow 	ctx->nb_flags = NBCF_NS_ENABLE | NBCF_BC_ENABLE;
69*4bff34e3Sthurlow 	*ctxpp = ctx;
70*4bff34e3Sthurlow 	return (0);
71*4bff34e3Sthurlow }
72*4bff34e3Sthurlow 
73*4bff34e3Sthurlow void
74*4bff34e3Sthurlow nb_ctx_done(struct nb_ctx *ctx)
75*4bff34e3Sthurlow {
76*4bff34e3Sthurlow 	if (ctx == NULL)
77*4bff34e3Sthurlow 		return;
78*4bff34e3Sthurlow 	if (ctx->nb_scope)
79*4bff34e3Sthurlow 		free(ctx->nb_scope);
80*4bff34e3Sthurlow 	if (ctx)
81*4bff34e3Sthurlow 		free(ctx);
82*4bff34e3Sthurlow }
83*4bff34e3Sthurlow 
84*4bff34e3Sthurlow static int
85*4bff34e3Sthurlow nb_ctx_setwins(in_addr_t *ina_p, const char *str)
86*4bff34e3Sthurlow {
87*4bff34e3Sthurlow 	struct in_addr ina;
88*4bff34e3Sthurlow 	struct sockaddr *sap;
89*4bff34e3Sthurlow 	int error;
90*4bff34e3Sthurlow 
91*4bff34e3Sthurlow 	if (str == NULL || str[0] == 0)
92*4bff34e3Sthurlow 		return (EINVAL);
93*4bff34e3Sthurlow 
94*4bff34e3Sthurlow 	if (inet_aton(str, &ina)) {
95*4bff34e3Sthurlow 		*ina_p = ina.s_addr;
96*4bff34e3Sthurlow 	} else {
97*4bff34e3Sthurlow 		error = nb_resolvehost_in(str, &sap);
98*4bff34e3Sthurlow 		if (error) {
99*4bff34e3Sthurlow 			smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"),
100*4bff34e3Sthurlow 			    error, str);
101*4bff34e3Sthurlow 			return (error);
102*4bff34e3Sthurlow 		}
103*4bff34e3Sthurlow 		if (sap->sa_family != AF_INET) {
104*4bff34e3Sthurlow 			smb_error(dgettext(TEXT_DOMAIN,
105*4bff34e3Sthurlow 			    "unsupported address family %d"), 0,
106*4bff34e3Sthurlow 			    sap->sa_family);
107*4bff34e3Sthurlow 			return (EINVAL);
108*4bff34e3Sthurlow 		}
109*4bff34e3Sthurlow 		/*LINTED*/
110*4bff34e3Sthurlow 		*ina_p = ((struct sockaddr_in *)sap)->sin_addr.s_addr;
111*4bff34e3Sthurlow 		free(sap);
112*4bff34e3Sthurlow 	}
113*4bff34e3Sthurlow 
114*4bff34e3Sthurlow 	return (0);
115*4bff34e3Sthurlow }
116*4bff34e3Sthurlow 
117*4bff34e3Sthurlow /*
118*4bff34e3Sthurlow  * This is called by "smbutil lookup" to handle the
119*4bff34e3Sthurlow  * "-w wins_server" option.  Let the semantics of
120*4bff34e3Sthurlow  * this option be: Use specified WINS server only.
121*4bff34e3Sthurlow  * If specified server is the broadcast address,
122*4bff34e3Sthurlow  * set broadcast mode (and no WINS servers).
123*4bff34e3Sthurlow  */
124*4bff34e3Sthurlow int
125*4bff34e3Sthurlow nb_ctx_setns(struct nb_ctx *ctx, const char *addr)
126*4bff34e3Sthurlow {
127*4bff34e3Sthurlow 	int error;
128*4bff34e3Sthurlow 
129*4bff34e3Sthurlow 	error = nb_ctx_setwins(&ctx->nb_wins1, addr);
130*4bff34e3Sthurlow 	if (error)
131*4bff34e3Sthurlow 		return (error);
132*4bff34e3Sthurlow 	ctx->nb_wins2 = 0;
133*4bff34e3Sthurlow 
134*4bff34e3Sthurlow 	/* Deal with explicit request for broadcast. */
135*4bff34e3Sthurlow 	if (ctx->nb_wins1 == INADDR_BROADCAST) {
136*4bff34e3Sthurlow 		ctx->nb_wins1 = 0;
137*4bff34e3Sthurlow 		ctx->nb_flags |= NBCF_BC_ENABLE;
138*4bff34e3Sthurlow 	}
139*4bff34e3Sthurlow 	return (0);
140*4bff34e3Sthurlow }
141*4bff34e3Sthurlow 
142*4bff34e3Sthurlow int
143*4bff34e3Sthurlow nb_ctx_setscope(struct nb_ctx *ctx, const char *scope)
144*4bff34e3Sthurlow {
145*4bff34e3Sthurlow 	size_t slen = strlen(scope);
146*4bff34e3Sthurlow 
147*4bff34e3Sthurlow 	if (slen >= 128) {
148*4bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
149*4bff34e3Sthurlow 		    "scope '%s' is too long"), 0, scope);
150*4bff34e3Sthurlow 		return (ENAMETOOLONG);
151*4bff34e3Sthurlow 	}
152*4bff34e3Sthurlow 	if (ctx->nb_scope)
153*4bff34e3Sthurlow 		free(ctx->nb_scope);
154*4bff34e3Sthurlow 	ctx->nb_scope = malloc(slen + 1);
155*4bff34e3Sthurlow 	if (ctx->nb_scope == NULL)
156*4bff34e3Sthurlow 		return (ENOMEM);
157*4bff34e3Sthurlow 	nls_str_upper(ctx->nb_scope, scope);
158*4bff34e3Sthurlow 	return (0);
159*4bff34e3Sthurlow }
160*4bff34e3Sthurlow 
161*4bff34e3Sthurlow /*
162*4bff34e3Sthurlow  * Now get the WINS server IP addresses directly
163*4bff34e3Sthurlow  * when reading the RC files, so no longer need to
164*4bff34e3Sthurlow  * lookup any names here.
165*4bff34e3Sthurlow  */
166*4bff34e3Sthurlow int
167*4bff34e3Sthurlow nb_ctx_resolve(struct nb_ctx *ctx)
168*4bff34e3Sthurlow {
169*4bff34e3Sthurlow 	ctx->nb_flags |= NBCF_RESOLVED;
170*4bff34e3Sthurlow 	return (0);
171*4bff34e3Sthurlow }
172*4bff34e3Sthurlow 
173*4bff34e3Sthurlow /*
174*4bff34e3Sthurlow  * used level values:
175*4bff34e3Sthurlow  * 0 - default
176*4bff34e3Sthurlow  * 1 - server
177*4bff34e3Sthurlow  *
178*4bff34e3Sthurlow  * All of these are normally system-wide settings;
179*4bff34e3Sthurlow  * the checks are in rc_parse() in rcfile.c.
180*4bff34e3Sthurlow  */
181*4bff34e3Sthurlow int
182*4bff34e3Sthurlow nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx,
183*4bff34e3Sthurlow 	const char *sname, int level)
184*4bff34e3Sthurlow {
185*4bff34e3Sthurlow 	char *p;
186*4bff34e3Sthurlow 	int error;
187*4bff34e3Sthurlow 	int nbns_enable;
188*4bff34e3Sthurlow 	int nbns_broadcast;
189*4bff34e3Sthurlow 
190*4bff34e3Sthurlow 	if (level > 1)
191*4bff34e3Sthurlow 		return (EINVAL);
192*4bff34e3Sthurlow #ifdef NOT_DEFINED
193*4bff34e3Sthurlow 	rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo);
194*4bff34e3Sthurlow 	rc_getstringptr(rcfile, sname, "nbscope", &p);
195*4bff34e3Sthurlow 	if (p)
196*4bff34e3Sthurlow 		nb_ctx_setscope(ctx, p);
197*4bff34e3Sthurlow #endif
198*4bff34e3Sthurlow 	/* "nbns" will be "wins1" some day, and we'll have a "wins2" also */
199*4bff34e3Sthurlow 	rc_getstringptr(rcfile, sname, "nbns", &p);
200*4bff34e3Sthurlow 	if (p) {
201*4bff34e3Sthurlow 		error = nb_ctx_setwins(&ctx->nb_wins1, p);
202*4bff34e3Sthurlow 		if (error) {
203*4bff34e3Sthurlow 			smb_error(dgettext(TEXT_DOMAIN,
204*4bff34e3Sthurlow 			    "invalid address specified in the section %s"),
205*4bff34e3Sthurlow 			    0, sname);
206*4bff34e3Sthurlow 			return (error);
207*4bff34e3Sthurlow 		}
208*4bff34e3Sthurlow 	}
209*4bff34e3Sthurlow 	error = rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable);
210*4bff34e3Sthurlow 	if (error == 0 && nbns_enable == 0)
211*4bff34e3Sthurlow 		ctx->nb_flags &= ~NBCF_NS_ENABLE;
212*4bff34e3Sthurlow 	error = rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast);
213*4bff34e3Sthurlow 	if (error == 0 && nbns_broadcast == 0)
214*4bff34e3Sthurlow 		ctx->nb_flags &= ~NBCF_BC_ENABLE;
215*4bff34e3Sthurlow 	return (0);
216*4bff34e3Sthurlow }
217*4bff34e3Sthurlow 
218*4bff34e3Sthurlow #ifdef I18N	/* never defined, permits xgettext(1) to pick out strings */
219*4bff34e3Sthurlow static const char *nb_err_rcode[] = {
220*4bff34e3Sthurlow 	gettext("bad request/response format"),
221*4bff34e3Sthurlow 	gettext("NBNS server failure"),
222*4bff34e3Sthurlow 	gettext("no such name"),
223*4bff34e3Sthurlow 	gettext("unsupported request"),
224*4bff34e3Sthurlow 	gettext("request rejected"),
225*4bff34e3Sthurlow 	gettext("name already registered)"
226*4bff34e3Sthurlow };
227*4bff34e3Sthurlow 
228*4bff34e3Sthurlow static const char *nb_err[] = {
229*4bff34e3Sthurlow 	gettext("host not found"),
230*4bff34e3Sthurlow 	gettext("too many redirects"),
231*4bff34e3Sthurlow 	gettext("invalid response"),
232*4bff34e3Sthurlow 	gettext("NETBIOS name too long"),
233*4bff34e3Sthurlow 	gettext("no interface to broadcast on and no NBNS server specified")
234*4bff34e3Sthurlow };
235*4bff34e3Sthurlow #else
236*4bff34e3Sthurlow static const char *nb_err_rcode[] = {
237*4bff34e3Sthurlow 	"bad request/response format",
238*4bff34e3Sthurlow 	"NBNS server failure",
239*4bff34e3Sthurlow 	"no such name",
240*4bff34e3Sthurlow 	"unsupported request",
241*4bff34e3Sthurlow 	"request rejected",
242*4bff34e3Sthurlow 	"name already registered"
243*4bff34e3Sthurlow };
244*4bff34e3Sthurlow 
245*4bff34e3Sthurlow static const char *nb_err[] = {
246*4bff34e3Sthurlow 	"host not found",
247*4bff34e3Sthurlow 	"too many redirects",
248*4bff34e3Sthurlow 	"invalid response",
249*4bff34e3Sthurlow 	"NETBIOS name too long",
250*4bff34e3Sthurlow 	"no interface to broadcast on and no NBNS server specified"
251*4bff34e3Sthurlow };
252*4bff34e3Sthurlow #endif
253*4bff34e3Sthurlow 
254*4bff34e3Sthurlow const char *
255*4bff34e3Sthurlow nb_strerror(int error)
256*4bff34e3Sthurlow {
257*4bff34e3Sthurlow 	if (error == 0)
258*4bff34e3Sthurlow 		return (NULL);
259*4bff34e3Sthurlow 	if (error <= NBERR_ACTIVE)
260*4bff34e3Sthurlow 		return (nb_err_rcode[error - 1]);
261*4bff34e3Sthurlow 	else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX)
262*4bff34e3Sthurlow 		return (nb_err[error - NBERR_HOSTNOTFOUND]);
263*4bff34e3Sthurlow 	else
264*4bff34e3Sthurlow 		return (NULL);
265*4bff34e3Sthurlow }
266