187866Ssheldonh/*
288282Ssheldonh * 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 *
3288282Ssheldonh * $Id: nb_name.c,v 1.2 2001/08/22 03:31:36 bp Exp $
3387866Ssheldonh */
34150312Simura
35150312Simura#include <sys/cdefs.h>
36150312Simura__FBSDID("$FreeBSD$");
37150312Simura
3887866Ssheldonh#include <sys/param.h>
39150312Simura#include <sys/endian.h>
4087866Ssheldonh#include <sys/socket.h>
4187866Ssheldonh
4287866Ssheldonh#include <ctype.h>
4387866Ssheldonh#include <err.h>
4487866Ssheldonh#include <errno.h>
4587866Ssheldonh#include <stdio.h>
4687866Ssheldonh#include <stdlib.h>
4787866Ssheldonh#include <string.h>
4887866Ssheldonh
4987866Ssheldonh#include <netsmb/netbios.h>
5087866Ssheldonh#include <netsmb/smb_lib.h>
5187866Ssheldonh#include <netsmb/nb_lib.h>
5287866Ssheldonh
5387866Ssheldonhint
5487866Ssheldonhnb_snballoc(int namelen, struct sockaddr_nb **dst)
5587866Ssheldonh{
5687866Ssheldonh	struct sockaddr_nb *snb;
5787866Ssheldonh	int slen;
5887866Ssheldonh
5987866Ssheldonh	slen = namelen + sizeof(*snb) - sizeof(snb->snb_name);
6087866Ssheldonh	snb = malloc(slen);
6187866Ssheldonh	if (snb == NULL)
6287866Ssheldonh		return ENOMEM;
6387866Ssheldonh	bzero(snb, slen);
6487866Ssheldonh	snb->snb_family = AF_NETBIOS;
6587866Ssheldonh	snb->snb_len = slen;
6687866Ssheldonh	*dst = snb;
6787866Ssheldonh	return 0;
6887866Ssheldonh}
6987866Ssheldonh
7087866Ssheldonhvoid
7187866Ssheldonhnb_snbfree(struct sockaddr *snb)
7287866Ssheldonh{
7387866Ssheldonh	free(snb);
7487866Ssheldonh}
7587866Ssheldonh
7687866Ssheldonh/*
7787866Ssheldonh * Create a full NETBIOS address
7887866Ssheldonh */
7987866Ssheldonhint
8087866Ssheldonhnb_sockaddr(struct sockaddr *peer, struct nb_name *np,
8187866Ssheldonh	struct sockaddr_nb **dst)
8287866Ssheldonh
8387866Ssheldonh{
8487866Ssheldonh	struct sockaddr_nb *snb;
8587866Ssheldonh	int nmlen, error;
8687866Ssheldonh
8787866Ssheldonh	if (peer && (peer->sa_family != AF_INET && peer->sa_family != AF_IPX))
8887866Ssheldonh		return EPROTONOSUPPORT;
8987866Ssheldonh	nmlen = nb_name_len(np);
9087866Ssheldonh	if (nmlen < NB_ENCNAMELEN)
9187866Ssheldonh		return EINVAL;
9287866Ssheldonh	error = nb_snballoc(nmlen, &snb);
9387866Ssheldonh	if (error)
9487866Ssheldonh		return error;
9587866Ssheldonh	if (nmlen != nb_name_encode(np, snb->snb_name))
9687866Ssheldonh		printf("a bug somewhere in the nb_name* code\n");
9787866Ssheldonh	if (peer)
9887866Ssheldonh		memcpy(&snb->snb_tran, peer, peer->sa_len);
9987866Ssheldonh	*dst = snb;
10087866Ssheldonh	return 0;
10187866Ssheldonh}
10287866Ssheldonh
10387866Ssheldonhint
10487866Ssheldonhnb_name_len(struct nb_name *np)
10587866Ssheldonh{
10687866Ssheldonh	u_char *name;
10787866Ssheldonh	int len, sclen;
10887866Ssheldonh
10987866Ssheldonh	len = 1 + NB_ENCNAMELEN;
11087866Ssheldonh	if (np->nn_scope == NULL)
11187866Ssheldonh		return len + 1;
11287866Ssheldonh	sclen = 0;
11387866Ssheldonh	for (name = np->nn_scope; *name; name++) {
11487866Ssheldonh		if (*name == '.') {
11587866Ssheldonh			sclen = 0;
11687866Ssheldonh		} else {
11787866Ssheldonh			if (sclen < NB_MAXLABLEN) {
11887866Ssheldonh				sclen++;
11987866Ssheldonh				len++;
12087866Ssheldonh			}
12187866Ssheldonh		}
12287866Ssheldonh	}
12387866Ssheldonh	return len + 1;
12487866Ssheldonh}
12587866Ssheldonh
12687866Ssheldonhint
12787866Ssheldonhnb_encname_len(const char *str)
12887866Ssheldonh{
12987866Ssheldonh	const u_char *cp = (const u_char *)str;
13087866Ssheldonh	int len, blen;
13187866Ssheldonh
13287866Ssheldonh	if ((cp[0] & 0xc0) == 0xc0)
13387866Ssheldonh		return -1;	/* first two bytes are offset to name */
13487866Ssheldonh
13587866Ssheldonh	len = 1;
13687866Ssheldonh	for (;;) {
13787866Ssheldonh		blen = *cp;
13887866Ssheldonh		if (blen++ == 0)
13987866Ssheldonh			break;
14087866Ssheldonh		len += blen;
14187866Ssheldonh		cp += blen;
14287866Ssheldonh	}
14387866Ssheldonh	return len;
14487866Ssheldonh}
14587866Ssheldonh
146150312Simura#define	NBENCODE(c)	(htole16((u_short)(((u_char)(c) >> 4) | \
14788282Ssheldonh			 (((u_char)(c) & 0xf) << 8)) + 0x4141))
14887866Ssheldonh
14987866Ssheldonhstatic void
15087866Ssheldonhmemsetw(char *dst, int n, u_short word)
15187866Ssheldonh{
15287866Ssheldonh	while (n--) {
15387866Ssheldonh		*(u_short*)dst = word;
15487866Ssheldonh		dst += 2;
15587866Ssheldonh	}
15687866Ssheldonh}
15787866Ssheldonh
15887866Ssheldonhint
15987866Ssheldonhnb_name_encode(struct nb_name *np, u_char *dst)
16087866Ssheldonh{
16187866Ssheldonh	u_char *name, *plen;
16287866Ssheldonh	u_char *cp = dst;
16387866Ssheldonh	int i, lblen;
16487866Ssheldonh
16587866Ssheldonh	*cp++ = NB_ENCNAMELEN;
16687866Ssheldonh	name = np->nn_name;
16787866Ssheldonh	if (name[0] == '*' && name[1] == 0) {
16887866Ssheldonh		*(u_short*)cp = NBENCODE('*');
16987866Ssheldonh		memsetw(cp + 2, NB_NAMELEN - 1, NBENCODE(' '));
17087866Ssheldonh		cp += NB_ENCNAMELEN;
17187866Ssheldonh	} else {
172184567Srwatson		for (i = 0; *name && i < NB_NAMELEN - 1; i++, cp += 2, name++)
17387866Ssheldonh			*(u_short*)cp = NBENCODE(toupper(*name));
17487866Ssheldonh		i = NB_NAMELEN - i - 1;
17587866Ssheldonh		if (i > 0) {
17687866Ssheldonh			memsetw(cp, i, NBENCODE(' '));
17787866Ssheldonh			cp += i * 2;
17887866Ssheldonh		}
17987866Ssheldonh		*(u_short*)cp = NBENCODE(np->nn_type);
18087866Ssheldonh		cp += 2;
18187866Ssheldonh	}
18287866Ssheldonh	*cp = 0;
18387866Ssheldonh	if (np->nn_scope == NULL)
18487866Ssheldonh		return nb_encname_len(dst);
18587866Ssheldonh	plen = cp++;
18687866Ssheldonh	lblen = 0;
18787866Ssheldonh	for (name = np->nn_scope; ; name++) {
18887866Ssheldonh		if (*name == '.' || *name == 0) {
18987866Ssheldonh			*plen = lblen;
19087866Ssheldonh			plen = cp++;
19187866Ssheldonh			*plen = 0;
19287866Ssheldonh			if (*name == 0)
19387866Ssheldonh				break;
19487866Ssheldonh		} else {
19587866Ssheldonh			if (lblen < NB_MAXLABLEN) {
19687866Ssheldonh				*cp++ = *name;
19787866Ssheldonh				lblen++;
19887866Ssheldonh			}
19987866Ssheldonh		}
20087866Ssheldonh	}
20187866Ssheldonh	return nb_encname_len(dst);
20287866Ssheldonh}
20387866Ssheldonh
204