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
146292552Sianstatic inline void
147292552Siannb_char_encode(u_char **ptr, u_char c, int n)
148292552Sian{
14987866Ssheldonh
15087866Ssheldonh	while (n--) {
151292552Sian		*(*ptr)++ = 0x41 + (c >> 4);
152292552Sian		*(*ptr)++ = 0x41 + (c & 0x0f);
15387866Ssheldonh	}
15487866Ssheldonh}
15587866Ssheldonh
15687866Ssheldonhint
15787866Ssheldonhnb_name_encode(struct nb_name *np, u_char *dst)
15887866Ssheldonh{
15987866Ssheldonh	u_char *name, *plen;
16087866Ssheldonh	u_char *cp = dst;
16187866Ssheldonh	int i, lblen;
16287866Ssheldonh
16387866Ssheldonh	*cp++ = NB_ENCNAMELEN;
16487866Ssheldonh	name = np->nn_name;
16587866Ssheldonh	if (name[0] == '*' && name[1] == 0) {
166292552Sian		nb_char_encode(&cp, '*', 1);
167292552Sian		nb_char_encode(&cp, ' ', NB_NAMELEN - 1);
16887866Ssheldonh	} else {
169292552Sian		for (i = 0; i < NB_NAMELEN - 1; i++)
170292552Sian			if (*name != 0)
171292552Sian				nb_char_encode(&cp, toupper(*name++), 1);
172292552Sian			else
173292552Sian				nb_char_encode(&cp, ' ', 1);
174292552Sian		nb_char_encode(&cp, np->nn_type, 1);
17587866Ssheldonh	}
17687866Ssheldonh	*cp = 0;
17787866Ssheldonh	if (np->nn_scope == NULL)
17887866Ssheldonh		return nb_encname_len(dst);
17987866Ssheldonh	plen = cp++;
18087866Ssheldonh	lblen = 0;
18187866Ssheldonh	for (name = np->nn_scope; ; name++) {
18287866Ssheldonh		if (*name == '.' || *name == 0) {
18387866Ssheldonh			*plen = lblen;
18487866Ssheldonh			plen = cp++;
18587866Ssheldonh			*plen = 0;
18687866Ssheldonh			if (*name == 0)
18787866Ssheldonh				break;
18887866Ssheldonh		} else {
18987866Ssheldonh			if (lblen < NB_MAXLABLEN) {
19087866Ssheldonh				*cp++ = *name;
19187866Ssheldonh				lblen++;
19287866Ssheldonh			}
19387866Ssheldonh		}
19487866Ssheldonh	}
19587866Ssheldonh	return nb_encname_len(dst);
19687866Ssheldonh}
19787866Ssheldonh
198