xref: /onnv-gate/usr/src/lib/libsmbfs/smb/nb.c (revision 10023:71bf38dba3d6)
16007Sthurlow /*
26007Sthurlow  * Copyright (c) 2000, 2001 Boris Popov
36007Sthurlow  * All rights reserved.
46007Sthurlow  *
56007Sthurlow  * Redistribution and use in source and binary forms, with or without
66007Sthurlow  * modification, are permitted provided that the following conditions
76007Sthurlow  * are met:
86007Sthurlow  * 1. Redistributions of source code must retain the above copyright
96007Sthurlow  *    notice, this list of conditions and the following disclaimer.
106007Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
116007Sthurlow  *    notice, this list of conditions and the following disclaimer in the
126007Sthurlow  *    documentation and/or other materials provided with the distribution.
136007Sthurlow  * 3. All advertising materials mentioning features or use of this software
146007Sthurlow  *    must display the following acknowledgement:
156007Sthurlow  *    This product includes software developed by Boris Popov.
166007Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
176007Sthurlow  *    may be used to endorse or promote products derived from this software
186007Sthurlow  *    without specific prior written permission.
196007Sthurlow  *
206007Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216007Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226007Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236007Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246007Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256007Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266007Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276007Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286007Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296007Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306007Sthurlow  * SUCH DAMAGE.
316007Sthurlow  *
326007Sthurlow  * $Id: nb.c,v 1.1.1.2 2001/07/06 22:38:42 conrad Exp $
336007Sthurlow  */
346007Sthurlow 
35*10023SGordon.Ross@Sun.COM /*
36*10023SGordon.Ross@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
37*10023SGordon.Ross@Sun.COM  * Use is subject to license terms.
38*10023SGordon.Ross@Sun.COM  */
396007Sthurlow 
406007Sthurlow #include <sys/param.h>
416007Sthurlow #include <sys/socket.h>
426007Sthurlow 
436007Sthurlow #include <errno.h>
44*10023SGordon.Ross@Sun.COM #include <stdio.h>
456007Sthurlow #include <stdlib.h>
466007Sthurlow #include <string.h>
476007Sthurlow #include <strings.h>
486007Sthurlow #include <unistd.h>
496007Sthurlow #include <libintl.h>
50*10023SGordon.Ross@Sun.COM #include <netdb.h>
516007Sthurlow 
526007Sthurlow #include <netinet/in.h>
536007Sthurlow #include <arpa/inet.h>
546007Sthurlow 
55*10023SGordon.Ross@Sun.COM #include <cflib.h>
566007Sthurlow #include <netsmb/netbios.h>
576007Sthurlow #include <netsmb/smb_lib.h>
586007Sthurlow #include <netsmb/nb_lib.h>
596007Sthurlow 
60*10023SGordon.Ross@Sun.COM int nb_ctx_setwins(struct nb_ctx *, const char *, const char *);
61*10023SGordon.Ross@Sun.COM 
62*10023SGordon.Ross@Sun.COM 
63*10023SGordon.Ross@Sun.COM /*
64*10023SGordon.Ross@Sun.COM  * API for library consumer to set wins1, wins2
65*10023SGordon.Ross@Sun.COM  */
66*10023SGordon.Ross@Sun.COM int
67*10023SGordon.Ross@Sun.COM smb_ctx_setwins(struct smb_ctx *ctx, const char *wins1, const char *wins2)
68*10023SGordon.Ross@Sun.COM {
69*10023SGordon.Ross@Sun.COM 	struct nb_ctx *nb = ctx->ct_nb;
70*10023SGordon.Ross@Sun.COM 
71*10023SGordon.Ross@Sun.COM 	if (nb == NULL)
72*10023SGordon.Ross@Sun.COM 		return (EINVAL);
73*10023SGordon.Ross@Sun.COM 
74*10023SGordon.Ross@Sun.COM 	return (nb_ctx_setwins(nb, wins1, wins2));
75*10023SGordon.Ross@Sun.COM }
76*10023SGordon.Ross@Sun.COM 
77*10023SGordon.Ross@Sun.COM /*
78*10023SGordon.Ross@Sun.COM  * API for library consumer to set NB scope.
79*10023SGordon.Ross@Sun.COM  */
80*10023SGordon.Ross@Sun.COM int
81*10023SGordon.Ross@Sun.COM smb_ctx_setscope(struct smb_ctx *ctx, const char *scope)
82*10023SGordon.Ross@Sun.COM {
83*10023SGordon.Ross@Sun.COM 	struct nb_ctx *nb = ctx->ct_nb;
84*10023SGordon.Ross@Sun.COM 
85*10023SGordon.Ross@Sun.COM 	if (nb == NULL)
86*10023SGordon.Ross@Sun.COM 		return (EINVAL);
87*10023SGordon.Ross@Sun.COM 
88*10023SGordon.Ross@Sun.COM 	return (nb_ctx_setscope(nb, scope));
89*10023SGordon.Ross@Sun.COM }
906007Sthurlow 
916007Sthurlow int
926007Sthurlow nb_ctx_create(struct nb_ctx **ctxpp)
936007Sthurlow {
946007Sthurlow 	struct nb_ctx *ctx;
956007Sthurlow 
966007Sthurlow 	ctx = malloc(sizeof (struct nb_ctx));
976007Sthurlow 	if (ctx == NULL)
986007Sthurlow 		return (ENOMEM);
996007Sthurlow 	bzero(ctx, sizeof (struct nb_ctx));
1006007Sthurlow 	ctx->nb_flags = NBCF_NS_ENABLE | NBCF_BC_ENABLE;
1016007Sthurlow 	*ctxpp = ctx;
1026007Sthurlow 	return (0);
1036007Sthurlow }
1046007Sthurlow 
1056007Sthurlow void
1066007Sthurlow nb_ctx_done(struct nb_ctx *ctx)
1076007Sthurlow {
1086007Sthurlow 	if (ctx == NULL)
1096007Sthurlow 		return;
1106007Sthurlow 	if (ctx->nb_scope)
1116007Sthurlow 		free(ctx->nb_scope);
1126007Sthurlow 	if (ctx)
1136007Sthurlow 		free(ctx);
1146007Sthurlow }
1156007Sthurlow 
116*10023SGordon.Ross@Sun.COM int
117*10023SGordon.Ross@Sun.COM nb_ctx_setwins(struct nb_ctx *ctx, const char *wins1, const char *wins2)
1186007Sthurlow {
1196007Sthurlow 	struct in_addr ina;
1206007Sthurlow 	int error;
1216007Sthurlow 
122*10023SGordon.Ross@Sun.COM 	if (wins1 == NULL) {
123*10023SGordon.Ross@Sun.COM 		ctx->nb_wins1 = 0;
124*10023SGordon.Ross@Sun.COM 		ctx->nb_wins2 = 0;
125*10023SGordon.Ross@Sun.COM 		return (0);
126*10023SGordon.Ross@Sun.COM 	}
1276007Sthurlow 
128*10023SGordon.Ross@Sun.COM 	error = nb_resolvehost_in(wins1, &ina);
129*10023SGordon.Ross@Sun.COM 	if (error) {
130*10023SGordon.Ross@Sun.COM 		smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"),
131*10023SGordon.Ross@Sun.COM 		    error, wins1);
132*10023SGordon.Ross@Sun.COM 		return (error);
133*10023SGordon.Ross@Sun.COM 	}
134*10023SGordon.Ross@Sun.COM 	ctx->nb_wins1 = ina.s_addr;
135*10023SGordon.Ross@Sun.COM 
136*10023SGordon.Ross@Sun.COM 	if (wins2 == NULL)
137*10023SGordon.Ross@Sun.COM 		ctx->nb_wins2 = 0;
138*10023SGordon.Ross@Sun.COM 	else {
139*10023SGordon.Ross@Sun.COM 		error = nb_resolvehost_in(wins2, &ina);
1406007Sthurlow 		if (error) {
1416007Sthurlow 			smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"),
142*10023SGordon.Ross@Sun.COM 			    error, wins2);
1436007Sthurlow 			return (error);
1446007Sthurlow 		}
145*10023SGordon.Ross@Sun.COM 		ctx->nb_wins2 = ina.s_addr;
1466007Sthurlow 	}
1476007Sthurlow 	return (0);
1486007Sthurlow }
1496007Sthurlow 
1506007Sthurlow /*
1516007Sthurlow  * This is called by "smbutil lookup" to handle the
1526007Sthurlow  * "-w wins_server" option.  Let the semantics of
1536007Sthurlow  * this option be: Use specified WINS server only.
1546007Sthurlow  * If specified server is the broadcast address,
1556007Sthurlow  * set broadcast mode (and no WINS servers).
1566007Sthurlow  */
1576007Sthurlow int
1586007Sthurlow nb_ctx_setns(struct nb_ctx *ctx, const char *addr)
1596007Sthurlow {
1606007Sthurlow 	int error;
1616007Sthurlow 
162*10023SGordon.Ross@Sun.COM 	error = nb_ctx_setwins(ctx, addr, NULL);
1636007Sthurlow 	if (error)
1646007Sthurlow 		return (error);
1656007Sthurlow 
1666007Sthurlow 	/* Deal with explicit request for broadcast. */
1676007Sthurlow 	if (ctx->nb_wins1 == INADDR_BROADCAST) {
1686007Sthurlow 		ctx->nb_wins1 = 0;
1696007Sthurlow 		ctx->nb_flags |= NBCF_BC_ENABLE;
1706007Sthurlow 	}
1716007Sthurlow 	return (0);
1726007Sthurlow }
1736007Sthurlow 
1746007Sthurlow int
1756007Sthurlow nb_ctx_setscope(struct nb_ctx *ctx, const char *scope)
1766007Sthurlow {
1776007Sthurlow 	size_t slen = strlen(scope);
1786007Sthurlow 
1796007Sthurlow 	if (slen >= 128) {
1806007Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1816007Sthurlow 		    "scope '%s' is too long"), 0, scope);
1826007Sthurlow 		return (ENAMETOOLONG);
1836007Sthurlow 	}
1846007Sthurlow 	if (ctx->nb_scope)
1856007Sthurlow 		free(ctx->nb_scope);
1866007Sthurlow 	ctx->nb_scope = malloc(slen + 1);
1876007Sthurlow 	if (ctx->nb_scope == NULL)
1886007Sthurlow 		return (ENOMEM);
1896007Sthurlow 	nls_str_upper(ctx->nb_scope, scope);
1906007Sthurlow 	return (0);
1916007Sthurlow }
1926007Sthurlow 
1936007Sthurlow /*
1946007Sthurlow  * Now get the WINS server IP addresses directly
1956007Sthurlow  * when reading the RC files, so no longer need to
1966007Sthurlow  * lookup any names here.
1976007Sthurlow  */
1986007Sthurlow int
1996007Sthurlow nb_ctx_resolve(struct nb_ctx *ctx)
2006007Sthurlow {
2016007Sthurlow 	ctx->nb_flags |= NBCF_RESOLVED;
2026007Sthurlow 	return (0);
2036007Sthurlow }
2046007Sthurlow 
2056007Sthurlow /*
2066007Sthurlow  * used level values:
2076007Sthurlow  * 0 - default
2086007Sthurlow  * 1 - server
2096007Sthurlow  *
2106007Sthurlow  * All of these are normally system-wide settings;
2116007Sthurlow  * the checks are in rc_parse() in rcfile.c.
2126007Sthurlow  */
2136007Sthurlow int
2146007Sthurlow nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx,
2156007Sthurlow 	const char *sname, int level)
2166007Sthurlow {
217*10023SGordon.Ross@Sun.COM 	char *wins1, *wins2;
2186007Sthurlow 	int error;
2196007Sthurlow 	int nbns_enable;
2206007Sthurlow 	int nbns_broadcast;
2216007Sthurlow 
2226007Sthurlow 	if (level > 1)
2236007Sthurlow 		return (EINVAL);
224*10023SGordon.Ross@Sun.COM 
225*10023SGordon.Ross@Sun.COM 	/* External callers pass NULL to get the default. */
226*10023SGordon.Ross@Sun.COM 	if (rcfile == NULL)
227*10023SGordon.Ross@Sun.COM 		rcfile = smb_rc;
228*10023SGordon.Ross@Sun.COM 
2296007Sthurlow #ifdef NOT_DEFINED
2306007Sthurlow 	rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo);
2316007Sthurlow 	rc_getstringptr(rcfile, sname, "nbscope", &p);
2326007Sthurlow 	if (p)
2336007Sthurlow 		nb_ctx_setscope(ctx, p);
2346007Sthurlow #endif
235*10023SGordon.Ross@Sun.COM 	/*
236*10023SGordon.Ross@Sun.COM 	 * Get "wins1", "wins2" config strings.
237*10023SGordon.Ross@Sun.COM 	 * Also support legacy "nbns".
238*10023SGordon.Ross@Sun.COM 	 */
239*10023SGordon.Ross@Sun.COM 	rc_getstringptr(rcfile, sname, "wins1", &wins1);
240*10023SGordon.Ross@Sun.COM 	if (wins1 == NULL)
241*10023SGordon.Ross@Sun.COM 		rc_getstringptr(rcfile, sname, "nbns", &wins1);
242*10023SGordon.Ross@Sun.COM 	rc_getstringptr(rcfile, sname, "wins2", &wins2);
243*10023SGordon.Ross@Sun.COM 
244*10023SGordon.Ross@Sun.COM 	if (wins1 != NULL) {
245*10023SGordon.Ross@Sun.COM 		error = nb_ctx_setwins(ctx, wins1, wins2);
2466007Sthurlow 		if (error) {
2476007Sthurlow 			smb_error(dgettext(TEXT_DOMAIN,
2486007Sthurlow 			    "invalid address specified in the section %s"),
2496007Sthurlow 			    0, sname);
2506007Sthurlow 			return (error);
2516007Sthurlow 		}
2526007Sthurlow 	}
2536007Sthurlow 	error = rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable);
2546007Sthurlow 	if (error == 0 && nbns_enable == 0)
2556007Sthurlow 		ctx->nb_flags &= ~NBCF_NS_ENABLE;
2566007Sthurlow 	error = rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast);
2576007Sthurlow 	if (error == 0 && nbns_broadcast == 0)
2586007Sthurlow 		ctx->nb_flags &= ~NBCF_BC_ENABLE;
2596007Sthurlow 	return (0);
2606007Sthurlow }
2616007Sthurlow 
2626007Sthurlow #ifdef I18N	/* never defined, permits xgettext(1) to pick out strings */
2636007Sthurlow static const char *nb_err_rcode[] = {
2646007Sthurlow 	gettext("bad request/response format"),
2656007Sthurlow 	gettext("NBNS server failure"),
2666007Sthurlow 	gettext("no such name"),
2676007Sthurlow 	gettext("unsupported request"),
2686007Sthurlow 	gettext("request rejected"),
2696007Sthurlow 	gettext("name already registered)"
2706007Sthurlow };
2716007Sthurlow 
2726007Sthurlow static const char *nb_err[] = {
2736007Sthurlow 	gettext("host not found"),
2746007Sthurlow 	gettext("too many redirects"),
2756007Sthurlow 	gettext("invalid response"),
2766007Sthurlow 	gettext("NETBIOS name too long"),
2776007Sthurlow 	gettext("no interface to broadcast on and no NBNS server specified")
2786007Sthurlow };
2796007Sthurlow #else
2806007Sthurlow static const char *nb_err_rcode[] = {
2816007Sthurlow 	"bad request/response format",
2826007Sthurlow 	"NBNS server failure",
2836007Sthurlow 	"no such name",
2846007Sthurlow 	"unsupported request",
2856007Sthurlow 	"request rejected",
2866007Sthurlow 	"name already registered"
2876007Sthurlow };
2886007Sthurlow 
2896007Sthurlow static const char *nb_err[] = {
2906007Sthurlow 	"host not found",
2916007Sthurlow 	"too many redirects",
2926007Sthurlow 	"invalid response",
2936007Sthurlow 	"NETBIOS name too long",
2946007Sthurlow 	"no interface to broadcast on and no NBNS server specified"
2956007Sthurlow };
2966007Sthurlow #endif
2976007Sthurlow 
2986007Sthurlow const char *
2996007Sthurlow nb_strerror(int error)
3006007Sthurlow {
3016007Sthurlow 	if (error == 0)
3026007Sthurlow 		return (NULL);
3036007Sthurlow 	if (error <= NBERR_ACTIVE)
3046007Sthurlow 		return (nb_err_rcode[error - 1]);
3056007Sthurlow 	else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX)
3066007Sthurlow 		return (nb_err[error - NBERR_HOSTNOTFOUND]);
3076007Sthurlow 	else
3086007Sthurlow 		return (NULL);
3096007Sthurlow }
310