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
35613a2f6bSGordon Ross /*
36*42d15982SGordon Ross * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
37613a2f6bSGordon Ross * Use is subject to license terms.
38613a2f6bSGordon Ross */
394bff34e3Sthurlow
404bff34e3Sthurlow #include <sys/param.h>
414bff34e3Sthurlow #include <sys/socket.h>
424bff34e3Sthurlow
434bff34e3Sthurlow #include <errno.h>
44613a2f6bSGordon Ross #include <stdio.h>
454bff34e3Sthurlow #include <stdlib.h>
464bff34e3Sthurlow #include <string.h>
474bff34e3Sthurlow #include <strings.h>
484bff34e3Sthurlow #include <unistd.h>
494bff34e3Sthurlow #include <libintl.h>
50613a2f6bSGordon Ross #include <netdb.h>
514bff34e3Sthurlow
524bff34e3Sthurlow #include <netinet/in.h>
534bff34e3Sthurlow #include <arpa/inet.h>
544bff34e3Sthurlow
55613a2f6bSGordon Ross #include <cflib.h>
564bff34e3Sthurlow #include <netsmb/netbios.h>
574bff34e3Sthurlow #include <netsmb/smb_lib.h>
584bff34e3Sthurlow #include <netsmb/nb_lib.h>
594bff34e3Sthurlow
608eb99b82SGordon Ross void nb_ctx_setnbflags(struct nb_ctx *, int ns_ena, int bc_ena);
61613a2f6bSGordon Ross int nb_ctx_setwins(struct nb_ctx *, const char *, const char *);
62613a2f6bSGordon Ross
638eb99b82SGordon Ross /*
648eb99b82SGordon Ross * API for seting NetBIOS name lookup flags:
658eb99b82SGordon Ross * NetBIOS name lookup enable,
668eb99b82SGordon Ross * NetBIOS broadcast enable.
678eb99b82SGordon Ross */
688eb99b82SGordon Ross int
smb_ctx_setnbflags(struct smb_ctx * ctx,int ns_ena,int bc_ena)698eb99b82SGordon Ross smb_ctx_setnbflags(struct smb_ctx *ctx, int ns_ena, int bc_ena)
708eb99b82SGordon Ross {
718eb99b82SGordon Ross struct nb_ctx *nb = ctx->ct_nb;
728eb99b82SGordon Ross
738eb99b82SGordon Ross if (nb == NULL)
748eb99b82SGordon Ross return (EINVAL);
758eb99b82SGordon Ross
768eb99b82SGordon Ross nb_ctx_setnbflags(nb, ns_ena, bc_ena);
778eb99b82SGordon Ross return (0);
788eb99b82SGordon Ross }
79613a2f6bSGordon Ross
80613a2f6bSGordon Ross /*
81613a2f6bSGordon Ross * API for library consumer to set wins1, wins2
82613a2f6bSGordon Ross */
83613a2f6bSGordon Ross int
smb_ctx_setwins(struct smb_ctx * ctx,const char * wins1,const char * wins2)84613a2f6bSGordon Ross smb_ctx_setwins(struct smb_ctx *ctx, const char *wins1, const char *wins2)
85613a2f6bSGordon Ross {
86613a2f6bSGordon Ross struct nb_ctx *nb = ctx->ct_nb;
87613a2f6bSGordon Ross
88613a2f6bSGordon Ross if (nb == NULL)
89613a2f6bSGordon Ross return (EINVAL);
90613a2f6bSGordon Ross
91613a2f6bSGordon Ross return (nb_ctx_setwins(nb, wins1, wins2));
92613a2f6bSGordon Ross }
93613a2f6bSGordon Ross
94613a2f6bSGordon Ross /*
95613a2f6bSGordon Ross * API for library consumer to set NB scope.
96613a2f6bSGordon Ross */
97613a2f6bSGordon Ross int
smb_ctx_setscope(struct smb_ctx * ctx,const char * scope)98613a2f6bSGordon Ross smb_ctx_setscope(struct smb_ctx *ctx, const char *scope)
99613a2f6bSGordon Ross {
100613a2f6bSGordon Ross struct nb_ctx *nb = ctx->ct_nb;
101613a2f6bSGordon Ross
102613a2f6bSGordon Ross if (nb == NULL)
103613a2f6bSGordon Ross return (EINVAL);
104613a2f6bSGordon Ross
105613a2f6bSGordon Ross return (nb_ctx_setscope(nb, scope));
106613a2f6bSGordon Ross }
1074bff34e3Sthurlow
1084bff34e3Sthurlow int
nb_ctx_create(struct nb_ctx ** ctxpp)1094bff34e3Sthurlow nb_ctx_create(struct nb_ctx **ctxpp)
1104bff34e3Sthurlow {
1114bff34e3Sthurlow struct nb_ctx *ctx;
1124bff34e3Sthurlow
1134bff34e3Sthurlow ctx = malloc(sizeof (struct nb_ctx));
1144bff34e3Sthurlow if (ctx == NULL)
1154bff34e3Sthurlow return (ENOMEM);
1164bff34e3Sthurlow bzero(ctx, sizeof (struct nb_ctx));
1174bff34e3Sthurlow *ctxpp = ctx;
1184bff34e3Sthurlow return (0);
1194bff34e3Sthurlow }
1204bff34e3Sthurlow
1214bff34e3Sthurlow void
nb_ctx_done(struct nb_ctx * ctx)1224bff34e3Sthurlow nb_ctx_done(struct nb_ctx *ctx)
1234bff34e3Sthurlow {
1244bff34e3Sthurlow if (ctx == NULL)
1254bff34e3Sthurlow return;
1264bff34e3Sthurlow if (ctx->nb_scope)
1274bff34e3Sthurlow free(ctx->nb_scope);
1284bff34e3Sthurlow if (ctx)
1294bff34e3Sthurlow free(ctx);
1304bff34e3Sthurlow }
1314bff34e3Sthurlow
1328eb99b82SGordon Ross void
nb_ctx_setnbflags(struct nb_ctx * nb,int ns_ena,int bc_ena)1338eb99b82SGordon Ross nb_ctx_setnbflags(struct nb_ctx *nb, int ns_ena, int bc_ena)
1348eb99b82SGordon Ross {
1358eb99b82SGordon Ross nb->nb_flags &= ~(NBCF_NS_ENABLE | NBCF_BC_ENABLE);
1368eb99b82SGordon Ross if (ns_ena) {
137*42d15982SGordon Ross nb->nb_flags |= NBCF_NS_ENABLE;
1388eb99b82SGordon Ross if (bc_ena)
139*42d15982SGordon Ross nb->nb_flags |= NBCF_BC_ENABLE;
1408eb99b82SGordon Ross }
1418eb99b82SGordon Ross }
1428eb99b82SGordon Ross
143613a2f6bSGordon Ross int
nb_ctx_setwins(struct nb_ctx * ctx,const char * wins1,const char * wins2)144613a2f6bSGordon Ross nb_ctx_setwins(struct nb_ctx *ctx, const char *wins1, const char *wins2)
1454bff34e3Sthurlow {
1464bff34e3Sthurlow struct in_addr ina;
1474bff34e3Sthurlow int error;
1484bff34e3Sthurlow
149613a2f6bSGordon Ross if (wins1 == NULL) {
150613a2f6bSGordon Ross ctx->nb_wins1 = 0;
151613a2f6bSGordon Ross ctx->nb_wins2 = 0;
152613a2f6bSGordon Ross return (0);
153613a2f6bSGordon Ross }
1544bff34e3Sthurlow
155613a2f6bSGordon Ross error = nb_resolvehost_in(wins1, &ina);
156613a2f6bSGordon Ross if (error) {
157613a2f6bSGordon Ross smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"),
158613a2f6bSGordon Ross error, wins1);
159613a2f6bSGordon Ross return (error);
160613a2f6bSGordon Ross }
161613a2f6bSGordon Ross ctx->nb_wins1 = ina.s_addr;
162613a2f6bSGordon Ross
163613a2f6bSGordon Ross if (wins2 == NULL)
164613a2f6bSGordon Ross ctx->nb_wins2 = 0;
165613a2f6bSGordon Ross else {
166613a2f6bSGordon Ross error = nb_resolvehost_in(wins2, &ina);
1674bff34e3Sthurlow if (error) {
1684bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"),
169613a2f6bSGordon Ross error, wins2);
1704bff34e3Sthurlow return (error);
1714bff34e3Sthurlow }
172613a2f6bSGordon Ross ctx->nb_wins2 = ina.s_addr;
1734bff34e3Sthurlow }
1744bff34e3Sthurlow return (0);
1754bff34e3Sthurlow }
1764bff34e3Sthurlow
1774bff34e3Sthurlow /*
1784bff34e3Sthurlow * This is called by "smbutil lookup" to handle the
1794bff34e3Sthurlow * "-w wins_server" option. Let the semantics of
1804bff34e3Sthurlow * this option be: Use specified WINS server only.
1814bff34e3Sthurlow * If specified server is the broadcast address,
1824bff34e3Sthurlow * set broadcast mode (and no WINS servers).
1834bff34e3Sthurlow */
1844bff34e3Sthurlow int
nb_ctx_setns(struct nb_ctx * ctx,const char * addr)1854bff34e3Sthurlow nb_ctx_setns(struct nb_ctx *ctx, const char *addr)
1864bff34e3Sthurlow {
1874bff34e3Sthurlow int error;
1884bff34e3Sthurlow
189613a2f6bSGordon Ross error = nb_ctx_setwins(ctx, addr, NULL);
1904bff34e3Sthurlow if (error)
1914bff34e3Sthurlow return (error);
1924bff34e3Sthurlow
1934bff34e3Sthurlow /* Deal with explicit request for broadcast. */
1944bff34e3Sthurlow if (ctx->nb_wins1 == INADDR_BROADCAST) {
1954bff34e3Sthurlow ctx->nb_wins1 = 0;
1964bff34e3Sthurlow ctx->nb_flags |= NBCF_BC_ENABLE;
1974bff34e3Sthurlow }
1984bff34e3Sthurlow return (0);
1994bff34e3Sthurlow }
2004bff34e3Sthurlow
2014bff34e3Sthurlow int
nb_ctx_setscope(struct nb_ctx * ctx,const char * scope)2024bff34e3Sthurlow nb_ctx_setscope(struct nb_ctx *ctx, const char *scope)
2034bff34e3Sthurlow {
2044bff34e3Sthurlow size_t slen = strlen(scope);
2054bff34e3Sthurlow
2064bff34e3Sthurlow if (slen >= 128) {
2074bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN,
2084bff34e3Sthurlow "scope '%s' is too long"), 0, scope);
2094bff34e3Sthurlow return (ENAMETOOLONG);
2104bff34e3Sthurlow }
2114bff34e3Sthurlow if (ctx->nb_scope)
2124bff34e3Sthurlow free(ctx->nb_scope);
2134bff34e3Sthurlow ctx->nb_scope = malloc(slen + 1);
2144bff34e3Sthurlow if (ctx->nb_scope == NULL)
2154bff34e3Sthurlow return (ENOMEM);
2164bff34e3Sthurlow nls_str_upper(ctx->nb_scope, scope);
2174bff34e3Sthurlow return (0);
2184bff34e3Sthurlow }
2194bff34e3Sthurlow
2204bff34e3Sthurlow /*
2214bff34e3Sthurlow * Now get the WINS server IP addresses directly
2224bff34e3Sthurlow * when reading the RC files, so no longer need to
2234bff34e3Sthurlow * lookup any names here.
2244bff34e3Sthurlow */
2254bff34e3Sthurlow int
nb_ctx_resolve(struct nb_ctx * ctx)2264bff34e3Sthurlow nb_ctx_resolve(struct nb_ctx *ctx)
2274bff34e3Sthurlow {
2284bff34e3Sthurlow ctx->nb_flags |= NBCF_RESOLVED;
2294bff34e3Sthurlow return (0);
2304bff34e3Sthurlow }
2314bff34e3Sthurlow
2324bff34e3Sthurlow /*
2334bff34e3Sthurlow * used level values:
2344bff34e3Sthurlow * 0 - default
2354bff34e3Sthurlow * 1 - server
2364bff34e3Sthurlow *
2374bff34e3Sthurlow * All of these are normally system-wide settings;
2384bff34e3Sthurlow * the checks are in rc_parse() in rcfile.c.
2394bff34e3Sthurlow */
2404bff34e3Sthurlow int
nb_ctx_readrcsection(struct rcfile * rcfile,struct nb_ctx * ctx,const char * sname,int level)2414bff34e3Sthurlow nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx,
2424bff34e3Sthurlow const char *sname, int level)
2434bff34e3Sthurlow {
244613a2f6bSGordon Ross char *wins1, *wins2;
2454bff34e3Sthurlow int error;
2464bff34e3Sthurlow int nbns_enable;
2474bff34e3Sthurlow int nbns_broadcast;
2484bff34e3Sthurlow
2494bff34e3Sthurlow if (level > 1)
2504bff34e3Sthurlow return (EINVAL);
251613a2f6bSGordon Ross
252613a2f6bSGordon Ross /* External callers pass NULL to get the default. */
253613a2f6bSGordon Ross if (rcfile == NULL)
254613a2f6bSGordon Ross rcfile = smb_rc;
255613a2f6bSGordon Ross
2564bff34e3Sthurlow #ifdef NOT_DEFINED
2574bff34e3Sthurlow rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo);
2584bff34e3Sthurlow rc_getstringptr(rcfile, sname, "nbscope", &p);
2594bff34e3Sthurlow if (p)
2604bff34e3Sthurlow nb_ctx_setscope(ctx, p);
2614bff34e3Sthurlow #endif
262613a2f6bSGordon Ross /*
263613a2f6bSGordon Ross * Get "wins1", "wins2" config strings.
264613a2f6bSGordon Ross * Also support legacy "nbns".
265613a2f6bSGordon Ross */
266613a2f6bSGordon Ross rc_getstringptr(rcfile, sname, "wins1", &wins1);
267613a2f6bSGordon Ross if (wins1 == NULL)
268613a2f6bSGordon Ross rc_getstringptr(rcfile, sname, "nbns", &wins1);
269613a2f6bSGordon Ross rc_getstringptr(rcfile, sname, "wins2", &wins2);
270613a2f6bSGordon Ross
271613a2f6bSGordon Ross if (wins1 != NULL) {
272613a2f6bSGordon Ross error = nb_ctx_setwins(ctx, wins1, wins2);
2734bff34e3Sthurlow if (error) {
2744bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN,
2754bff34e3Sthurlow "invalid address specified in the section %s"),
2764bff34e3Sthurlow 0, sname);
2774bff34e3Sthurlow return (error);
2784bff34e3Sthurlow }
2794bff34e3Sthurlow }
2808eb99b82SGordon Ross
2818eb99b82SGordon Ross /*
2828eb99b82SGordon Ross * Want to use nb_ctx_setnbflags here, but
2838eb99b82SGordon Ross * have to get both boolean values first,
2848eb99b82SGordon Ross * either from settings or defaults.
2858eb99b82SGordon Ross */
286*42d15982SGordon Ross nbns_enable = nbns_broadcast = 1; /* defaults */
2878eb99b82SGordon Ross rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable);
2888eb99b82SGordon Ross rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast);
289*42d15982SGordon Ross nb_ctx_setnbflags(ctx, nbns_enable, nbns_broadcast);
290*42d15982SGordon Ross
2914bff34e3Sthurlow return (0);
2924bff34e3Sthurlow }
2934bff34e3Sthurlow
2944bff34e3Sthurlow #ifdef I18N /* never defined, permits xgettext(1) to pick out strings */
2954bff34e3Sthurlow static const char *nb_err_rcode[] = {
2964bff34e3Sthurlow gettext("bad request/response format"),
2974bff34e3Sthurlow gettext("NBNS server failure"),
2984bff34e3Sthurlow gettext("no such name"),
2994bff34e3Sthurlow gettext("unsupported request"),
3004bff34e3Sthurlow gettext("request rejected"),
3014bff34e3Sthurlow gettext("name already registered)"
3024bff34e3Sthurlow };
3034bff34e3Sthurlow
3044bff34e3Sthurlow static const char *nb_err[] = {
3054bff34e3Sthurlow gettext("host not found"),
3064bff34e3Sthurlow gettext("too many redirects"),
3074bff34e3Sthurlow gettext("invalid response"),
3084bff34e3Sthurlow gettext("NETBIOS name too long"),
3094bff34e3Sthurlow gettext("no interface to broadcast on and no NBNS server specified")
3104bff34e3Sthurlow };
3114bff34e3Sthurlow #else
3124bff34e3Sthurlow static const char *nb_err_rcode[] = {
3134bff34e3Sthurlow "bad request/response format",
3144bff34e3Sthurlow "NBNS server failure",
3154bff34e3Sthurlow "no such name",
3164bff34e3Sthurlow "unsupported request",
3174bff34e3Sthurlow "request rejected",
3184bff34e3Sthurlow "name already registered"
3194bff34e3Sthurlow };
3204bff34e3Sthurlow
3214bff34e3Sthurlow static const char *nb_err[] = {
3224bff34e3Sthurlow "host not found",
3234bff34e3Sthurlow "too many redirects",
3244bff34e3Sthurlow "invalid response",
3254bff34e3Sthurlow "NETBIOS name too long",
3264bff34e3Sthurlow "no interface to broadcast on and no NBNS server specified"
3274bff34e3Sthurlow };
3284bff34e3Sthurlow #endif
3294bff34e3Sthurlow
3304bff34e3Sthurlow const char *
3314bff34e3Sthurlow nb_strerror(int error)
3324bff34e3Sthurlow {
3334bff34e3Sthurlow if (error == 0)
3344bff34e3Sthurlow return (NULL);
3354bff34e3Sthurlow if (error <= NBERR_ACTIVE)
3364bff34e3Sthurlow return (nb_err_rcode[error - 1]);
3374bff34e3Sthurlow else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX)
3384bff34e3Sthurlow return (nb_err[error - NBERR_HOSTNOTFOUND]);
3394bff34e3Sthurlow else
3404bff34e3Sthurlow return (NULL);
3414bff34e3Sthurlow }
342