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.4 2001/04/16 04:33:01 bp Exp $ 33 * $FreeBSD$ 34 */ 35 #include <sys/param.h> 36 #include <sys/socket.h> 37 38 #include <ctype.h> 39 #include <netdb.h> 40 #include <err.h> 41 #include <errno.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <stdio.h> 45 #include <unistd.h> 46 #include <cflib.h> 47 48 #include <netsmb/netbios.h> 49 #include <netsmb/smb_lib.h> 50 #include <netsmb/nb_lib.h> 51 52 int 53 nb_ctx_create(struct nb_ctx **ctxpp) 54 { 55 struct nb_ctx *ctx; 56 57 ctx = malloc(sizeof(struct nb_ctx)); 58 if (ctx == NULL) 59 return ENOMEM; 60 bzero(ctx, sizeof(struct nb_ctx)); 61 ctx->nb_nmbtcpport = NMB_TCP_PORT; 62 ctx->nb_smbtcpport = SMB_TCP_PORT; 63 64 *ctxpp = ctx; 65 return 0; 66 } 67 68 void 69 nb_ctx_done(struct nb_ctx *ctx) 70 { 71 if (ctx == NULL) 72 return; 73 if (ctx->nb_scope) 74 free(ctx->nb_scope); 75 } 76 77 int 78 nb_ctx_setns(struct nb_ctx *ctx, const char *addr) 79 { 80 if (addr == NULL || addr[0] == 0) 81 return EINVAL; 82 if (ctx->nb_nsname) 83 free(ctx->nb_nsname); 84 if ((ctx->nb_nsname = strdup(addr)) == NULL) 85 return ENOMEM; 86 return 0; 87 } 88 89 int 90 nb_ctx_setscope(struct nb_ctx *ctx, const char *scope) 91 { 92 size_t slen = strlen(scope); 93 94 if (slen >= 128) { 95 smb_error("scope '%s' is too long", 0, scope); 96 return ENAMETOOLONG; 97 } 98 if (ctx->nb_scope) 99 free(ctx->nb_scope); 100 ctx->nb_scope = malloc(slen + 1); 101 if (ctx->nb_scope == NULL) 102 return ENOMEM; 103 nls_str_upper(ctx->nb_scope, scope); 104 return 0; 105 } 106 107 int 108 nb_ctx_resolve(struct nb_ctx *ctx) 109 { 110 struct sockaddr *sap; 111 int error; 112 113 ctx->nb_flags &= ~NBCF_RESOLVED; 114 115 if (ctx->nb_nsname == NULL) { 116 ctx->nb_ns.sin_addr.s_addr = htonl(INADDR_BROADCAST); 117 } else { 118 error = nb_resolvehost_in(ctx->nb_nsname, &sap, ctx->nb_smbtcpport); 119 if (error) { 120 smb_error("can't resolve %s", error, ctx->nb_nsname); 121 return error; 122 } 123 if (sap->sa_family != AF_INET) { 124 smb_error("unsupported address family %d", 0, sap->sa_family); 125 return EINVAL; 126 } 127 bcopy(sap, &ctx->nb_ns, sizeof(ctx->nb_ns)); 128 free(sap); 129 } 130 ctx->nb_ns.sin_port = htons(ctx->nb_nmbtcpport); 131 ctx->nb_ns.sin_family = AF_INET; 132 ctx->nb_ns.sin_len = sizeof(ctx->nb_ns); 133 ctx->nb_flags |= NBCF_RESOLVED; 134 return 0; 135 } 136 137 /* 138 * used level values: 139 * 0 - default 140 * 1 - server 141 */ 142 int 143 nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx, 144 const char *sname, int level) 145 { 146 char *p; 147 int error; 148 149 if (level > 1) 150 return EINVAL; 151 rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo); 152 rc_getstringptr(rcfile, sname, "nbns", &p); 153 if (p) { 154 error = nb_ctx_setns(ctx, p); 155 if (error) { 156 smb_error("invalid address specified in the section %s", 0, sname); 157 return error; 158 } 159 } 160 rc_getstringptr(rcfile, sname, "nbscope", &p); 161 if (p) 162 nb_ctx_setscope(ctx, p); 163 return 0; 164 } 165 166 static const char *nb_err_rcode[] = { 167 "bad request/response format", 168 "NBNS server failure", 169 "no such name", 170 "unsupported request", 171 "request rejected", 172 "name already registered" 173 }; 174 175 static const char *nb_err[] = { 176 "host not found", 177 "too many redirects", 178 "invalid response", 179 "NETBIOS name too long", 180 "no interface to broadcast on and no NBNS server specified" 181 }; 182 183 const char * 184 nb_strerror(int error) 185 { 186 if (error == 0) 187 return NULL; 188 if (error <= NBERR_ACTIVE) 189 return nb_err_rcode[error - 1]; 190 else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX) 191 return nb_err[error - NBERR_HOSTNOTFOUND]; 192 else 193 return NULL; 194 } 195 196