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