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: releng/10.2/contrib/smbfs/lib/smb/nb_name.c 184567 2008-11-02 19:48:15Z rwatson $"); 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