smbrdr_netbios.c revision 380acbbe9da7dc2cbab5b6db169ec6968dd927fa
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
/*
* NetBIOS support functions. NetBIOS is documented in the following
* RFC documents:
*
* Transport: Concepts and Methods
*
* Transport: Detailed Specifications
*
*/
#define BSD_BYTE_STRING_PROTOTYPES
#include <string.h>
#include <unistd.h>
#include <synch.h>
#include <stdio.h>
#include <pthread.h>
#define MAX_NETBIOS_NAME_SIZE 16
#define SESSION_MESSAGE 0x00
#define SESSION_REQUEST 0x81
#define POSITIVE_SESSION_RESPONSE 0x82
#define NEGATIVE_SESSION_RESPONSE 0x83
#define RETARGET_SESSION_RESPONSE 0x84
#define SESSION_KEEP_ALIVE 0x85
#define NB_READ_MSG_ERR_EOF 0
#define NB_READ_MSG_ERR -1
#define NB_READ_MSG_ERR_OVERFLOW -2
#define NB_READ_MSG_ERR_UNDERFLOW -3
#define NB_RCV_MSG_ERR_INVTYPE -4
/*
* Semaphore object used to serialize access through NetBIOS exchange.
*/
/*
* nb_lock
*
* Acquire mutex for doing netbios operations
*/
void
nb_lock()
{
(void) mutex_lock(&nb_mutex);
}
/*
* nb_lock
*
* Release netbios mutex.
*/
void
{
(void) mutex_unlock(&nb_mutex);
}
void
{
(void) mutex_lock(&nb_mutex);
if (fd > 0)
(void) mutex_unlock(&nb_mutex);
}
/*
* nb_keep_alive
*
* Send the NetBIOS keep alive message only if smbrdr is connected on port 139.
* No response is expected but we do need to ignore keep-alive messages in
* nb_exchange. The mutex ensures compatibility/serialization with
* nb_exchange to allow us to call this function from a separate thread.
*/
int
{
int nothing;
int rc;
if (port == IPPORT_SMB)
return (0);
(void) mutex_lock(&nb_mutex);
(void) mutex_unlock(&nb_mutex);
return (rc);
}
/*
* nb_send
*
* This is just a wrapper round the nb_write_msg.
*/
int
{
int rc;
return (rc);
}
/*
* nb_rcv
*
* This is a wrapper round the nb_read_msg() so that if a
* keep-alive message is received, just discard it and go
* back to look for the real response.
*/
int
{
int rc;
int type;
do {
if (rc < 0)
return (rc);
} while (type == SESSION_KEEP_ALIVE);
if (type != SESSION_MESSAGE)
return (NB_RCV_MSG_ERR_INVTYPE);
return (rc);
}
/*
* nb_exchange
*
* message exchange. A mutex is used to serialize access because
* we may get swapped out between the send and receive operations and
* another thread could enter here and collect our response. If a
* keep-alive message is received, just discard it and go back to look
* for the real response.
*
* Note: With the addition of support for SMB over TCP, this function
* may be exchanging NetBIOS-less SMB data.
*/
int
{
int rc;
return (rc);
}
/*
* nb_session_request
*
* We should never see descriptor 0 (stdin) or -1.
*/
int
char *calling_name, char *calling_scope)
{
unsigned char sr_buf[200];
int len;
int rc;
int type;
return (-1);
(void) mutex_lock(&nb_mutex);
if (rc < 0) {
(void) mutex_unlock(&nb_mutex);
return (rc);
}
for (;;) {
if (rc < 0) {
(void) mutex_unlock(&nb_mutex);
return (rc);
}
(void) mutex_unlock(&nb_mutex);
return (-1); /* EOF */
}
if (type == POSITIVE_SESSION_RESPONSE) {
(void) mutex_unlock(&nb_mutex);
return (0);
}
if (type == NEGATIVE_SESSION_RESPONSE) {
(void) mutex_unlock(&nb_mutex);
return (-1);
}
}
/* NOTREACHED */
(void) mutex_unlock(&nb_mutex);
return (-1);
}
/*
* nb_write_msg
*/
static int
{
unsigned char header[4];
int rc;
/*
* We should never see descriptor 0 (stdin).
*/
return (-1);
}
/*
* The NetBIOS message length is limited to 17 bits but
* we use this layer for SMB over both NetBIOS and TCP
* (NetBIOS-less SMB). When using SMB over TCP the length
* is 24 bits but we are ignoring that for now because we
* don't expect any messages larger than 64KB.
*/
return (-3); /* error */
}
return (count);
}
/*
* nb_read_msg
*
* Added select to ensure that we don't block forever waiting for a
* message.
*/
static int
{
unsigned char header[4];
int length;
int rc;
*type = -1;
/*
* We should never see descriptor 0 (stdin).
*/
return (NB_READ_MSG_ERR);
}
if (timeout == 0)
return (NB_READ_MSG_ERR);
}
return (rc); /* error */
if (rc != 4)
return (NB_READ_MSG_ERR_EOF); /* EOF */
/*
* The NetBIOS message length is limited to 17 bits but
* we use this layer for SMB over both NetBIOS and TCP
* (NetBIOS-less SMB). When using SMB over TCP the length
* is 24 bits but we are ignoring that for now because we
* don't expect any messages larger than 64KB.
*/
return (NB_READ_MSG_ERR_OVERFLOW); /* error overflow */
return (NB_READ_MSG_ERR_UNDERFLOW); /* error underflow */
return (rc);
}
/*
* nb_read_itter
*
* We should never see descriptor 0 (stdin) or -1.
*/
static int
{
int ix;
int rc;
return (-1);
return (rc);
if (rc == 0)
break;
}
return (ix);
}
/*
* nb_first_level_name_encode
*/
static int
{
unsigned char *in;
unsigned char *lp;
*op++ = 0x20;
}
ch = ' ';
}
len = 0;
if (ch == 0) {
*op++ = 0;
break;
}
if (ch == '.') {
len = 0;
} else {
len++;
}
}
}