Home | History | Annotate | Download | only in smb
      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(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  * Passed names should already be upper case.
     77  * Stores the names truncated or blank padded.
     78  * NetBIOS name encoding happens later.
     79  */
     80 int
     81 nb_sockaddr(struct sockaddr *peer, struct nb_name *np,
     82 	struct sockaddr_nb **dst)
     83 
     84 {
     85 	struct sockaddr_nb *snb;
     86 	struct sockaddr_in *sin;
     87 	int error;
     88 
     89 	if (peer && (peer->sa_family != AF_INET))
     90 		return (EPROTONOSUPPORT);
     91 	error = nb_snballoc(&snb);
     92 	if (error)
     93 		return (error);
     94 
     95 	if (strcmp(np->nn_name, "*") == 0) {
     96 		/* Star is special: No blanks, type, etc. */
     97 		snb->snb_name[0] = '*';
     98 	} else {
     99 		/* Normal name: pad with blanks, add type. */
    100 		snprintf(snb->snb_name, NB_NAMELEN,
    101 		    "%-15.15s", np->nn_name);
    102 		snb->snb_name[15] = (char)np->nn_type;
    103 	}
    104 
    105 	if (peer) {
    106 		/*LINTED*/
    107 		sin = (struct sockaddr_in *)peer;
    108 		snb->snb_ipaddr = sin->sin_addr.s_addr;
    109 	}
    110 	*dst = snb;
    111 	return (0);
    112 }
    113 
    114 int
    115 nb_name_len(struct nb_name *np)
    116 {
    117 	char *name;
    118 	int len, sclen;
    119 
    120 	len = 1 + NB_ENCNAMELEN;
    121 	if (np->nn_scope == NULL)
    122 		return (len + 1);
    123 	sclen = 0;
    124 	for (name = np->nn_scope; *name; name++) {
    125 		if (*name == '.') {
    126 			sclen = 0;
    127 		} else {
    128 			if (sclen < NB_MAXLABLEN) {
    129 				sclen++;
    130 				len++;
    131 			}
    132 		}
    133 	}
    134 	return (len + 1);
    135 }
    136 
    137 int
    138 nb_encname_len(const uchar_t *str)
    139 {
    140 	const uchar_t *cp = str;
    141 	int len, blen;
    142 
    143 	if ((cp[0] & 0xc0) == 0xc0)
    144 		return (-1);	/* first two bytes are offset to name */
    145 
    146 	len = 1;
    147 	for (;;) {
    148 		blen = *cp;
    149 		if (blen++ == 0)
    150 			break;
    151 		len += blen;
    152 		cp += blen;
    153 	}
    154 	return (len);
    155 }
    156 
    157 int
    158 nb_name_encode(struct mbdata *mbp, struct nb_name *nn)
    159 {
    160 	char *plen;
    161 	uchar_t ch;
    162 	char *p, namebuf[NB_NAMELEN+1];
    163 	int i, lblen;
    164 
    165 	bcopy(nn->nn_name, namebuf, NB_NAMELEN);
    166 	namebuf[NB_NAMELEN-1] = (char)nn->nn_type;
    167 	namebuf[NB_NAMELEN] = '\0'; /* for debug */
    168 
    169 	/*
    170 	 * Do the NetBIOS "first-level encoding" here.
    171 	 * (RFC1002 explains this weirdness...)
    172 	 *
    173 	 * Here is what we marshall:
    174 	 *   uint8_t NAME_LENGTH (always 32)
    175 	 *   uint8_t ENCODED_NAME[32]
    176 	 *   uint8_t SCOPE_LENGTH
    177 	 *   Scope follows here, then another null.
    178 	 */
    179 
    180 	/* NAME_LENGTH */
    181 	mb_put_uint8(mbp, (2 * NB_NAMELEN));
    182 
    183 	/* ENCODED_NAME */
    184 	for (i = 0; i < NB_NAMELEN; i++) {
    185 		ch = namebuf[i];
    186 		mb_put_uint8(mbp, 'A' + ((ch >> 4) & 0xF));
    187 		mb_put_uint8(mbp, 'A' + ((ch) & 0xF));
    188 	}
    189 
    190 	/*
    191 	 * NetBIOS "scope" sting encoding,
    192 	 * a.k.a second-level encoding.
    193 	 * See RFC1002 for the details.
    194 	 *
    195 	 * Note: plen points to the length byte at the
    196 	 * start of each string.  This keeps a pointer
    197 	 * to the location and fills it in after the
    198 	 * length of the string is determined.
    199 	 *
    200 	 * One string of length zero terminates.
    201 	 * With no scope string, the zero-length
    202 	 * string is the only thing there.
    203 	 */
    204 	if (nn->nn_scope == NULL) {
    205 		mb_put_uint8(mbp, 0);
    206 		return (0);
    207 	}
    208 
    209 	(void) mb_fit(mbp, 1, &plen);
    210 	*plen = 0; /* will update below */
    211 	lblen = 0;
    212 	for (p = nn->nn_scope; ; p++) {
    213 		if (*p == '\0') {
    214 			*plen = lblen;
    215 			if (lblen)
    216 				mb_put_uint8(mbp, 0);
    217 			break;
    218 		}
    219 		if (*p == '.') {
    220 			*plen = lblen;
    221 			(void) mb_fit(mbp, 1, &plen);
    222 			*plen = 0;
    223 			lblen = 0;
    224 		} else {
    225 			if (lblen < NB_MAXLABLEN) {
    226 				mb_put_uint8(mbp, *p);
    227 				lblen++;
    228 			}
    229 		}
    230 	}
    231 
    232 	return (0);
    233 }
    234