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