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 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 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 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 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 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 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 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); 1564bff34e3Sthurlow if (error) { 1574bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 158613a2f6bSGordon Ross error, wins1); 1594bff34e3Sthurlow return (error); 1604bff34e3Sthurlow } 161613a2f6bSGordon Ross ctx->nb_wins1 = ina.s_addr; 1624bff34e3Sthurlow 163613a2f6bSGordon Ross if (wins2 == NULL) 164613a2f6bSGordon Ross ctx->nb_wins2 = 0; 165613a2f6bSGordon Ross else { 166613a2f6bSGordon Ross error = nb_resolvehost_in(wins2, &ina); 167613a2f6bSGordon Ross if (error) { 168613a2f6bSGordon Ross smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 169613a2f6bSGordon Ross error, wins2); 170613a2f6bSGordon Ross return (error); 171613a2f6bSGordon Ross } 172613a2f6bSGordon Ross ctx->nb_wins2 = ina.s_addr; 173613a2f6bSGordon Ross } 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 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 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 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 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); 2898eb99b82SGordon 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