16007Sthurlow /* 26007Sthurlow * Copyright (c) 2000, Boris Popov 36007Sthurlow * All rights reserved. 46007Sthurlow * 56007Sthurlow * Redistribution and use in source and binary forms, with or without 66007Sthurlow * modification, are permitted provided that the following conditions 76007Sthurlow * are met: 86007Sthurlow * 1. Redistributions of source code must retain the above copyright 96007Sthurlow * notice, this list of conditions and the following disclaimer. 106007Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 116007Sthurlow * notice, this list of conditions and the following disclaimer in the 126007Sthurlow * documentation and/or other materials provided with the distribution. 136007Sthurlow * 3. All advertising materials mentioning features or use of this software 146007Sthurlow * must display the following acknowledgement: 156007Sthurlow * This product includes software developed by Boris Popov. 166007Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 176007Sthurlow * may be used to endorse or promote products derived from this software 186007Sthurlow * without specific prior written permission. 196007Sthurlow * 206007Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 216007Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 226007Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 236007Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 246007Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 256007Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 266007Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 276007Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 286007Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 296007Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 306007Sthurlow * SUCH DAMAGE. 316007Sthurlow * 326007Sthurlow * $Id: nb_name.c,v 1.11 2004/12/11 05:23:59 lindak Exp $ 336007Sthurlow */ 346007Sthurlow 356007Sthurlow #include <sys/param.h> 366007Sthurlow #include <sys/socket.h> 376007Sthurlow #include <ctype.h> 386007Sthurlow #include <errno.h> 396007Sthurlow #include <stdio.h> 406007Sthurlow #include <stdlib.h> 416007Sthurlow #include <string.h> 426007Sthurlow #include <strings.h> 436007Sthurlow #include <libintl.h> 446007Sthurlow #include <assert.h> 456007Sthurlow 466007Sthurlow #include <netsmb/netbios.h> 476007Sthurlow #include <netsmb/smb_lib.h> 486007Sthurlow #include <netsmb/nb_lib.h> 496007Sthurlow #include <netsmb/mchain.h> 50*8271SGordon.Ross@Sun.COM #include "private.h" 516007Sthurlow 526007Sthurlow int 536007Sthurlow nb_snballoc(int namelen, struct sockaddr_nb **dst) 546007Sthurlow { 556007Sthurlow struct sockaddr_nb *snb; 566007Sthurlow int slen; 576007Sthurlow 586007Sthurlow slen = sizeof (struct sockaddr_nb); 596007Sthurlow snb = malloc(slen); 606007Sthurlow if (snb == NULL) 616007Sthurlow return (ENOMEM); 626007Sthurlow bzero(snb, slen); 636007Sthurlow snb->snb_family = AF_NETBIOS; 646007Sthurlow *dst = snb; 656007Sthurlow return (0); 666007Sthurlow } 676007Sthurlow 686007Sthurlow void 696007Sthurlow nb_snbfree(struct sockaddr *snb) 706007Sthurlow { 716007Sthurlow free(snb); 726007Sthurlow } 736007Sthurlow 746007Sthurlow /* 756007Sthurlow * Create a full NETBIOS address 766007Sthurlow */ 776007Sthurlow int 786007Sthurlow nb_sockaddr(struct sockaddr *peer, struct nb_name *np, 796007Sthurlow struct sockaddr_nb **dst) 806007Sthurlow 816007Sthurlow { 826007Sthurlow struct sockaddr_nb *snb; 836007Sthurlow struct sockaddr_in *sin; 846007Sthurlow struct hostent *hst; 856007Sthurlow int nmlen, error; 866007Sthurlow 876007Sthurlow if (peer && (peer->sa_family != AF_INET)) 886007Sthurlow return (EPROTONOSUPPORT); 896007Sthurlow #if NOT_DEFINED /* moved encoding into kernel */ 906007Sthurlow nmlen = nb_name_len(np); 916007Sthurlow if (nmlen < NB_ENCNAMELEN) 926007Sthurlow return (EINVAL); 936007Sthurlow #else 946007Sthurlow nmlen = NB_NAMELEN; 956007Sthurlow #endif 966007Sthurlow error = nb_snballoc(nmlen, &snb); 976007Sthurlow if (error) 986007Sthurlow return (error); 996007Sthurlow 1006007Sthurlow /* 1016007Sthurlow * Moved toupper() work to callers. 1026007Sthurlow * 1036007Sthurlow * Moved NetBIOS name encoding into the driver 1046007Sthurlow * so we have readable names right up until the 1056007Sthurlow * point where we marshall them in to a message. 1066007Sthurlow * Just makes debugging easier. 1076007Sthurlow */ 1086007Sthurlow #if NOT_DEFINED 1096007Sthurlow if (nmlen != nb_name_encode(np, snb->snb_name)) 1106007Sthurlow printf(dgettext(TEXT_DOMAIN, 1116007Sthurlow "a bug somewhere in the nb_name* code\n")); 1126007Sthurlow /* XXX */ 1136007Sthurlow #else 1146007Sthurlow /* 1156007Sthurlow * OK, nb_snballoc() did bzero, set snb_family. 1166007Sthurlow * Hacks for "*" moved here from nb_name_encode(), 1176007Sthurlow * but belongs where nn_name is filled in... 1186007Sthurlow * XXX fix later 1196007Sthurlow */ 1206007Sthurlow if (strcmp(np->nn_name, "*") == 0) { 1216007Sthurlow /* Star is special: No blanks, type, etc. */ 1226007Sthurlow snb->snb_name[0] = '*'; 1236007Sthurlow } else { 1246007Sthurlow /* Normal name: pad with blanks, add type. */ 1256007Sthurlow assert(NB_NAMELEN == 16); 1266007Sthurlow snprintf(snb->snb_name, NB_NAMELEN, 1276007Sthurlow "%-15.15s", np->nn_name); 1286007Sthurlow snb->snb_name[15] = (char)np->nn_type; 1296007Sthurlow } 1306007Sthurlow #endif 1316007Sthurlow 1326007Sthurlow if (peer) { 1336007Sthurlow /*LINTED*/ 1346007Sthurlow sin = (struct sockaddr_in *)peer; 1356007Sthurlow snb->snb_ipaddr = sin->sin_addr.s_addr; 1366007Sthurlow } 1376007Sthurlow *dst = snb; 1386007Sthurlow return (0); 1396007Sthurlow } 1406007Sthurlow 1416007Sthurlow int 1426007Sthurlow nb_name_len(struct nb_name *np) 1436007Sthurlow { 1446007Sthurlow char *name; 1456007Sthurlow int len, sclen; 1466007Sthurlow 1476007Sthurlow len = 1 + NB_ENCNAMELEN; 1486007Sthurlow if (np->nn_scope == NULL) 1496007Sthurlow return (len + 1); 1506007Sthurlow sclen = 0; 1516007Sthurlow for (name = np->nn_scope; *name; name++) { 1526007Sthurlow if (*name == '.') { 1536007Sthurlow sclen = 0; 1546007Sthurlow } else { 1556007Sthurlow if (sclen < NB_MAXLABLEN) { 1566007Sthurlow sclen++; 1576007Sthurlow len++; 1586007Sthurlow } 1596007Sthurlow } 1606007Sthurlow } 1616007Sthurlow return (len + 1); 1626007Sthurlow } 1636007Sthurlow 1646007Sthurlow int 1656007Sthurlow nb_encname_len(const uchar_t *str) 1666007Sthurlow { 1676007Sthurlow const uchar_t *cp = str; 1686007Sthurlow int len, blen; 1696007Sthurlow 1706007Sthurlow if ((cp[0] & 0xc0) == 0xc0) 1716007Sthurlow return (-1); /* first two bytes are offset to name */ 1726007Sthurlow 1736007Sthurlow len = 1; 1746007Sthurlow for (;;) { 1756007Sthurlow blen = *cp; 1766007Sthurlow if (blen++ == 0) 1776007Sthurlow break; 1786007Sthurlow len += blen; 1796007Sthurlow cp += blen; 1806007Sthurlow } 1816007Sthurlow return (len); 1826007Sthurlow } 1836007Sthurlow 1846007Sthurlow int 1856007Sthurlow nb_name_encode(struct nb_name *np, uchar_t *dst) 1866007Sthurlow { 1876007Sthurlow char *name; 1886007Sthurlow uchar_t *plen; 1896007Sthurlow uchar_t ch, *cp = dst; 1906007Sthurlow char *p, buf1[NB_NAMELEN+1]; 1916007Sthurlow int i, lblen; 1926007Sthurlow 1936007Sthurlow /* 1946007Sthurlow * XXX: I'd rather see this part moved into 1956007Sthurlow * callers of this function, leaving just 1966007Sthurlow * the pure NB encoding here. -GWR 1976007Sthurlow */ 1986007Sthurlow name = np->nn_name; 1996007Sthurlow if (name[0] == '*') { 2006007Sthurlow /* Star is special: No blanks, type, etc. */ 2016007Sthurlow bzero(buf1, NB_NAMELEN); 2026007Sthurlow buf1[0] = '*'; 2036007Sthurlow } else { 2046007Sthurlow /* Normal name: pad with blanks, add type. */ 2056007Sthurlow assert(NB_NAMELEN == 16); 2066007Sthurlow snprintf(buf1, NB_NAMELEN, 2076007Sthurlow "%-15.15s", name); 2086007Sthurlow buf1[15] = (char)np->nn_type; 2096007Sthurlow } 2106007Sthurlow name = buf1; 2116007Sthurlow 2126007Sthurlow /* 2136007Sthurlow * Do the NetBIOS "first-level encoding" here. 2146007Sthurlow * (RFC1002 explains this wierdness...) 2156007Sthurlow * See similar code in kernel nsmb module: 2166007Sthurlow * uts/common/fs/smbclnt/netsmb/smb_trantcp.c 2176007Sthurlow * 2186007Sthurlow * Here is what we marshall: 2196007Sthurlow * uint8_t NAME_LENGTH (always 32) 2206007Sthurlow * uint8_t ENCODED_NAME[32] 2216007Sthurlow * uint8_t SCOPE_LENGTH 2226007Sthurlow * Scope follows here, then another null. 2236007Sthurlow */ 2246007Sthurlow 2256007Sthurlow /* NAME_LENGTH */ 2266007Sthurlow *cp++ = (2 * NB_NAMELEN); 2276007Sthurlow 2286007Sthurlow /* ENCODED_NAME */ 2296007Sthurlow for (i = 0; i < NB_NAMELEN; i++) { 2306007Sthurlow ch = name[i]; 2316007Sthurlow *cp++ = 'A' + ((ch >> 4) & 0xF); 2326007Sthurlow *cp++ = 'A' + ((ch) & 0xF); 2336007Sthurlow } 2346007Sthurlow 2356007Sthurlow /* 2366007Sthurlow * NetBIOS "scope" sting encoding, 2376007Sthurlow * a.k.a second-level encoding. 2386007Sthurlow * See RFC1002 for the details. 2396007Sthurlow * 2406007Sthurlow * Note: plen points to the length byte at the 2416007Sthurlow * start of each string. This keeps a pointer 2426007Sthurlow * to the location and fills it in after the 2436007Sthurlow * length of the string is determined. 2446007Sthurlow */ 2456007Sthurlow #if NOT_DEFINED /* XXX: not yet */ 2466007Sthurlow if (np->nn_scope) { 2476007Sthurlow plen = cp++; 2486007Sthurlow *plen = 0; /* fill in later */ 2496007Sthurlow lblen = 0; 2506007Sthurlow for (p = np->nn_scope; ; p++) { 2516007Sthurlow if (*p == '.' || *p == 0) { 2526007Sthurlow *plen = lblen; 2536007Sthurlow if (*p == 0) 2546007Sthurlow break; 2556007Sthurlow plen = cp++; 2566007Sthurlow *plen = 0; 2576007Sthurlow lblen = 0; 2586007Sthurlow } else { 2596007Sthurlow if (lblen < NB_MAXLABLEN) { 2606007Sthurlow *cp++ = *p; 2616007Sthurlow lblen++; 2626007Sthurlow } 2636007Sthurlow } 2646007Sthurlow } 2656007Sthurlow } else 2666007Sthurlow #endif /* XXX: not yet */ 2676007Sthurlow { 2686007Sthurlow *cp++ = 0; 2696007Sthurlow } 2706007Sthurlow 2716007Sthurlow return (cp - dst); 2726007Sthurlow } 273