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 int nb_ctx_setwins(struct nb_ctx *, const char *, const char *); 61 62 63 /* 64 * API for library consumer to set wins1, wins2 65 */ 66 int 67 smb_ctx_setwins(struct smb_ctx *ctx, const char *wins1, const char *wins2) 68 { 69 struct nb_ctx *nb = ctx->ct_nb; 70 71 if (nb == NULL) 72 return (EINVAL); 73 74 return (nb_ctx_setwins(nb, wins1, wins2)); 75 } 76 77 /* 78 * API for library consumer to set NB scope. 79 */ 80 int 81 smb_ctx_setscope(struct smb_ctx *ctx, const char *scope) 82 { 83 struct nb_ctx *nb = ctx->ct_nb; 84 85 if (nb == NULL) 86 return (EINVAL); 87 88 return (nb_ctx_setscope(nb, scope)); 89 } 90 91 int 92 nb_ctx_create(struct nb_ctx **ctxpp) 93 { 94 struct nb_ctx *ctx; 95 96 ctx = malloc(sizeof (struct nb_ctx)); 97 if (ctx == NULL) 98 return (ENOMEM); 99 bzero(ctx, sizeof (struct nb_ctx)); 100 ctx->nb_flags = NBCF_NS_ENABLE | NBCF_BC_ENABLE; 101 *ctxpp = ctx; 102 return (0); 103 } 104 105 void 106 nb_ctx_done(struct nb_ctx *ctx) 107 { 108 if (ctx == NULL) 109 return; 110 if (ctx->nb_scope) 111 free(ctx->nb_scope); 112 if (ctx) 113 free(ctx); 114 } 115 116 int 117 nb_ctx_setwins(struct nb_ctx *ctx, const char *wins1, const char *wins2) 118 { 119 struct in_addr ina; 120 int error; 121 122 if (wins1 == NULL) { 123 ctx->nb_wins1 = 0; 124 ctx->nb_wins2 = 0; 125 return (0); 126 } 127 128 error = nb_resolvehost_in(wins1, &ina); 129 if (error) { 130 smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 131 error, wins1); 132 return (error); 133 } 134 ctx->nb_wins1 = ina.s_addr; 135 136 if (wins2 == NULL) 137 ctx->nb_wins2 = 0; 138 else { 139 error = nb_resolvehost_in(wins2, &ina); 140 if (error) { 141 smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 142 error, wins2); 143 return (error); 144 } 145 ctx->nb_wins2 = ina.s_addr; 146 } 147 return (0); 148 } 149 150 /* 151 * This is called by "smbutil lookup" to handle the 152 * "-w wins_server" option. Let the semantics of 153 * this option be: Use specified WINS server only. 154 * If specified server is the broadcast address, 155 * set broadcast mode (and no WINS servers). 156 */ 157 int 158 nb_ctx_setns(struct nb_ctx *ctx, const char *addr) 159 { 160 int error; 161 162 error = nb_ctx_setwins(ctx, addr, NULL); 163 if (error) 164 return (error); 165 166 /* Deal with explicit request for broadcast. */ 167 if (ctx->nb_wins1 == INADDR_BROADCAST) { 168 ctx->nb_wins1 = 0; 169 ctx->nb_flags |= NBCF_BC_ENABLE; 170 } 171 return (0); 172 } 173 174 int 175 nb_ctx_setscope(struct nb_ctx *ctx, const char *scope) 176 { 177 size_t slen = strlen(scope); 178 179 if (slen >= 128) { 180 smb_error(dgettext(TEXT_DOMAIN, 181 "scope '%s' is too long"), 0, scope); 182 return (ENAMETOOLONG); 183 } 184 if (ctx->nb_scope) 185 free(ctx->nb_scope); 186 ctx->nb_scope = malloc(slen + 1); 187 if (ctx->nb_scope == NULL) 188 return (ENOMEM); 189 nls_str_upper(ctx->nb_scope, scope); 190 return (0); 191 } 192 193 /* 194 * Now get the WINS server IP addresses directly 195 * when reading the RC files, so no longer need to 196 * lookup any names here. 197 */ 198 int 199 nb_ctx_resolve(struct nb_ctx *ctx) 200 { 201 ctx->nb_flags |= NBCF_RESOLVED; 202 return (0); 203 } 204 205 /* 206 * used level values: 207 * 0 - default 208 * 1 - server 209 * 210 * All of these are normally system-wide settings; 211 * the checks are in rc_parse() in rcfile.c. 212 */ 213 int 214 nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx, 215 const char *sname, int level) 216 { 217 char *wins1, *wins2; 218 int error; 219 int nbns_enable; 220 int nbns_broadcast; 221 222 if (level > 1) 223 return (EINVAL); 224 225 /* External callers pass NULL to get the default. */ 226 if (rcfile == NULL) 227 rcfile = smb_rc; 228 229 #ifdef NOT_DEFINED 230 rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo); 231 rc_getstringptr(rcfile, sname, "nbscope", &p); 232 if (p) 233 nb_ctx_setscope(ctx, p); 234 #endif 235 /* 236 * Get "wins1", "wins2" config strings. 237 * Also support legacy "nbns". 238 */ 239 rc_getstringptr(rcfile, sname, "wins1", &wins1); 240 if (wins1 == NULL) 241 rc_getstringptr(rcfile, sname, "nbns", &wins1); 242 rc_getstringptr(rcfile, sname, "wins2", &wins2); 243 244 if (wins1 != NULL) { 245 error = nb_ctx_setwins(ctx, wins1, wins2); 246 if (error) { 247 smb_error(dgettext(TEXT_DOMAIN, 248 "invalid address specified in the section %s"), 249 0, sname); 250 return (error); 251 } 252 } 253 error = rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable); 254 if (error == 0 && nbns_enable == 0) 255 ctx->nb_flags &= ~NBCF_NS_ENABLE; 256 error = rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast); 257 if (error == 0 && nbns_broadcast == 0) 258 ctx->nb_flags &= ~NBCF_BC_ENABLE; 259 return (0); 260 } 261 262 #ifdef I18N /* never defined, permits xgettext(1) to pick out strings */ 263 static const char *nb_err_rcode[] = { 264 gettext("bad request/response format"), 265 gettext("NBNS server failure"), 266 gettext("no such name"), 267 gettext("unsupported request"), 268 gettext("request rejected"), 269 gettext("name already registered)" 270 }; 271 272 static const char *nb_err[] = { 273 gettext("host not found"), 274 gettext("too many redirects"), 275 gettext("invalid response"), 276 gettext("NETBIOS name too long"), 277 gettext("no interface to broadcast on and no NBNS server specified") 278 }; 279 #else 280 static const char *nb_err_rcode[] = { 281 "bad request/response format", 282 "NBNS server failure", 283 "no such name", 284 "unsupported request", 285 "request rejected", 286 "name already registered" 287 }; 288 289 static const char *nb_err[] = { 290 "host not found", 291 "too many redirects", 292 "invalid response", 293 "NETBIOS name too long", 294 "no interface to broadcast on and no NBNS server specified" 295 }; 296 #endif 297 298 const char * 299 nb_strerror(int error) 300 { 301 if (error == 0) 302 return (NULL); 303 if (error <= NBERR_ACTIVE) 304 return (nb_err_rcode[error - 1]); 305 else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX) 306 return (nb_err[error - NBERR_HOSTNOTFOUND]); 307 else 308 return (NULL); 309 } 310