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