nb_name.c revision 02d09e03eb27f3a2dc299de704e45dae5173f43f
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Copyright (c) 2000, Boris Popov
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * All rights reserved.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Redistribution and use in source and binary forms, with or without
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * modification, are permitted provided that the following conditions
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * are met:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * 1. Redistributions of source code must retain the above copyright
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * notice, this list of conditions and the following disclaimer.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * 2. Redistributions in binary form must reproduce the above copyright
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * notice, this list of conditions and the following disclaimer in the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * documentation and/or other materials provided with the distribution.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * 3. All advertising materials mentioning features or use of this software
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * must display the following acknowledgement:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * This product includes software developed by Boris Popov.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * 4. Neither the name of the author nor the names of any co-contributors
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * may be used to endorse or promote products derived from this software
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * without specific prior written permission.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * SUCH DAMAGE.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * $Id: nb_name.c,v 1.11 2004/12/11 05:23:59 lindak Exp $
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <sys/param.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <sys/socket.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <ctype.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <errno.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <stdio.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <stdlib.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <string.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <strings.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <libintl.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <assert.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <netsmb/netbios.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <netsmb/smb_lib.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <netsmb/nb_lib.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include <netsmb/mchain.h>
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include "private.h"
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisint
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisnb_snballoc(struct sockaddr_nb **dst)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis{
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis struct sockaddr_nb *snb;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis int slen;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis slen = sizeof (struct sockaddr_nb);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis snb = malloc(slen);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (snb == NULL)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (ENOMEM);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis bzero(snb, slen);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis snb->snb_family = AF_NETBIOS;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *dst = snb;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (0);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis}
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisvoid
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisnb_snbfree(struct sockaddr *snb)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis{
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis free(snb);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis}
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Create a full NETBIOS address
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Passed names should already be upper case.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Stores the names truncated or blank padded.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * NetBIOS name encoding happens later.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisint
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisnb_sockaddr(struct sockaddr *peer, struct nb_name *np,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis struct sockaddr_nb **dst)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis{
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis struct sockaddr_nb *snb;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis struct sockaddr_in *sin;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis int error;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (peer && (peer->sa_family != AF_INET))
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (EPROTONOSUPPORT);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis error = nb_snballoc(&snb);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (error)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (error);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (strcmp(np->nn_name, "*") == 0) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* Star is special: No blanks, type, etc. */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis snb->snb_name[0] = '*';
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis } else {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* Normal name: pad with blanks, add type. */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis snprintf(snb->snb_name, NB_NAMELEN,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis "%-15.15s", np->nn_name);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis snb->snb_name[15] = (char)np->nn_type;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (peer) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /*LINTED*/
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis sin = (struct sockaddr_in *)peer;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis snb->snb_ipaddr = sin->sin_addr.s_addr;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *dst = snb;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (0);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis}
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisint
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisnb_name_len(struct nb_name *np)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis{
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis char *name;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis int len, sclen;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis len = 1 + NB_ENCNAMELEN;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (np->nn_scope == NULL)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (len + 1);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis sclen = 0;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis for (name = np->nn_scope; *name; name++) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (*name == '.') {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis sclen = 0;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis } else {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (sclen < NB_MAXLABLEN) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis sclen++;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis len++;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (len + 1);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis}
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisint
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisnb_encname_len(const uchar_t *str)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis{
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis const uchar_t *cp = str;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis int len, blen;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if ((cp[0] & 0xc0) == 0xc0)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (-1); /* first two bytes are offset to name */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis len = 1;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis for (;;) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis blen = *cp;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (blen++ == 0)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis break;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis len += blen;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis cp += blen;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (len);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis}
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisint
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisnb_name_encode(struct mbdata *mbp, struct nb_name *nn)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis{
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis char *plen;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis uchar_t ch;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis char *p, namebuf[NB_NAMELEN+1];
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis int i, lblen;
bcopy(nn->nn_name, namebuf, NB_NAMELEN);
namebuf[NB_NAMELEN-1] = (char)nn->nn_type;
namebuf[NB_NAMELEN] = '\0'; /* for debug */
/*
* Do the NetBIOS "first-level encoding" here.
* (RFC1002 explains this weirdness...)
*
* Here is what we marshall:
* uint8_t NAME_LENGTH (always 32)
* uint8_t ENCODED_NAME[32]
* uint8_t SCOPE_LENGTH
* Scope follows here, then another null.
*/
/* NAME_LENGTH */
mb_put_uint8(mbp, (2 * NB_NAMELEN));
/* ENCODED_NAME */
for (i = 0; i < NB_NAMELEN; i++) {
ch = namebuf[i];
mb_put_uint8(mbp, 'A' + ((ch >> 4) & 0xF));
mb_put_uint8(mbp, 'A' + ((ch) & 0xF));
}
/*
* NetBIOS "scope" sting encoding,
* a.k.a second-level encoding.
* See RFC1002 for the details.
*
* Note: plen points to the length byte at the
* start of each string. This keeps a pointer
* to the location and fills it in after the
* length of the string is determined.
*
* One string of length zero terminates.
* With no scope string, the zero-length
* string is the only thing there.
*/
if (nn->nn_scope == NULL) {
mb_put_uint8(mbp, 0);
return (0);
}
(void) mb_fit(mbp, 1, &plen);
*plen = 0; /* will update below */
lblen = 0;
for (p = nn->nn_scope; ; p++) {
if (*p == '\0') {
*plen = lblen;
if (lblen)
mb_put_uint8(mbp, 0);
break;
}
if (*p == '.') {
*plen = lblen;
(void) mb_fit(mbp, 1, &plen);
*plen = 0;
lblen = 0;
} else {
if (lblen < NB_MAXLABLEN) {
mb_put_uint8(mbp, *p);
lblen++;
}
}
}
return (0);
}