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