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