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 2010 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 *ctxpp = ctx; 118 return (0); 119 } 120 121 void 122 nb_ctx_done(struct nb_ctx *ctx) 123 { 124 if (ctx == NULL) 125 return; 126 if (ctx->nb_scope) 127 free(ctx->nb_scope); 128 if (ctx) 129 free(ctx); 130 } 131 132 void 133 nb_ctx_setnbflags(struct nb_ctx *nb, int ns_ena, int bc_ena) 134 { 135 nb->nb_flags &= ~(NBCF_NS_ENABLE | NBCF_BC_ENABLE); 136 if (ns_ena) { 137 nb->nb_flags |= NBCF_NS_ENABLE; 138 if (bc_ena) 139 nb->nb_flags |= NBCF_BC_ENABLE; 140 } 141 } 142 143 int 144 nb_ctx_setwins(struct nb_ctx *ctx, const char *wins1, const char *wins2) 145 { 146 struct in_addr ina; 147 int error; 148 149 if (wins1 == NULL) { 150 ctx->nb_wins1 = 0; 151 ctx->nb_wins2 = 0; 152 return (0); 153 } 154 155 error = nb_resolvehost_in(wins1, &ina); 156 if (error) { 157 smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 158 error, wins1); 159 return (error); 160 } 161 ctx->nb_wins1 = ina.s_addr; 162 163 if (wins2 == NULL) 164 ctx->nb_wins2 = 0; 165 else { 166 error = nb_resolvehost_in(wins2, &ina); 167 if (error) { 168 smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 169 error, wins2); 170 return (error); 171 } 172 ctx->nb_wins2 = ina.s_addr; 173 } 174 return (0); 175 } 176 177 /* 178 * This is called by "smbutil lookup" to handle the 179 * "-w wins_server" option. Let the semantics of 180 * this option be: Use specified WINS server only. 181 * If specified server is the broadcast address, 182 * set broadcast mode (and no WINS servers). 183 */ 184 int 185 nb_ctx_setns(struct nb_ctx *ctx, const char *addr) 186 { 187 int error; 188 189 error = nb_ctx_setwins(ctx, addr, NULL); 190 if (error) 191 return (error); 192 193 /* Deal with explicit request for broadcast. */ 194 if (ctx->nb_wins1 == INADDR_BROADCAST) { 195 ctx->nb_wins1 = 0; 196 ctx->nb_flags |= NBCF_BC_ENABLE; 197 } 198 return (0); 199 } 200 201 int 202 nb_ctx_setscope(struct nb_ctx *ctx, const char *scope) 203 { 204 size_t slen = strlen(scope); 205 206 if (slen >= 128) { 207 smb_error(dgettext(TEXT_DOMAIN, 208 "scope '%s' is too long"), 0, scope); 209 return (ENAMETOOLONG); 210 } 211 if (ctx->nb_scope) 212 free(ctx->nb_scope); 213 ctx->nb_scope = malloc(slen + 1); 214 if (ctx->nb_scope == NULL) 215 return (ENOMEM); 216 nls_str_upper(ctx->nb_scope, scope); 217 return (0); 218 } 219 220 /* 221 * Now get the WINS server IP addresses directly 222 * when reading the RC files, so no longer need to 223 * lookup any names here. 224 */ 225 int 226 nb_ctx_resolve(struct nb_ctx *ctx) 227 { 228 ctx->nb_flags |= NBCF_RESOLVED; 229 return (0); 230 } 231 232 /* 233 * used level values: 234 * 0 - default 235 * 1 - server 236 * 237 * All of these are normally system-wide settings; 238 * the checks are in rc_parse() in rcfile.c. 239 */ 240 int 241 nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx, 242 const char *sname, int level) 243 { 244 char *wins1, *wins2; 245 int error; 246 int nbns_enable; 247 int nbns_broadcast; 248 249 if (level > 1) 250 return (EINVAL); 251 252 /* External callers pass NULL to get the default. */ 253 if (rcfile == NULL) 254 rcfile = smb_rc; 255 256 #ifdef NOT_DEFINED 257 rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo); 258 rc_getstringptr(rcfile, sname, "nbscope", &p); 259 if (p) 260 nb_ctx_setscope(ctx, p); 261 #endif 262 /* 263 * Get "wins1", "wins2" config strings. 264 * Also support legacy "nbns". 265 */ 266 rc_getstringptr(rcfile, sname, "wins1", &wins1); 267 if (wins1 == NULL) 268 rc_getstringptr(rcfile, sname, "nbns", &wins1); 269 rc_getstringptr(rcfile, sname, "wins2", &wins2); 270 271 if (wins1 != NULL) { 272 error = nb_ctx_setwins(ctx, wins1, wins2); 273 if (error) { 274 smb_error(dgettext(TEXT_DOMAIN, 275 "invalid address specified in the section %s"), 276 0, sname); 277 return (error); 278 } 279 } 280 281 /* 282 * Want to use nb_ctx_setnbflags here, but 283 * have to get both boolean values first, 284 * either from settings or defaults. 285 */ 286 nbns_enable = nbns_broadcast = 1; /* defaults */ 287 rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable); 288 rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast); 289 nb_ctx_setnbflags(ctx, nbns_enable, nbns_broadcast); 290 291 return (0); 292 } 293 294 #ifdef I18N /* never defined, permits xgettext(1) to pick out strings */ 295 static const char *nb_err_rcode[] = { 296 gettext("bad request/response format"), 297 gettext("NBNS server failure"), 298 gettext("no such name"), 299 gettext("unsupported request"), 300 gettext("request rejected"), 301 gettext("name already registered)" 302 }; 303 304 static const char *nb_err[] = { 305 gettext("host not found"), 306 gettext("too many redirects"), 307 gettext("invalid response"), 308 gettext("NETBIOS name too long"), 309 gettext("no interface to broadcast on and no NBNS server specified") 310 }; 311 #else 312 static const char *nb_err_rcode[] = { 313 "bad request/response format", 314 "NBNS server failure", 315 "no such name", 316 "unsupported request", 317 "request rejected", 318 "name already registered" 319 }; 320 321 static const char *nb_err[] = { 322 "host not found", 323 "too many redirects", 324 "invalid response", 325 "NETBIOS name too long", 326 "no interface to broadcast on and no NBNS server specified" 327 }; 328 #endif 329 330 const char * 331 nb_strerror(int error) 332 { 333 if (error == 0) 334 return (NULL); 335 if (error <= NBERR_ACTIVE) 336 return (nb_err_rcode[error - 1]); 337 else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX) 338 return (nb_err[error - NBERR_HOSTNOTFOUND]); 339 else 340 return (NULL); 341 } 342