1*4bff34e3Sthurlow /* 2*4bff34e3Sthurlow * Copyright (c) 2000, Boris Popov 3*4bff34e3Sthurlow * All rights reserved. 4*4bff34e3Sthurlow * 5*4bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 6*4bff34e3Sthurlow * modification, are permitted provided that the following conditions 7*4bff34e3Sthurlow * are met: 8*4bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 9*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 10*4bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 11*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 12*4bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 13*4bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 14*4bff34e3Sthurlow * must display the following acknowledgement: 15*4bff34e3Sthurlow * This product includes software developed by Boris Popov. 16*4bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 17*4bff34e3Sthurlow * may be used to endorse or promote products derived from this software 18*4bff34e3Sthurlow * without specific prior written permission. 19*4bff34e3Sthurlow * 20*4bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*4bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*4bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*4bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*4bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*4bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*4bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*4bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*4bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*4bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*4bff34e3Sthurlow * SUCH DAMAGE. 31*4bff34e3Sthurlow * 32*4bff34e3Sthurlow * $Id: nb_name.c,v 1.11 2004/12/11 05:23:59 lindak Exp $ 33*4bff34e3Sthurlow */ 34*4bff34e3Sthurlow 35*4bff34e3Sthurlow #pragma ident "%Z%%M% %I% %E% SMI" 36*4bff34e3Sthurlow 37*4bff34e3Sthurlow #include <sys/param.h> 38*4bff34e3Sthurlow #include <sys/socket.h> 39*4bff34e3Sthurlow #include <ctype.h> 40*4bff34e3Sthurlow #include <errno.h> 41*4bff34e3Sthurlow #include <stdio.h> 42*4bff34e3Sthurlow #include <stdlib.h> 43*4bff34e3Sthurlow #include <string.h> 44*4bff34e3Sthurlow #include <strings.h> 45*4bff34e3Sthurlow #include <libintl.h> 46*4bff34e3Sthurlow #include <assert.h> 47*4bff34e3Sthurlow 48*4bff34e3Sthurlow #include <netsmb/netbios.h> 49*4bff34e3Sthurlow #include <netsmb/smb_lib.h> 50*4bff34e3Sthurlow #include <netsmb/nb_lib.h> 51*4bff34e3Sthurlow #include <netsmb/mchain.h> 52*4bff34e3Sthurlow 53*4bff34e3Sthurlow int 54*4bff34e3Sthurlow nb_snballoc(int namelen, struct sockaddr_nb **dst) 55*4bff34e3Sthurlow { 56*4bff34e3Sthurlow struct sockaddr_nb *snb; 57*4bff34e3Sthurlow int slen; 58*4bff34e3Sthurlow 59*4bff34e3Sthurlow slen = sizeof (struct sockaddr_nb); 60*4bff34e3Sthurlow snb = malloc(slen); 61*4bff34e3Sthurlow if (snb == NULL) 62*4bff34e3Sthurlow return (ENOMEM); 63*4bff34e3Sthurlow bzero(snb, slen); 64*4bff34e3Sthurlow snb->snb_family = AF_NETBIOS; 65*4bff34e3Sthurlow *dst = snb; 66*4bff34e3Sthurlow return (0); 67*4bff34e3Sthurlow } 68*4bff34e3Sthurlow 69*4bff34e3Sthurlow void 70*4bff34e3Sthurlow nb_snbfree(struct sockaddr *snb) 71*4bff34e3Sthurlow { 72*4bff34e3Sthurlow free(snb); 73*4bff34e3Sthurlow } 74*4bff34e3Sthurlow 75*4bff34e3Sthurlow /* 76*4bff34e3Sthurlow * Create a full NETBIOS address 77*4bff34e3Sthurlow */ 78*4bff34e3Sthurlow int 79*4bff34e3Sthurlow nb_sockaddr(struct sockaddr *peer, struct nb_name *np, 80*4bff34e3Sthurlow struct sockaddr_nb **dst) 81*4bff34e3Sthurlow 82*4bff34e3Sthurlow { 83*4bff34e3Sthurlow struct sockaddr_nb *snb; 84*4bff34e3Sthurlow struct sockaddr_in *sin; 85*4bff34e3Sthurlow struct hostent *hst; 86*4bff34e3Sthurlow int nmlen, error; 87*4bff34e3Sthurlow 88*4bff34e3Sthurlow if (peer && (peer->sa_family != AF_INET)) 89*4bff34e3Sthurlow return (EPROTONOSUPPORT); 90*4bff34e3Sthurlow #if NOT_DEFINED /* moved encoding into kernel */ 91*4bff34e3Sthurlow nmlen = nb_name_len(np); 92*4bff34e3Sthurlow if (nmlen < NB_ENCNAMELEN) 93*4bff34e3Sthurlow return (EINVAL); 94*4bff34e3Sthurlow #else 95*4bff34e3Sthurlow nmlen = NB_NAMELEN; 96*4bff34e3Sthurlow #endif 97*4bff34e3Sthurlow error = nb_snballoc(nmlen, &snb); 98*4bff34e3Sthurlow if (error) 99*4bff34e3Sthurlow return (error); 100*4bff34e3Sthurlow 101*4bff34e3Sthurlow /* 102*4bff34e3Sthurlow * Moved toupper() work to callers. 103*4bff34e3Sthurlow * 104*4bff34e3Sthurlow * Moved NetBIOS name encoding into the driver 105*4bff34e3Sthurlow * so we have readable names right up until the 106*4bff34e3Sthurlow * point where we marshall them in to a message. 107*4bff34e3Sthurlow * Just makes debugging easier. 108*4bff34e3Sthurlow */ 109*4bff34e3Sthurlow #if NOT_DEFINED 110*4bff34e3Sthurlow if (nmlen != nb_name_encode(np, snb->snb_name)) 111*4bff34e3Sthurlow printf(dgettext(TEXT_DOMAIN, 112*4bff34e3Sthurlow "a bug somewhere in the nb_name* code\n")); 113*4bff34e3Sthurlow /* XXX */ 114*4bff34e3Sthurlow #else 115*4bff34e3Sthurlow /* 116*4bff34e3Sthurlow * OK, nb_snballoc() did bzero, set snb_family. 117*4bff34e3Sthurlow * Hacks for "*" moved here from nb_name_encode(), 118*4bff34e3Sthurlow * but belongs where nn_name is filled in... 119*4bff34e3Sthurlow * XXX fix later 120*4bff34e3Sthurlow */ 121*4bff34e3Sthurlow if (strcmp(np->nn_name, "*") == 0) { 122*4bff34e3Sthurlow /* Star is special: No blanks, type, etc. */ 123*4bff34e3Sthurlow snb->snb_name[0] = '*'; 124*4bff34e3Sthurlow } else { 125*4bff34e3Sthurlow /* Normal name: pad with blanks, add type. */ 126*4bff34e3Sthurlow assert(NB_NAMELEN == 16); 127*4bff34e3Sthurlow snprintf(snb->snb_name, NB_NAMELEN, 128*4bff34e3Sthurlow "%-15.15s", np->nn_name); 129*4bff34e3Sthurlow snb->snb_name[15] = (char)np->nn_type; 130*4bff34e3Sthurlow } 131*4bff34e3Sthurlow #endif 132*4bff34e3Sthurlow 133*4bff34e3Sthurlow if (peer) { 134*4bff34e3Sthurlow /*LINTED*/ 135*4bff34e3Sthurlow sin = (struct sockaddr_in *)peer; 136*4bff34e3Sthurlow snb->snb_ipaddr = sin->sin_addr.s_addr; 137*4bff34e3Sthurlow } 138*4bff34e3Sthurlow *dst = snb; 139*4bff34e3Sthurlow return (0); 140*4bff34e3Sthurlow } 141*4bff34e3Sthurlow 142*4bff34e3Sthurlow int 143*4bff34e3Sthurlow nb_name_len(struct nb_name *np) 144*4bff34e3Sthurlow { 145*4bff34e3Sthurlow char *name; 146*4bff34e3Sthurlow int len, sclen; 147*4bff34e3Sthurlow 148*4bff34e3Sthurlow len = 1 + NB_ENCNAMELEN; 149*4bff34e3Sthurlow if (np->nn_scope == NULL) 150*4bff34e3Sthurlow return (len + 1); 151*4bff34e3Sthurlow sclen = 0; 152*4bff34e3Sthurlow for (name = np->nn_scope; *name; name++) { 153*4bff34e3Sthurlow if (*name == '.') { 154*4bff34e3Sthurlow sclen = 0; 155*4bff34e3Sthurlow } else { 156*4bff34e3Sthurlow if (sclen < NB_MAXLABLEN) { 157*4bff34e3Sthurlow sclen++; 158*4bff34e3Sthurlow len++; 159*4bff34e3Sthurlow } 160*4bff34e3Sthurlow } 161*4bff34e3Sthurlow } 162*4bff34e3Sthurlow return (len + 1); 163*4bff34e3Sthurlow } 164*4bff34e3Sthurlow 165*4bff34e3Sthurlow int 166*4bff34e3Sthurlow nb_encname_len(const uchar_t *str) 167*4bff34e3Sthurlow { 168*4bff34e3Sthurlow const uchar_t *cp = str; 169*4bff34e3Sthurlow int len, blen; 170*4bff34e3Sthurlow 171*4bff34e3Sthurlow if ((cp[0] & 0xc0) == 0xc0) 172*4bff34e3Sthurlow return (-1); /* first two bytes are offset to name */ 173*4bff34e3Sthurlow 174*4bff34e3Sthurlow len = 1; 175*4bff34e3Sthurlow for (;;) { 176*4bff34e3Sthurlow blen = *cp; 177*4bff34e3Sthurlow if (blen++ == 0) 178*4bff34e3Sthurlow break; 179*4bff34e3Sthurlow len += blen; 180*4bff34e3Sthurlow cp += blen; 181*4bff34e3Sthurlow } 182*4bff34e3Sthurlow return (len); 183*4bff34e3Sthurlow } 184*4bff34e3Sthurlow 185*4bff34e3Sthurlow int 186*4bff34e3Sthurlow nb_name_encode(struct nb_name *np, uchar_t *dst) 187*4bff34e3Sthurlow { 188*4bff34e3Sthurlow char *name; 189*4bff34e3Sthurlow uchar_t *plen; 190*4bff34e3Sthurlow uchar_t ch, *cp = dst; 191*4bff34e3Sthurlow char *p, buf1[NB_NAMELEN+1]; 192*4bff34e3Sthurlow int i, lblen; 193*4bff34e3Sthurlow 194*4bff34e3Sthurlow /* 195*4bff34e3Sthurlow * XXX: I'd rather see this part moved into 196*4bff34e3Sthurlow * callers of this function, leaving just 197*4bff34e3Sthurlow * the pure NB encoding here. -GWR 198*4bff34e3Sthurlow */ 199*4bff34e3Sthurlow name = np->nn_name; 200*4bff34e3Sthurlow if (name[0] == '*') { 201*4bff34e3Sthurlow /* Star is special: No blanks, type, etc. */ 202*4bff34e3Sthurlow bzero(buf1, NB_NAMELEN); 203*4bff34e3Sthurlow buf1[0] = '*'; 204*4bff34e3Sthurlow } else { 205*4bff34e3Sthurlow /* Normal name: pad with blanks, add type. */ 206*4bff34e3Sthurlow assert(NB_NAMELEN == 16); 207*4bff34e3Sthurlow snprintf(buf1, NB_NAMELEN, 208*4bff34e3Sthurlow "%-15.15s", name); 209*4bff34e3Sthurlow buf1[15] = (char)np->nn_type; 210*4bff34e3Sthurlow } 211*4bff34e3Sthurlow name = buf1; 212*4bff34e3Sthurlow 213*4bff34e3Sthurlow /* 214*4bff34e3Sthurlow * Do the NetBIOS "first-level encoding" here. 215*4bff34e3Sthurlow * (RFC1002 explains this wierdness...) 216*4bff34e3Sthurlow * See similar code in kernel nsmb module: 217*4bff34e3Sthurlow * uts/common/fs/smbclnt/netsmb/smb_trantcp.c 218*4bff34e3Sthurlow * 219*4bff34e3Sthurlow * Here is what we marshall: 220*4bff34e3Sthurlow * uint8_t NAME_LENGTH (always 32) 221*4bff34e3Sthurlow * uint8_t ENCODED_NAME[32] 222*4bff34e3Sthurlow * uint8_t SCOPE_LENGTH 223*4bff34e3Sthurlow * Scope follows here, then another null. 224*4bff34e3Sthurlow */ 225*4bff34e3Sthurlow 226*4bff34e3Sthurlow /* NAME_LENGTH */ 227*4bff34e3Sthurlow *cp++ = (2 * NB_NAMELEN); 228*4bff34e3Sthurlow 229*4bff34e3Sthurlow /* ENCODED_NAME */ 230*4bff34e3Sthurlow for (i = 0; i < NB_NAMELEN; i++) { 231*4bff34e3Sthurlow ch = name[i]; 232*4bff34e3Sthurlow *cp++ = 'A' + ((ch >> 4) & 0xF); 233*4bff34e3Sthurlow *cp++ = 'A' + ((ch) & 0xF); 234*4bff34e3Sthurlow } 235*4bff34e3Sthurlow 236*4bff34e3Sthurlow /* 237*4bff34e3Sthurlow * NetBIOS "scope" sting encoding, 238*4bff34e3Sthurlow * a.k.a second-level encoding. 239*4bff34e3Sthurlow * See RFC1002 for the details. 240*4bff34e3Sthurlow * 241*4bff34e3Sthurlow * Note: plen points to the length byte at the 242*4bff34e3Sthurlow * start of each string. This keeps a pointer 243*4bff34e3Sthurlow * to the location and fills it in after the 244*4bff34e3Sthurlow * length of the string is determined. 245*4bff34e3Sthurlow */ 246*4bff34e3Sthurlow #if NOT_DEFINED /* XXX: not yet */ 247*4bff34e3Sthurlow if (np->nn_scope) { 248*4bff34e3Sthurlow plen = cp++; 249*4bff34e3Sthurlow *plen = 0; /* fill in later */ 250*4bff34e3Sthurlow lblen = 0; 251*4bff34e3Sthurlow for (p = np->nn_scope; ; p++) { 252*4bff34e3Sthurlow if (*p == '.' || *p == 0) { 253*4bff34e3Sthurlow *plen = lblen; 254*4bff34e3Sthurlow if (*p == 0) 255*4bff34e3Sthurlow break; 256*4bff34e3Sthurlow plen = cp++; 257*4bff34e3Sthurlow *plen = 0; 258*4bff34e3Sthurlow lblen = 0; 259*4bff34e3Sthurlow } else { 260*4bff34e3Sthurlow if (lblen < NB_MAXLABLEN) { 261*4bff34e3Sthurlow *cp++ = *p; 262*4bff34e3Sthurlow lblen++; 263*4bff34e3Sthurlow } 264*4bff34e3Sthurlow } 265*4bff34e3Sthurlow } 266*4bff34e3Sthurlow } else 267*4bff34e3Sthurlow #endif /* XXX: not yet */ 268*4bff34e3Sthurlow { 269*4bff34e3Sthurlow *cp++ = 0; 270*4bff34e3Sthurlow } 271*4bff34e3Sthurlow 272*4bff34e3Sthurlow return (cp - dst); 273*4bff34e3Sthurlow } 274