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