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