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