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 /* 36613a2f6bSGordon Ross * Copyright 2009 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 60*8eb99b82SGordon 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 63*8eb99b82SGordon Ross /* 64*8eb99b82SGordon Ross * API for seting NetBIOS name lookup flags: 65*8eb99b82SGordon Ross * NetBIOS name lookup enable, 66*8eb99b82SGordon Ross * NetBIOS broadcast enable. 67*8eb99b82SGordon Ross */ 68*8eb99b82SGordon Ross int 69*8eb99b82SGordon Ross smb_ctx_setnbflags(struct smb_ctx *ctx, int ns_ena, int bc_ena) 70*8eb99b82SGordon Ross { 71*8eb99b82SGordon Ross struct nb_ctx *nb = ctx->ct_nb; 72*8eb99b82SGordon Ross 73*8eb99b82SGordon Ross if (nb == NULL) 74*8eb99b82SGordon Ross return (EINVAL); 75*8eb99b82SGordon Ross 76*8eb99b82SGordon Ross nb_ctx_setnbflags(nb, ns_ena, bc_ena); 77*8eb99b82SGordon Ross return (0); 78*8eb99b82SGordon 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 ctx->nb_flags = NBCF_NS_ENABLE | NBCF_BC_ENABLE; 1184bff34e3Sthurlow *ctxpp = ctx; 1194bff34e3Sthurlow return (0); 1204bff34e3Sthurlow } 1214bff34e3Sthurlow 1224bff34e3Sthurlow void 1234bff34e3Sthurlow nb_ctx_done(struct nb_ctx *ctx) 1244bff34e3Sthurlow { 1254bff34e3Sthurlow if (ctx == NULL) 1264bff34e3Sthurlow return; 1274bff34e3Sthurlow if (ctx->nb_scope) 1284bff34e3Sthurlow free(ctx->nb_scope); 1294bff34e3Sthurlow if (ctx) 1304bff34e3Sthurlow free(ctx); 1314bff34e3Sthurlow } 1324bff34e3Sthurlow 133*8eb99b82SGordon Ross void 134*8eb99b82SGordon Ross nb_ctx_setnbflags(struct nb_ctx *nb, int ns_ena, int bc_ena) 135*8eb99b82SGordon Ross { 136*8eb99b82SGordon Ross nb->nb_flags &= ~(NBCF_NS_ENABLE | NBCF_BC_ENABLE); 137*8eb99b82SGordon Ross if (ns_ena) { 138*8eb99b82SGordon Ross nb->nb_flags = NBCF_NS_ENABLE; 139*8eb99b82SGordon Ross if (bc_ena) 140*8eb99b82SGordon Ross nb->nb_flags = NBCF_BC_ENABLE; 141*8eb99b82SGordon Ross } 142*8eb99b82SGordon Ross } 143*8eb99b82SGordon Ross 144613a2f6bSGordon Ross int 145613a2f6bSGordon Ross nb_ctx_setwins(struct nb_ctx *ctx, const char *wins1, const char *wins2) 1464bff34e3Sthurlow { 1474bff34e3Sthurlow struct in_addr ina; 1484bff34e3Sthurlow int error; 1494bff34e3Sthurlow 150613a2f6bSGordon Ross if (wins1 == NULL) { 151613a2f6bSGordon Ross ctx->nb_wins1 = 0; 152613a2f6bSGordon Ross ctx->nb_wins2 = 0; 153613a2f6bSGordon Ross return (0); 154613a2f6bSGordon Ross } 1554bff34e3Sthurlow 156613a2f6bSGordon Ross error = nb_resolvehost_in(wins1, &ina); 1574bff34e3Sthurlow if (error) { 1584bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 159613a2f6bSGordon Ross error, wins1); 1604bff34e3Sthurlow return (error); 1614bff34e3Sthurlow } 162613a2f6bSGordon Ross ctx->nb_wins1 = ina.s_addr; 1634bff34e3Sthurlow 164613a2f6bSGordon Ross if (wins2 == NULL) 165613a2f6bSGordon Ross ctx->nb_wins2 = 0; 166613a2f6bSGordon Ross else { 167613a2f6bSGordon Ross error = nb_resolvehost_in(wins2, &ina); 168613a2f6bSGordon Ross if (error) { 169613a2f6bSGordon Ross smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 170613a2f6bSGordon Ross error, wins2); 171613a2f6bSGordon Ross return (error); 172613a2f6bSGordon Ross } 173613a2f6bSGordon Ross ctx->nb_wins2 = ina.s_addr; 174613a2f6bSGordon Ross } 1754bff34e3Sthurlow return (0); 1764bff34e3Sthurlow } 1774bff34e3Sthurlow 1784bff34e3Sthurlow /* 1794bff34e3Sthurlow * This is called by "smbutil lookup" to handle the 1804bff34e3Sthurlow * "-w wins_server" option. Let the semantics of 1814bff34e3Sthurlow * this option be: Use specified WINS server only. 1824bff34e3Sthurlow * If specified server is the broadcast address, 1834bff34e3Sthurlow * set broadcast mode (and no WINS servers). 1844bff34e3Sthurlow */ 1854bff34e3Sthurlow int 1864bff34e3Sthurlow nb_ctx_setns(struct nb_ctx *ctx, const char *addr) 1874bff34e3Sthurlow { 1884bff34e3Sthurlow int error; 1894bff34e3Sthurlow 190613a2f6bSGordon Ross error = nb_ctx_setwins(ctx, addr, NULL); 1914bff34e3Sthurlow if (error) 1924bff34e3Sthurlow return (error); 1934bff34e3Sthurlow 1944bff34e3Sthurlow /* Deal with explicit request for broadcast. */ 1954bff34e3Sthurlow if (ctx->nb_wins1 == INADDR_BROADCAST) { 1964bff34e3Sthurlow ctx->nb_wins1 = 0; 1974bff34e3Sthurlow ctx->nb_flags |= NBCF_BC_ENABLE; 1984bff34e3Sthurlow } 1994bff34e3Sthurlow return (0); 2004bff34e3Sthurlow } 2014bff34e3Sthurlow 2024bff34e3Sthurlow int 2034bff34e3Sthurlow nb_ctx_setscope(struct nb_ctx *ctx, const char *scope) 2044bff34e3Sthurlow { 2054bff34e3Sthurlow size_t slen = strlen(scope); 2064bff34e3Sthurlow 2074bff34e3Sthurlow if (slen >= 128) { 2084bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, 2094bff34e3Sthurlow "scope '%s' is too long"), 0, scope); 2104bff34e3Sthurlow return (ENAMETOOLONG); 2114bff34e3Sthurlow } 2124bff34e3Sthurlow if (ctx->nb_scope) 2134bff34e3Sthurlow free(ctx->nb_scope); 2144bff34e3Sthurlow ctx->nb_scope = malloc(slen + 1); 2154bff34e3Sthurlow if (ctx->nb_scope == NULL) 2164bff34e3Sthurlow return (ENOMEM); 2174bff34e3Sthurlow nls_str_upper(ctx->nb_scope, scope); 2184bff34e3Sthurlow return (0); 2194bff34e3Sthurlow } 2204bff34e3Sthurlow 2214bff34e3Sthurlow /* 2224bff34e3Sthurlow * Now get the WINS server IP addresses directly 2234bff34e3Sthurlow * when reading the RC files, so no longer need to 2244bff34e3Sthurlow * lookup any names here. 2254bff34e3Sthurlow */ 2264bff34e3Sthurlow int 2274bff34e3Sthurlow nb_ctx_resolve(struct nb_ctx *ctx) 2284bff34e3Sthurlow { 2294bff34e3Sthurlow ctx->nb_flags |= NBCF_RESOLVED; 2304bff34e3Sthurlow return (0); 2314bff34e3Sthurlow } 2324bff34e3Sthurlow 2334bff34e3Sthurlow /* 2344bff34e3Sthurlow * used level values: 2354bff34e3Sthurlow * 0 - default 2364bff34e3Sthurlow * 1 - server 2374bff34e3Sthurlow * 2384bff34e3Sthurlow * All of these are normally system-wide settings; 2394bff34e3Sthurlow * the checks are in rc_parse() in rcfile.c. 2404bff34e3Sthurlow */ 2414bff34e3Sthurlow int 2424bff34e3Sthurlow nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx, 2434bff34e3Sthurlow const char *sname, int level) 2444bff34e3Sthurlow { 245613a2f6bSGordon Ross char *wins1, *wins2; 2464bff34e3Sthurlow int error; 2474bff34e3Sthurlow int nbns_enable; 2484bff34e3Sthurlow int nbns_broadcast; 2494bff34e3Sthurlow 2504bff34e3Sthurlow if (level > 1) 2514bff34e3Sthurlow return (EINVAL); 252613a2f6bSGordon Ross 253613a2f6bSGordon Ross /* External callers pass NULL to get the default. */ 254613a2f6bSGordon Ross if (rcfile == NULL) 255613a2f6bSGordon Ross rcfile = smb_rc; 256613a2f6bSGordon Ross 2574bff34e3Sthurlow #ifdef NOT_DEFINED 2584bff34e3Sthurlow rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo); 2594bff34e3Sthurlow rc_getstringptr(rcfile, sname, "nbscope", &p); 2604bff34e3Sthurlow if (p) 2614bff34e3Sthurlow nb_ctx_setscope(ctx, p); 2624bff34e3Sthurlow #endif 263613a2f6bSGordon Ross /* 264613a2f6bSGordon Ross * Get "wins1", "wins2" config strings. 265613a2f6bSGordon Ross * Also support legacy "nbns". 266613a2f6bSGordon Ross */ 267613a2f6bSGordon Ross rc_getstringptr(rcfile, sname, "wins1", &wins1); 268613a2f6bSGordon Ross if (wins1 == NULL) 269613a2f6bSGordon Ross rc_getstringptr(rcfile, sname, "nbns", &wins1); 270613a2f6bSGordon Ross rc_getstringptr(rcfile, sname, "wins2", &wins2); 271613a2f6bSGordon Ross 272613a2f6bSGordon Ross if (wins1 != NULL) { 273613a2f6bSGordon Ross error = nb_ctx_setwins(ctx, wins1, wins2); 2744bff34e3Sthurlow if (error) { 2754bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, 2764bff34e3Sthurlow "invalid address specified in the section %s"), 2774bff34e3Sthurlow 0, sname); 2784bff34e3Sthurlow return (error); 2794bff34e3Sthurlow } 2804bff34e3Sthurlow } 281*8eb99b82SGordon Ross 282*8eb99b82SGordon Ross /* 283*8eb99b82SGordon Ross * Want to use nb_ctx_setnbflags here, but 284*8eb99b82SGordon Ross * have to get both boolean values first, 285*8eb99b82SGordon Ross * either from settings or defaults. 286*8eb99b82SGordon Ross */ 287*8eb99b82SGordon Ross nbns_enable = nbns_broadcast = -1; /* not set */ 288*8eb99b82SGordon Ross rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable); 289*8eb99b82SGordon Ross rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast); 290*8eb99b82SGordon Ross if (nbns_enable >= 0 || nbns_broadcast >= 0) { 291*8eb99b82SGordon Ross if (nbns_enable < 0) 292*8eb99b82SGordon Ross nbns_enable = 1; /* default */ 293*8eb99b82SGordon Ross if (nbns_broadcast < 0) 294*8eb99b82SGordon Ross nbns_broadcast = 1; /* default */ 295*8eb99b82SGordon Ross nb_ctx_setnbflags(ctx, nbns_enable, nbns_broadcast); 296*8eb99b82SGordon Ross } 2974bff34e3Sthurlow return (0); 2984bff34e3Sthurlow } 2994bff34e3Sthurlow 3004bff34e3Sthurlow #ifdef I18N /* never defined, permits xgettext(1) to pick out strings */ 3014bff34e3Sthurlow static const char *nb_err_rcode[] = { 3024bff34e3Sthurlow gettext("bad request/response format"), 3034bff34e3Sthurlow gettext("NBNS server failure"), 3044bff34e3Sthurlow gettext("no such name"), 3054bff34e3Sthurlow gettext("unsupported request"), 3064bff34e3Sthurlow gettext("request rejected"), 3074bff34e3Sthurlow gettext("name already registered)" 3084bff34e3Sthurlow }; 3094bff34e3Sthurlow 3104bff34e3Sthurlow static const char *nb_err[] = { 3114bff34e3Sthurlow gettext("host not found"), 3124bff34e3Sthurlow gettext("too many redirects"), 3134bff34e3Sthurlow gettext("invalid response"), 3144bff34e3Sthurlow gettext("NETBIOS name too long"), 3154bff34e3Sthurlow gettext("no interface to broadcast on and no NBNS server specified") 3164bff34e3Sthurlow }; 3174bff34e3Sthurlow #else 3184bff34e3Sthurlow static const char *nb_err_rcode[] = { 3194bff34e3Sthurlow "bad request/response format", 3204bff34e3Sthurlow "NBNS server failure", 3214bff34e3Sthurlow "no such name", 3224bff34e3Sthurlow "unsupported request", 3234bff34e3Sthurlow "request rejected", 3244bff34e3Sthurlow "name already registered" 3254bff34e3Sthurlow }; 3264bff34e3Sthurlow 3274bff34e3Sthurlow static const char *nb_err[] = { 3284bff34e3Sthurlow "host not found", 3294bff34e3Sthurlow "too many redirects", 3304bff34e3Sthurlow "invalid response", 3314bff34e3Sthurlow "NETBIOS name too long", 3324bff34e3Sthurlow "no interface to broadcast on and no NBNS server specified" 3334bff34e3Sthurlow }; 3344bff34e3Sthurlow #endif 3354bff34e3Sthurlow 3364bff34e3Sthurlow const char * 3374bff34e3Sthurlow nb_strerror(int error) 3384bff34e3Sthurlow { 3394bff34e3Sthurlow if (error == 0) 3404bff34e3Sthurlow return (NULL); 3414bff34e3Sthurlow if (error <= NBERR_ACTIVE) 3424bff34e3Sthurlow return (nb_err_rcode[error - 1]); 3434bff34e3Sthurlow else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX) 3444bff34e3Sthurlow return (nb_err[error - NBERR_HOSTNOTFOUND]); 3454bff34e3Sthurlow else 3464bff34e3Sthurlow return (NULL); 3474bff34e3Sthurlow } 348