1*4bff34e3Sthurlow /* 2*4bff34e3Sthurlow * Copyright (c) 2000, 2001 Boris Popov 3*4bff34e3Sthurlow * All rights reserved. 4*4bff34e3Sthurlow * 5*4bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 6*4bff34e3Sthurlow * modification, are permitted provided that the following conditions 7*4bff34e3Sthurlow * are met: 8*4bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 9*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 10*4bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 11*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 12*4bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 13*4bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 14*4bff34e3Sthurlow * must display the following acknowledgement: 15*4bff34e3Sthurlow * This product includes software developed by Boris Popov. 16*4bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 17*4bff34e3Sthurlow * may be used to endorse or promote products derived from this software 18*4bff34e3Sthurlow * without specific prior written permission. 19*4bff34e3Sthurlow * 20*4bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*4bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*4bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*4bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*4bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*4bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*4bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*4bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*4bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*4bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*4bff34e3Sthurlow * SUCH DAMAGE. 31*4bff34e3Sthurlow * 32*4bff34e3Sthurlow * $Id: nb.c,v 1.1.1.2 2001/07/06 22:38:42 conrad Exp $ 33*4bff34e3Sthurlow */ 34*4bff34e3Sthurlow 35*4bff34e3Sthurlow #pragma ident "%Z%%M% %I% %E% SMI" 36*4bff34e3Sthurlow 37*4bff34e3Sthurlow #include <sys/param.h> 38*4bff34e3Sthurlow #include <sys/socket.h> 39*4bff34e3Sthurlow 40*4bff34e3Sthurlow #include <ctype.h> 41*4bff34e3Sthurlow #include <netdb.h> 42*4bff34e3Sthurlow #include <errno.h> 43*4bff34e3Sthurlow #include <stdlib.h> 44*4bff34e3Sthurlow #include <string.h> 45*4bff34e3Sthurlow #include <strings.h> 46*4bff34e3Sthurlow #include <stdio.h> 47*4bff34e3Sthurlow #include <unistd.h> 48*4bff34e3Sthurlow #include <libintl.h> 49*4bff34e3Sthurlow 50*4bff34e3Sthurlow #include <netinet/in.h> 51*4bff34e3Sthurlow #include <arpa/inet.h> 52*4bff34e3Sthurlow 53*4bff34e3Sthurlow #include <netsmb/netbios.h> 54*4bff34e3Sthurlow #include <netsmb/smb_lib.h> 55*4bff34e3Sthurlow #include <netsmb/nb_lib.h> 56*4bff34e3Sthurlow 57*4bff34e3Sthurlow #include <cflib.h> 58*4bff34e3Sthurlow 59*4bff34e3Sthurlow int 60*4bff34e3Sthurlow nb_ctx_create(struct nb_ctx **ctxpp) 61*4bff34e3Sthurlow { 62*4bff34e3Sthurlow struct nb_ctx *ctx; 63*4bff34e3Sthurlow 64*4bff34e3Sthurlow ctx = malloc(sizeof (struct nb_ctx)); 65*4bff34e3Sthurlow if (ctx == NULL) 66*4bff34e3Sthurlow return (ENOMEM); 67*4bff34e3Sthurlow bzero(ctx, sizeof (struct nb_ctx)); 68*4bff34e3Sthurlow ctx->nb_flags = NBCF_NS_ENABLE | NBCF_BC_ENABLE; 69*4bff34e3Sthurlow *ctxpp = ctx; 70*4bff34e3Sthurlow return (0); 71*4bff34e3Sthurlow } 72*4bff34e3Sthurlow 73*4bff34e3Sthurlow void 74*4bff34e3Sthurlow nb_ctx_done(struct nb_ctx *ctx) 75*4bff34e3Sthurlow { 76*4bff34e3Sthurlow if (ctx == NULL) 77*4bff34e3Sthurlow return; 78*4bff34e3Sthurlow if (ctx->nb_scope) 79*4bff34e3Sthurlow free(ctx->nb_scope); 80*4bff34e3Sthurlow if (ctx) 81*4bff34e3Sthurlow free(ctx); 82*4bff34e3Sthurlow } 83*4bff34e3Sthurlow 84*4bff34e3Sthurlow static int 85*4bff34e3Sthurlow nb_ctx_setwins(in_addr_t *ina_p, const char *str) 86*4bff34e3Sthurlow { 87*4bff34e3Sthurlow struct in_addr ina; 88*4bff34e3Sthurlow struct sockaddr *sap; 89*4bff34e3Sthurlow int error; 90*4bff34e3Sthurlow 91*4bff34e3Sthurlow if (str == NULL || str[0] == 0) 92*4bff34e3Sthurlow return (EINVAL); 93*4bff34e3Sthurlow 94*4bff34e3Sthurlow if (inet_aton(str, &ina)) { 95*4bff34e3Sthurlow *ina_p = ina.s_addr; 96*4bff34e3Sthurlow } else { 97*4bff34e3Sthurlow error = nb_resolvehost_in(str, &sap); 98*4bff34e3Sthurlow if (error) { 99*4bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 100*4bff34e3Sthurlow error, str); 101*4bff34e3Sthurlow return (error); 102*4bff34e3Sthurlow } 103*4bff34e3Sthurlow if (sap->sa_family != AF_INET) { 104*4bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, 105*4bff34e3Sthurlow "unsupported address family %d"), 0, 106*4bff34e3Sthurlow sap->sa_family); 107*4bff34e3Sthurlow return (EINVAL); 108*4bff34e3Sthurlow } 109*4bff34e3Sthurlow /*LINTED*/ 110*4bff34e3Sthurlow *ina_p = ((struct sockaddr_in *)sap)->sin_addr.s_addr; 111*4bff34e3Sthurlow free(sap); 112*4bff34e3Sthurlow } 113*4bff34e3Sthurlow 114*4bff34e3Sthurlow return (0); 115*4bff34e3Sthurlow } 116*4bff34e3Sthurlow 117*4bff34e3Sthurlow /* 118*4bff34e3Sthurlow * This is called by "smbutil lookup" to handle the 119*4bff34e3Sthurlow * "-w wins_server" option. Let the semantics of 120*4bff34e3Sthurlow * this option be: Use specified WINS server only. 121*4bff34e3Sthurlow * If specified server is the broadcast address, 122*4bff34e3Sthurlow * set broadcast mode (and no WINS servers). 123*4bff34e3Sthurlow */ 124*4bff34e3Sthurlow int 125*4bff34e3Sthurlow nb_ctx_setns(struct nb_ctx *ctx, const char *addr) 126*4bff34e3Sthurlow { 127*4bff34e3Sthurlow int error; 128*4bff34e3Sthurlow 129*4bff34e3Sthurlow error = nb_ctx_setwins(&ctx->nb_wins1, addr); 130*4bff34e3Sthurlow if (error) 131*4bff34e3Sthurlow return (error); 132*4bff34e3Sthurlow ctx->nb_wins2 = 0; 133*4bff34e3Sthurlow 134*4bff34e3Sthurlow /* Deal with explicit request for broadcast. */ 135*4bff34e3Sthurlow if (ctx->nb_wins1 == INADDR_BROADCAST) { 136*4bff34e3Sthurlow ctx->nb_wins1 = 0; 137*4bff34e3Sthurlow ctx->nb_flags |= NBCF_BC_ENABLE; 138*4bff34e3Sthurlow } 139*4bff34e3Sthurlow return (0); 140*4bff34e3Sthurlow } 141*4bff34e3Sthurlow 142*4bff34e3Sthurlow int 143*4bff34e3Sthurlow nb_ctx_setscope(struct nb_ctx *ctx, const char *scope) 144*4bff34e3Sthurlow { 145*4bff34e3Sthurlow size_t slen = strlen(scope); 146*4bff34e3Sthurlow 147*4bff34e3Sthurlow if (slen >= 128) { 148*4bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, 149*4bff34e3Sthurlow "scope '%s' is too long"), 0, scope); 150*4bff34e3Sthurlow return (ENAMETOOLONG); 151*4bff34e3Sthurlow } 152*4bff34e3Sthurlow if (ctx->nb_scope) 153*4bff34e3Sthurlow free(ctx->nb_scope); 154*4bff34e3Sthurlow ctx->nb_scope = malloc(slen + 1); 155*4bff34e3Sthurlow if (ctx->nb_scope == NULL) 156*4bff34e3Sthurlow return (ENOMEM); 157*4bff34e3Sthurlow nls_str_upper(ctx->nb_scope, scope); 158*4bff34e3Sthurlow return (0); 159*4bff34e3Sthurlow } 160*4bff34e3Sthurlow 161*4bff34e3Sthurlow /* 162*4bff34e3Sthurlow * Now get the WINS server IP addresses directly 163*4bff34e3Sthurlow * when reading the RC files, so no longer need to 164*4bff34e3Sthurlow * lookup any names here. 165*4bff34e3Sthurlow */ 166*4bff34e3Sthurlow int 167*4bff34e3Sthurlow nb_ctx_resolve(struct nb_ctx *ctx) 168*4bff34e3Sthurlow { 169*4bff34e3Sthurlow ctx->nb_flags |= NBCF_RESOLVED; 170*4bff34e3Sthurlow return (0); 171*4bff34e3Sthurlow } 172*4bff34e3Sthurlow 173*4bff34e3Sthurlow /* 174*4bff34e3Sthurlow * used level values: 175*4bff34e3Sthurlow * 0 - default 176*4bff34e3Sthurlow * 1 - server 177*4bff34e3Sthurlow * 178*4bff34e3Sthurlow * All of these are normally system-wide settings; 179*4bff34e3Sthurlow * the checks are in rc_parse() in rcfile.c. 180*4bff34e3Sthurlow */ 181*4bff34e3Sthurlow int 182*4bff34e3Sthurlow nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx, 183*4bff34e3Sthurlow const char *sname, int level) 184*4bff34e3Sthurlow { 185*4bff34e3Sthurlow char *p; 186*4bff34e3Sthurlow int error; 187*4bff34e3Sthurlow int nbns_enable; 188*4bff34e3Sthurlow int nbns_broadcast; 189*4bff34e3Sthurlow 190*4bff34e3Sthurlow if (level > 1) 191*4bff34e3Sthurlow return (EINVAL); 192*4bff34e3Sthurlow #ifdef NOT_DEFINED 193*4bff34e3Sthurlow rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo); 194*4bff34e3Sthurlow rc_getstringptr(rcfile, sname, "nbscope", &p); 195*4bff34e3Sthurlow if (p) 196*4bff34e3Sthurlow nb_ctx_setscope(ctx, p); 197*4bff34e3Sthurlow #endif 198*4bff34e3Sthurlow /* "nbns" will be "wins1" some day, and we'll have a "wins2" also */ 199*4bff34e3Sthurlow rc_getstringptr(rcfile, sname, "nbns", &p); 200*4bff34e3Sthurlow if (p) { 201*4bff34e3Sthurlow error = nb_ctx_setwins(&ctx->nb_wins1, p); 202*4bff34e3Sthurlow if (error) { 203*4bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, 204*4bff34e3Sthurlow "invalid address specified in the section %s"), 205*4bff34e3Sthurlow 0, sname); 206*4bff34e3Sthurlow return (error); 207*4bff34e3Sthurlow } 208*4bff34e3Sthurlow } 209*4bff34e3Sthurlow error = rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable); 210*4bff34e3Sthurlow if (error == 0 && nbns_enable == 0) 211*4bff34e3Sthurlow ctx->nb_flags &= ~NBCF_NS_ENABLE; 212*4bff34e3Sthurlow error = rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast); 213*4bff34e3Sthurlow if (error == 0 && nbns_broadcast == 0) 214*4bff34e3Sthurlow ctx->nb_flags &= ~NBCF_BC_ENABLE; 215*4bff34e3Sthurlow return (0); 216*4bff34e3Sthurlow } 217*4bff34e3Sthurlow 218*4bff34e3Sthurlow #ifdef I18N /* never defined, permits xgettext(1) to pick out strings */ 219*4bff34e3Sthurlow static const char *nb_err_rcode[] = { 220*4bff34e3Sthurlow gettext("bad request/response format"), 221*4bff34e3Sthurlow gettext("NBNS server failure"), 222*4bff34e3Sthurlow gettext("no such name"), 223*4bff34e3Sthurlow gettext("unsupported request"), 224*4bff34e3Sthurlow gettext("request rejected"), 225*4bff34e3Sthurlow gettext("name already registered)" 226*4bff34e3Sthurlow }; 227*4bff34e3Sthurlow 228*4bff34e3Sthurlow static const char *nb_err[] = { 229*4bff34e3Sthurlow gettext("host not found"), 230*4bff34e3Sthurlow gettext("too many redirects"), 231*4bff34e3Sthurlow gettext("invalid response"), 232*4bff34e3Sthurlow gettext("NETBIOS name too long"), 233*4bff34e3Sthurlow gettext("no interface to broadcast on and no NBNS server specified") 234*4bff34e3Sthurlow }; 235*4bff34e3Sthurlow #else 236*4bff34e3Sthurlow static const char *nb_err_rcode[] = { 237*4bff34e3Sthurlow "bad request/response format", 238*4bff34e3Sthurlow "NBNS server failure", 239*4bff34e3Sthurlow "no such name", 240*4bff34e3Sthurlow "unsupported request", 241*4bff34e3Sthurlow "request rejected", 242*4bff34e3Sthurlow "name already registered" 243*4bff34e3Sthurlow }; 244*4bff34e3Sthurlow 245*4bff34e3Sthurlow static const char *nb_err[] = { 246*4bff34e3Sthurlow "host not found", 247*4bff34e3Sthurlow "too many redirects", 248*4bff34e3Sthurlow "invalid response", 249*4bff34e3Sthurlow "NETBIOS name too long", 250*4bff34e3Sthurlow "no interface to broadcast on and no NBNS server specified" 251*4bff34e3Sthurlow }; 252*4bff34e3Sthurlow #endif 253*4bff34e3Sthurlow 254*4bff34e3Sthurlow const char * 255*4bff34e3Sthurlow nb_strerror(int error) 256*4bff34e3Sthurlow { 257*4bff34e3Sthurlow if (error == 0) 258*4bff34e3Sthurlow return (NULL); 259*4bff34e3Sthurlow if (error <= NBERR_ACTIVE) 260*4bff34e3Sthurlow return (nb_err_rcode[error - 1]); 261*4bff34e3Sthurlow else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX) 262*4bff34e3Sthurlow return (nb_err[error - NBERR_HOSTNOTFOUND]); 263*4bff34e3Sthurlow else 264*4bff34e3Sthurlow return (NULL); 265*4bff34e3Sthurlow } 266