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.3/contrib/smbfs/lib/smb/nb_name.c 294364 2016-01-19 23:36:49Z ian $"); 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 146294364Sianstatic inline void 147294364Siannb_char_encode(u_char **ptr, u_char c, int n) 148294364Sian{ 14987866Ssheldonh 15087866Ssheldonh while (n--) { 151294364Sian *(*ptr)++ = 0x41 + (c >> 4); 152294364Sian *(*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) { 166294364Sian nb_char_encode(&cp, '*', 1); 167294364Sian nb_char_encode(&cp, ' ', NB_NAMELEN - 1); 16887866Ssheldonh } else { 169294364Sian for (i = 0; i < NB_NAMELEN - 1; i++) 170294364Sian if (*name != 0) 171294364Sian nb_char_encode(&cp, toupper(*name++), 1); 172294364Sian else 173294364Sian nb_char_encode(&cp, ' ', 1); 174294364Sian 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