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 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 #include <sys/param.h> 38 #include <sys/socket.h> 39 40 #include <ctype.h> 41 #include <netdb.h> 42 #include <errno.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <strings.h> 46 #include <stdio.h> 47 #include <unistd.h> 48 #include <libintl.h> 49 50 #include <netinet/in.h> 51 #include <arpa/inet.h> 52 53 #include <netsmb/netbios.h> 54 #include <netsmb/smb_lib.h> 55 #include <netsmb/nb_lib.h> 56 57 #include <cflib.h> 58 59 int 60 nb_ctx_create(struct nb_ctx **ctxpp) 61 { 62 struct nb_ctx *ctx; 63 64 ctx = malloc(sizeof (struct nb_ctx)); 65 if (ctx == NULL) 66 return (ENOMEM); 67 bzero(ctx, sizeof (struct nb_ctx)); 68 ctx->nb_flags = NBCF_NS_ENABLE | NBCF_BC_ENABLE; 69 *ctxpp = ctx; 70 return (0); 71 } 72 73 void 74 nb_ctx_done(struct nb_ctx *ctx) 75 { 76 if (ctx == NULL) 77 return; 78 if (ctx->nb_scope) 79 free(ctx->nb_scope); 80 if (ctx) 81 free(ctx); 82 } 83 84 static int 85 nb_ctx_setwins(in_addr_t *ina_p, const char *str) 86 { 87 struct in_addr ina; 88 struct sockaddr *sap; 89 int error; 90 91 if (str == NULL || str[0] == 0) 92 return (EINVAL); 93 94 if (inet_aton(str, &ina)) { 95 *ina_p = ina.s_addr; 96 } else { 97 error = nb_resolvehost_in(str, &sap); 98 if (error) { 99 smb_error(dgettext(TEXT_DOMAIN, "can't resolve %s"), 100 error, str); 101 return (error); 102 } 103 if (sap->sa_family != AF_INET) { 104 smb_error(dgettext(TEXT_DOMAIN, 105 "unsupported address family %d"), 0, 106 sap->sa_family); 107 return (EINVAL); 108 } 109 /*LINTED*/ 110 *ina_p = ((struct sockaddr_in *)sap)->sin_addr.s_addr; 111 free(sap); 112 } 113 114 return (0); 115 } 116 117 /* 118 * This is called by "smbutil lookup" to handle the 119 * "-w wins_server" option. Let the semantics of 120 * this option be: Use specified WINS server only. 121 * If specified server is the broadcast address, 122 * set broadcast mode (and no WINS servers). 123 */ 124 int 125 nb_ctx_setns(struct nb_ctx *ctx, const char *addr) 126 { 127 int error; 128 129 error = nb_ctx_setwins(&ctx->nb_wins1, addr); 130 if (error) 131 return (error); 132 ctx->nb_wins2 = 0; 133 134 /* Deal with explicit request for broadcast. */ 135 if (ctx->nb_wins1 == INADDR_BROADCAST) { 136 ctx->nb_wins1 = 0; 137 ctx->nb_flags |= NBCF_BC_ENABLE; 138 } 139 return (0); 140 } 141 142 int 143 nb_ctx_setscope(struct nb_ctx *ctx, const char *scope) 144 { 145 size_t slen = strlen(scope); 146 147 if (slen >= 128) { 148 smb_error(dgettext(TEXT_DOMAIN, 149 "scope '%s' is too long"), 0, scope); 150 return (ENAMETOOLONG); 151 } 152 if (ctx->nb_scope) 153 free(ctx->nb_scope); 154 ctx->nb_scope = malloc(slen + 1); 155 if (ctx->nb_scope == NULL) 156 return (ENOMEM); 157 nls_str_upper(ctx->nb_scope, scope); 158 return (0); 159 } 160 161 /* 162 * Now get the WINS server IP addresses directly 163 * when reading the RC files, so no longer need to 164 * lookup any names here. 165 */ 166 int 167 nb_ctx_resolve(struct nb_ctx *ctx) 168 { 169 ctx->nb_flags |= NBCF_RESOLVED; 170 return (0); 171 } 172 173 /* 174 * used level values: 175 * 0 - default 176 * 1 - server 177 * 178 * All of these are normally system-wide settings; 179 * the checks are in rc_parse() in rcfile.c. 180 */ 181 int 182 nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx, 183 const char *sname, int level) 184 { 185 char *p; 186 int error; 187 int nbns_enable; 188 int nbns_broadcast; 189 190 if (level > 1) 191 return (EINVAL); 192 #ifdef NOT_DEFINED 193 rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo); 194 rc_getstringptr(rcfile, sname, "nbscope", &p); 195 if (p) 196 nb_ctx_setscope(ctx, p); 197 #endif 198 /* "nbns" will be "wins1" some day, and we'll have a "wins2" also */ 199 rc_getstringptr(rcfile, sname, "nbns", &p); 200 if (p) { 201 error = nb_ctx_setwins(&ctx->nb_wins1, p); 202 if (error) { 203 smb_error(dgettext(TEXT_DOMAIN, 204 "invalid address specified in the section %s"), 205 0, sname); 206 return (error); 207 } 208 } 209 error = rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable); 210 if (error == 0 && nbns_enable == 0) 211 ctx->nb_flags &= ~NBCF_NS_ENABLE; 212 error = rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast); 213 if (error == 0 && nbns_broadcast == 0) 214 ctx->nb_flags &= ~NBCF_BC_ENABLE; 215 return (0); 216 } 217 218 #ifdef I18N /* never defined, permits xgettext(1) to pick out strings */ 219 static const char *nb_err_rcode[] = { 220 gettext("bad request/response format"), 221 gettext("NBNS server failure"), 222 gettext("no such name"), 223 gettext("unsupported request"), 224 gettext("request rejected"), 225 gettext("name already registered)" 226 }; 227 228 static const char *nb_err[] = { 229 gettext("host not found"), 230 gettext("too many redirects"), 231 gettext("invalid response"), 232 gettext("NETBIOS name too long"), 233 gettext("no interface to broadcast on and no NBNS server specified") 234 }; 235 #else 236 static const char *nb_err_rcode[] = { 237 "bad request/response format", 238 "NBNS server failure", 239 "no such name", 240 "unsupported request", 241 "request rejected", 242 "name already registered" 243 }; 244 245 static const char *nb_err[] = { 246 "host not found", 247 "too many redirects", 248 "invalid response", 249 "NETBIOS name too long", 250 "no interface to broadcast on and no NBNS server specified" 251 }; 252 #endif 253 254 const char * 255 nb_strerror(int error) 256 { 257 if (error == 0) 258 return (NULL); 259 if (error <= NBERR_ACTIVE) 260 return (nb_err_rcode[error - 1]); 261 else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX) 262 return (nb_err[error - NBERR_HOSTNOTFOUND]); 263 else 264 return (NULL); 265 } 266