187866Ssheldonh/* 287866Ssheldonh * Copyright (c) 2000, 2001 Boris Popov 387866Ssheldonh * All rights reserved. 487866Ssheldonh * 587866Ssheldonh * Redistribution and use in source and binary forms, with or without 687866Ssheldonh * modification, are permitted provided that the following conditions 787866Ssheldonh * are met: 887866Ssheldonh * 1. Redistributions of source code must retain the above copyright 987866Ssheldonh * notice, this list of conditions and the following disclaimer. 1087866Ssheldonh * 2. Redistributions in binary form must reproduce the above copyright 1187866Ssheldonh * notice, this list of conditions and the following disclaimer in the 1287866Ssheldonh * documentation and/or other materials provided with the distribution. 1387866Ssheldonh * 3. All advertising materials mentioning features or use of this software 1487866Ssheldonh * must display the following acknowledgement: 1587866Ssheldonh * This product includes software developed by Boris Popov. 1687866Ssheldonh * 4. Neither the name of the author nor the names of any co-contributors 1787866Ssheldonh * may be used to endorse or promote products derived from this software 1887866Ssheldonh * without specific prior written permission. 1987866Ssheldonh * 2087866Ssheldonh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2187866Ssheldonh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2287866Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2387866Ssheldonh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2487866Ssheldonh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2587866Ssheldonh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2687866Ssheldonh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2787866Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2887866Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2987866Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3087866Ssheldonh * SUCH DAMAGE. 3187866Ssheldonh * 3287866Ssheldonh * $Id: nb.c,v 1.4 2001/04/16 04:33:01 bp Exp $ 33150802Sbp * $FreeBSD$ 3487866Ssheldonh */ 3587866Ssheldonh#include <sys/param.h> 3687866Ssheldonh#include <sys/socket.h> 3787866Ssheldonh 3887866Ssheldonh#include <ctype.h> 3987866Ssheldonh#include <netdb.h> 4087866Ssheldonh#include <err.h> 4187866Ssheldonh#include <errno.h> 4287866Ssheldonh#include <stdlib.h> 4387866Ssheldonh#include <string.h> 4487866Ssheldonh#include <stdio.h> 4587866Ssheldonh#include <unistd.h> 4687866Ssheldonh#include <cflib.h> 4787866Ssheldonh 4887866Ssheldonh#include <netsmb/netbios.h> 4987866Ssheldonh#include <netsmb/smb_lib.h> 5087866Ssheldonh#include <netsmb/nb_lib.h> 5187866Ssheldonh 5287866Ssheldonhint 5387866Ssheldonhnb_ctx_create(struct nb_ctx **ctxpp) 5487866Ssheldonh{ 5587866Ssheldonh struct nb_ctx *ctx; 5687866Ssheldonh 5787866Ssheldonh ctx = malloc(sizeof(struct nb_ctx)); 5887866Ssheldonh if (ctx == NULL) 5987866Ssheldonh return ENOMEM; 6087866Ssheldonh bzero(ctx, sizeof(struct nb_ctx)); 61150802Sbp ctx->nb_nmbtcpport = NMB_TCP_PORT; 62150802Sbp ctx->nb_smbtcpport = SMB_TCP_PORT; 63150802Sbp 6487866Ssheldonh *ctxpp = ctx; 6587866Ssheldonh return 0; 6687866Ssheldonh} 6787866Ssheldonh 6887866Ssheldonhvoid 6987866Ssheldonhnb_ctx_done(struct nb_ctx *ctx) 7087866Ssheldonh{ 7187866Ssheldonh if (ctx == NULL) 7287866Ssheldonh return; 7387866Ssheldonh if (ctx->nb_scope) 7487866Ssheldonh free(ctx->nb_scope); 7587866Ssheldonh} 7687866Ssheldonh 7787866Ssheldonhint 7887866Ssheldonhnb_ctx_setns(struct nb_ctx *ctx, const char *addr) 7987866Ssheldonh{ 8087866Ssheldonh if (addr == NULL || addr[0] == 0) 8187866Ssheldonh return EINVAL; 8287866Ssheldonh if (ctx->nb_nsname) 8387866Ssheldonh free(ctx->nb_nsname); 8487866Ssheldonh if ((ctx->nb_nsname = strdup(addr)) == NULL) 8587866Ssheldonh return ENOMEM; 8687866Ssheldonh return 0; 8787866Ssheldonh} 8887866Ssheldonh 8987866Ssheldonhint 9087866Ssheldonhnb_ctx_setscope(struct nb_ctx *ctx, const char *scope) 9187866Ssheldonh{ 9287866Ssheldonh size_t slen = strlen(scope); 9387866Ssheldonh 9487866Ssheldonh if (slen >= 128) { 9587866Ssheldonh smb_error("scope '%s' is too long", 0, scope); 9687866Ssheldonh return ENAMETOOLONG; 9787866Ssheldonh } 9887866Ssheldonh if (ctx->nb_scope) 9987866Ssheldonh free(ctx->nb_scope); 10087866Ssheldonh ctx->nb_scope = malloc(slen + 1); 10187866Ssheldonh if (ctx->nb_scope == NULL) 10287866Ssheldonh return ENOMEM; 10387866Ssheldonh nls_str_upper(ctx->nb_scope, scope); 10487866Ssheldonh return 0; 10587866Ssheldonh} 10687866Ssheldonh 10787866Ssheldonhint 10887866Ssheldonhnb_ctx_resolve(struct nb_ctx *ctx) 10987866Ssheldonh{ 11087866Ssheldonh struct sockaddr *sap; 11187866Ssheldonh int error; 11287866Ssheldonh 11387866Ssheldonh ctx->nb_flags &= ~NBCF_RESOLVED; 11487866Ssheldonh 11587866Ssheldonh if (ctx->nb_nsname == NULL) { 11687866Ssheldonh ctx->nb_ns.sin_addr.s_addr = htonl(INADDR_BROADCAST); 11787866Ssheldonh } else { 118150802Sbp error = nb_resolvehost_in(ctx->nb_nsname, &sap, ctx->nb_smbtcpport); 11987866Ssheldonh if (error) { 12087866Ssheldonh smb_error("can't resolve %s", error, ctx->nb_nsname); 12187866Ssheldonh return error; 12287866Ssheldonh } 12387866Ssheldonh if (sap->sa_family != AF_INET) { 12487866Ssheldonh smb_error("unsupported address family %d", 0, sap->sa_family); 12587866Ssheldonh return EINVAL; 12687866Ssheldonh } 12787866Ssheldonh bcopy(sap, &ctx->nb_ns, sizeof(ctx->nb_ns)); 12887866Ssheldonh free(sap); 12987866Ssheldonh } 130150802Sbp ctx->nb_ns.sin_port = htons(ctx->nb_nmbtcpport); 13187866Ssheldonh ctx->nb_ns.sin_family = AF_INET; 13287866Ssheldonh ctx->nb_ns.sin_len = sizeof(ctx->nb_ns); 13387866Ssheldonh ctx->nb_flags |= NBCF_RESOLVED; 13487866Ssheldonh return 0; 13587866Ssheldonh} 13687866Ssheldonh 13787866Ssheldonh/* 13887866Ssheldonh * used level values: 13987866Ssheldonh * 0 - default 14087866Ssheldonh * 1 - server 14187866Ssheldonh */ 14287866Ssheldonhint 14387866Ssheldonhnb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx, 14487866Ssheldonh const char *sname, int level) 14587866Ssheldonh{ 14687866Ssheldonh char *p; 14787866Ssheldonh int error; 14887866Ssheldonh 14987866Ssheldonh if (level > 1) 15087866Ssheldonh return EINVAL; 15187866Ssheldonh rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo); 15287866Ssheldonh rc_getstringptr(rcfile, sname, "nbns", &p); 15387866Ssheldonh if (p) { 15487866Ssheldonh error = nb_ctx_setns(ctx, p); 15587866Ssheldonh if (error) { 15687866Ssheldonh smb_error("invalid address specified in the section %s", 0, sname); 15787866Ssheldonh return error; 15887866Ssheldonh } 15987866Ssheldonh } 16087866Ssheldonh rc_getstringptr(rcfile, sname, "nbscope", &p); 16187866Ssheldonh if (p) 16287866Ssheldonh nb_ctx_setscope(ctx, p); 16387866Ssheldonh return 0; 16487866Ssheldonh} 16587866Ssheldonh 16687866Ssheldonhstatic const char *nb_err_rcode[] = { 16787866Ssheldonh "bad request/response format", 16887866Ssheldonh "NBNS server failure", 16987866Ssheldonh "no such name", 17087866Ssheldonh "unsupported request", 17187866Ssheldonh "request rejected", 17287866Ssheldonh "name already registered" 17387866Ssheldonh}; 17487866Ssheldonh 17587866Ssheldonhstatic const char *nb_err[] = { 17687866Ssheldonh "host not found", 17787866Ssheldonh "too many redirects", 17887866Ssheldonh "invalid response", 17987866Ssheldonh "NETBIOS name too long", 18087866Ssheldonh "no interface to broadcast on and no NBNS server specified" 18187866Ssheldonh}; 18287866Ssheldonh 18387866Ssheldonhconst char * 18487866Ssheldonhnb_strerror(int error) 18587866Ssheldonh{ 18687866Ssheldonh if (error == 0) 18787866Ssheldonh return NULL; 18887866Ssheldonh if (error <= NBERR_ACTIVE) 18987866Ssheldonh return nb_err_rcode[error - 1]; 19087866Ssheldonh else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX) 19187866Ssheldonh return nb_err[error - NBERR_HOSTNOTFOUND]; 19287866Ssheldonh else 19387866Ssheldonh return NULL; 19487866Ssheldonh} 19587866Ssheldonh 196