xref: /titanic_50/usr/src/lib/libsmbfs/smb/nb.c (revision 613a2f6ba31e891e3d947a356daf5e563d43c1ce)
14bff34e3Sthurlow /*
24bff34e3Sthurlow  * Copyright (c) 2000, 2001 Boris Popov
34bff34e3Sthurlow  * All rights reserved.
44bff34e3Sthurlow  *
54bff34e3Sthurlow  * Redistribution and use in source and binary forms, with or without
64bff34e3Sthurlow  * modification, are permitted provided that the following conditions
74bff34e3Sthurlow  * are met:
84bff34e3Sthurlow  * 1. Redistributions of source code must retain the above copyright
94bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer.
104bff34e3Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
114bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer in the
124bff34e3Sthurlow  *    documentation and/or other materials provided with the distribution.
134bff34e3Sthurlow  * 3. All advertising materials mentioning features or use of this software
144bff34e3Sthurlow  *    must display the following acknowledgement:
154bff34e3Sthurlow  *    This product includes software developed by Boris Popov.
164bff34e3Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
174bff34e3Sthurlow  *    may be used to endorse or promote products derived from this software
184bff34e3Sthurlow  *    without specific prior written permission.
194bff34e3Sthurlow  *
204bff34e3Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
214bff34e3Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
224bff34e3Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
234bff34e3Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
244bff34e3Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
254bff34e3Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
264bff34e3Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
274bff34e3Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
284bff34e3Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
294bff34e3Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
304bff34e3Sthurlow  * SUCH DAMAGE.
314bff34e3Sthurlow  *
324bff34e3Sthurlow  * $Id: nb.c,v 1.1.1.2 2001/07/06 22:38:42 conrad Exp $
334bff34e3Sthurlow  */
344bff34e3Sthurlow 
35*613a2f6bSGordon Ross /*
36*613a2f6bSGordon Ross  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
37*613a2f6bSGordon Ross  * Use is subject to license terms.
38*613a2f6bSGordon Ross  */
394bff34e3Sthurlow 
404bff34e3Sthurlow #include <sys/param.h>
414bff34e3Sthurlow #include <sys/socket.h>
424bff34e3Sthurlow 
434bff34e3Sthurlow #include <errno.h>
44*613a2f6bSGordon Ross #include <stdio.h>
454bff34e3Sthurlow #include <stdlib.h>
464bff34e3Sthurlow #include <string.h>
474bff34e3Sthurlow #include <strings.h>
484bff34e3Sthurlow #include <unistd.h>
494bff34e3Sthurlow #include <libintl.h>
50*613a2f6bSGordon Ross #include <netdb.h>
514bff34e3Sthurlow 
524bff34e3Sthurlow #include <netinet/in.h>
534bff34e3Sthurlow #include <arpa/inet.h>
544bff34e3Sthurlow 
55*613a2f6bSGordon Ross #include <cflib.h>
564bff34e3Sthurlow #include <netsmb/netbios.h>
574bff34e3Sthurlow #include <netsmb/smb_lib.h>
584bff34e3Sthurlow #include <netsmb/nb_lib.h>
594bff34e3Sthurlow 
60*613a2f6bSGordon Ross int nb_ctx_setwins(struct nb_ctx *, const char *, const char *);
61*613a2f6bSGordon Ross 
62*613a2f6bSGordon Ross 
63*613a2f6bSGordon Ross /*
64*613a2f6bSGordon Ross  * API for library consumer to set wins1, wins2
65*613a2f6bSGordon Ross  */
66*613a2f6bSGordon Ross int
67*613a2f6bSGordon Ross smb_ctx_setwins(struct smb_ctx *ctx, const char *wins1, const char *wins2)
68*613a2f6bSGordon Ross {
69*613a2f6bSGordon Ross 	struct nb_ctx *nb = ctx->ct_nb;
70*613a2f6bSGordon Ross 
71*613a2f6bSGordon Ross 	if (nb == NULL)
72*613a2f6bSGordon Ross 		return (EINVAL);
73*613a2f6bSGordon Ross 
74*613a2f6bSGordon Ross 	return (nb_ctx_setwins(nb, wins1, wins2));
75*613a2f6bSGordon Ross }
76*613a2f6bSGordon Ross 
77*613a2f6bSGordon Ross /*
78*613a2f6bSGordon Ross  * API for library consumer to set NB scope.
79*613a2f6bSGordon Ross  */
80*613a2f6bSGordon Ross int
81*613a2f6bSGordon Ross smb_ctx_setscope(struct smb_ctx *ctx, const char *scope)
82*613a2f6bSGordon Ross {
83*613a2f6bSGordon Ross 	struct nb_ctx *nb = ctx->ct_nb;
84*613a2f6bSGordon Ross 
85*613a2f6bSGordon Ross 	if (nb == NULL)
86*613a2f6bSGordon Ross 		return (EINVAL);
87*613a2f6bSGordon Ross 
88*613a2f6bSGordon Ross 	return (nb_ctx_setscope(nb, scope));
89*613a2f6bSGordon Ross }
904bff34e3Sthurlow 
914bff34e3Sthurlow int
924bff34e3Sthurlow nb_ctx_create(struct nb_ctx **ctxpp)
934bff34e3Sthurlow {
944bff34e3Sthurlow 	struct nb_ctx *ctx;
954bff34e3Sthurlow 
964bff34e3Sthurlow 	ctx = malloc(sizeof (struct nb_ctx));
974bff34e3Sthurlow 	if (ctx == NULL)
984bff34e3Sthurlow 		return (ENOMEM);
994bff34e3Sthurlow 	bzero(ctx, sizeof (struct nb_ctx));
1004bff34e3Sthurlow 	ctx->nb_flags = NBCF_NS_ENABLE | NBCF_BC_ENABLE;
1014bff34e3Sthurlow 	*ctxpp = ctx;
1024bff34e3Sthurlow 	return (0);
1034bff34e3Sthurlow }
1044bff34e3Sthurlow 
1054bff34e3Sthurlow void
1064bff34e3Sthurlow nb_ctx_done(struct nb_ctx *ctx)
1074bff34e3Sthurlow {
1084bff34e3Sthurlow 	if (ctx == NULL)
1094bff34e3Sthurlow 		return;
1104bff34e3Sthurlow 	if (ctx->nb_scope)
1114bff34e3Sthurlow 		free(ctx->nb_scope);
1124bff34e3Sthurlow 	if (ctx)
1134bff34e3Sthurlow 		free(ctx);
1144bff34e3Sthurlow }
1154bff34e3Sthurlow 
116*613a2f6bSGordon Ross int
117*613a2f6bSGordon Ross nb_ctx_setwins(struct nb_ctx *ctx, const char *wins1, const char *wins2)
1184bff34e3Sthurlow {
1194bff34e3Sthurlow 	struct in_addr ina;
1204bff34e3Sthurlow 	int error;
1214bff34e3Sthurlow 
122*613a2f6bSGordon Ross 	if (wins1 == NULL) {
123*613a2f6bSGordon Ross 		ctx->nb_wins1 = 0;
124*613a2f6bSGordon Ross 		ctx->nb_wins2 = 0;
125*613a2f6bSGordon Ross 		return (0);
126*613a2f6bSGordon Ross 	}
1274bff34e3Sthurlow 
128*613a2f6bSGordon Ross 	error = nb_resolvehost_in(wins1, &ina);
1294bff34e3Sthurlow 	if (error) {
1304bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"),
131*613a2f6bSGordon Ross 		    error, wins1);
1324bff34e3Sthurlow 		return (error);
1334bff34e3Sthurlow 	}
134*613a2f6bSGordon Ross 	ctx->nb_wins1 = ina.s_addr;
1354bff34e3Sthurlow 
136*613a2f6bSGordon Ross 	if (wins2 == NULL)
137*613a2f6bSGordon Ross 		ctx->nb_wins2 = 0;
138*613a2f6bSGordon Ross 	else {
139*613a2f6bSGordon Ross 		error = nb_resolvehost_in(wins2, &ina);
140*613a2f6bSGordon Ross 		if (error) {
141*613a2f6bSGordon Ross 			smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"),
142*613a2f6bSGordon Ross 			    error, wins2);
143*613a2f6bSGordon Ross 			return (error);
144*613a2f6bSGordon Ross 		}
145*613a2f6bSGordon Ross 		ctx->nb_wins2 = ina.s_addr;
146*613a2f6bSGordon Ross 	}
1474bff34e3Sthurlow 	return (0);
1484bff34e3Sthurlow }
1494bff34e3Sthurlow 
1504bff34e3Sthurlow /*
1514bff34e3Sthurlow  * This is called by "smbutil lookup" to handle the
1524bff34e3Sthurlow  * "-w wins_server" option.  Let the semantics of
1534bff34e3Sthurlow  * this option be: Use specified WINS server only.
1544bff34e3Sthurlow  * If specified server is the broadcast address,
1554bff34e3Sthurlow  * set broadcast mode (and no WINS servers).
1564bff34e3Sthurlow  */
1574bff34e3Sthurlow int
1584bff34e3Sthurlow nb_ctx_setns(struct nb_ctx *ctx, const char *addr)
1594bff34e3Sthurlow {
1604bff34e3Sthurlow 	int error;
1614bff34e3Sthurlow 
162*613a2f6bSGordon Ross 	error = nb_ctx_setwins(ctx, addr, NULL);
1634bff34e3Sthurlow 	if (error)
1644bff34e3Sthurlow 		return (error);
1654bff34e3Sthurlow 
1664bff34e3Sthurlow 	/* Deal with explicit request for broadcast. */
1674bff34e3Sthurlow 	if (ctx->nb_wins1 == INADDR_BROADCAST) {
1684bff34e3Sthurlow 		ctx->nb_wins1 = 0;
1694bff34e3Sthurlow 		ctx->nb_flags |= NBCF_BC_ENABLE;
1704bff34e3Sthurlow 	}
1714bff34e3Sthurlow 	return (0);
1724bff34e3Sthurlow }
1734bff34e3Sthurlow 
1744bff34e3Sthurlow int
1754bff34e3Sthurlow nb_ctx_setscope(struct nb_ctx *ctx, const char *scope)
1764bff34e3Sthurlow {
1774bff34e3Sthurlow 	size_t slen = strlen(scope);
1784bff34e3Sthurlow 
1794bff34e3Sthurlow 	if (slen >= 128) {
1804bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1814bff34e3Sthurlow 		    "scope '%s' is too long"), 0, scope);
1824bff34e3Sthurlow 		return (ENAMETOOLONG);
1834bff34e3Sthurlow 	}
1844bff34e3Sthurlow 	if (ctx->nb_scope)
1854bff34e3Sthurlow 		free(ctx->nb_scope);
1864bff34e3Sthurlow 	ctx->nb_scope = malloc(slen + 1);
1874bff34e3Sthurlow 	if (ctx->nb_scope == NULL)
1884bff34e3Sthurlow 		return (ENOMEM);
1894bff34e3Sthurlow 	nls_str_upper(ctx->nb_scope, scope);
1904bff34e3Sthurlow 	return (0);
1914bff34e3Sthurlow }
1924bff34e3Sthurlow 
1934bff34e3Sthurlow /*
1944bff34e3Sthurlow  * Now get the WINS server IP addresses directly
1954bff34e3Sthurlow  * when reading the RC files, so no longer need to
1964bff34e3Sthurlow  * lookup any names here.
1974bff34e3Sthurlow  */
1984bff34e3Sthurlow int
1994bff34e3Sthurlow nb_ctx_resolve(struct nb_ctx *ctx)
2004bff34e3Sthurlow {
2014bff34e3Sthurlow 	ctx->nb_flags |= NBCF_RESOLVED;
2024bff34e3Sthurlow 	return (0);
2034bff34e3Sthurlow }
2044bff34e3Sthurlow 
2054bff34e3Sthurlow /*
2064bff34e3Sthurlow  * used level values:
2074bff34e3Sthurlow  * 0 - default
2084bff34e3Sthurlow  * 1 - server
2094bff34e3Sthurlow  *
2104bff34e3Sthurlow  * All of these are normally system-wide settings;
2114bff34e3Sthurlow  * the checks are in rc_parse() in rcfile.c.
2124bff34e3Sthurlow  */
2134bff34e3Sthurlow int
2144bff34e3Sthurlow nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx,
2154bff34e3Sthurlow 	const char *sname, int level)
2164bff34e3Sthurlow {
217*613a2f6bSGordon Ross 	char *wins1, *wins2;
2184bff34e3Sthurlow 	int error;
2194bff34e3Sthurlow 	int nbns_enable;
2204bff34e3Sthurlow 	int nbns_broadcast;
2214bff34e3Sthurlow 
2224bff34e3Sthurlow 	if (level > 1)
2234bff34e3Sthurlow 		return (EINVAL);
224*613a2f6bSGordon Ross 
225*613a2f6bSGordon Ross 	/* External callers pass NULL to get the default. */
226*613a2f6bSGordon Ross 	if (rcfile == NULL)
227*613a2f6bSGordon Ross 		rcfile = smb_rc;
228*613a2f6bSGordon Ross 
2294bff34e3Sthurlow #ifdef NOT_DEFINED
2304bff34e3Sthurlow 	rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo);
2314bff34e3Sthurlow 	rc_getstringptr(rcfile, sname, "nbscope", &p);
2324bff34e3Sthurlow 	if (p)
2334bff34e3Sthurlow 		nb_ctx_setscope(ctx, p);
2344bff34e3Sthurlow #endif
235*613a2f6bSGordon Ross 	/*
236*613a2f6bSGordon Ross 	 * Get "wins1", "wins2" config strings.
237*613a2f6bSGordon Ross 	 * Also support legacy "nbns".
238*613a2f6bSGordon Ross 	 */
239*613a2f6bSGordon Ross 	rc_getstringptr(rcfile, sname, "wins1", &wins1);
240*613a2f6bSGordon Ross 	if (wins1 == NULL)
241*613a2f6bSGordon Ross 		rc_getstringptr(rcfile, sname, "nbns", &wins1);
242*613a2f6bSGordon Ross 	rc_getstringptr(rcfile, sname, "wins2", &wins2);
243*613a2f6bSGordon Ross 
244*613a2f6bSGordon Ross 	if (wins1 != NULL) {
245*613a2f6bSGordon Ross 		error = nb_ctx_setwins(ctx, wins1, wins2);
2464bff34e3Sthurlow 		if (error) {
2474bff34e3Sthurlow 			smb_error(dgettext(TEXT_DOMAIN,
2484bff34e3Sthurlow 			    "invalid address specified in the section %s"),
2494bff34e3Sthurlow 			    0, sname);
2504bff34e3Sthurlow 			return (error);
2514bff34e3Sthurlow 		}
2524bff34e3Sthurlow 	}
2534bff34e3Sthurlow 	error = rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable);
2544bff34e3Sthurlow 	if (error == 0 && nbns_enable == 0)
2554bff34e3Sthurlow 		ctx->nb_flags &= ~NBCF_NS_ENABLE;
2564bff34e3Sthurlow 	error = rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast);
2574bff34e3Sthurlow 	if (error == 0 && nbns_broadcast == 0)
2584bff34e3Sthurlow 		ctx->nb_flags &= ~NBCF_BC_ENABLE;
2594bff34e3Sthurlow 	return (0);
2604bff34e3Sthurlow }
2614bff34e3Sthurlow 
2624bff34e3Sthurlow #ifdef I18N	/* never defined, permits xgettext(1) to pick out strings */
2634bff34e3Sthurlow static const char *nb_err_rcode[] = {
2644bff34e3Sthurlow 	gettext("bad request/response format"),
2654bff34e3Sthurlow 	gettext("NBNS server failure"),
2664bff34e3Sthurlow 	gettext("no such name"),
2674bff34e3Sthurlow 	gettext("unsupported request"),
2684bff34e3Sthurlow 	gettext("request rejected"),
2694bff34e3Sthurlow 	gettext("name already registered)"
2704bff34e3Sthurlow };
2714bff34e3Sthurlow 
2724bff34e3Sthurlow static const char *nb_err[] = {
2734bff34e3Sthurlow 	gettext("host not found"),
2744bff34e3Sthurlow 	gettext("too many redirects"),
2754bff34e3Sthurlow 	gettext("invalid response"),
2764bff34e3Sthurlow 	gettext("NETBIOS name too long"),
2774bff34e3Sthurlow 	gettext("no interface to broadcast on and no NBNS server specified")
2784bff34e3Sthurlow };
2794bff34e3Sthurlow #else
2804bff34e3Sthurlow static const char *nb_err_rcode[] = {
2814bff34e3Sthurlow 	"bad request/response format",
2824bff34e3Sthurlow 	"NBNS server failure",
2834bff34e3Sthurlow 	"no such name",
2844bff34e3Sthurlow 	"unsupported request",
2854bff34e3Sthurlow 	"request rejected",
2864bff34e3Sthurlow 	"name already registered"
2874bff34e3Sthurlow };
2884bff34e3Sthurlow 
2894bff34e3Sthurlow static const char *nb_err[] = {
2904bff34e3Sthurlow 	"host not found",
2914bff34e3Sthurlow 	"too many redirects",
2924bff34e3Sthurlow 	"invalid response",
2934bff34e3Sthurlow 	"NETBIOS name too long",
2944bff34e3Sthurlow 	"no interface to broadcast on and no NBNS server specified"
2954bff34e3Sthurlow };
2964bff34e3Sthurlow #endif
2974bff34e3Sthurlow 
2984bff34e3Sthurlow const char *
2994bff34e3Sthurlow nb_strerror(int error)
3004bff34e3Sthurlow {
3014bff34e3Sthurlow 	if (error == 0)
3024bff34e3Sthurlow 		return (NULL);
3034bff34e3Sthurlow 	if (error <= NBERR_ACTIVE)
3044bff34e3Sthurlow 		return (nb_err_rcode[error - 1]);
3054bff34e3Sthurlow 	else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX)
3064bff34e3Sthurlow 		return (nb_err[error - NBERR_HOSTNOTFOUND]);
3074bff34e3Sthurlow 	else
3084bff34e3Sthurlow 		return (NULL);
3094bff34e3Sthurlow }
310