smbns_netbios_name.c revision fc724630b14603e4c1147df68b7bf45f7de7431f
/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Description:
*
* Contains base code for netbios name service.
*
*
* 6. DEFINED CONSTANTS AND VARIABLES
*
* GENERAL:
*
* SCOPE_ID The name of the NetBIOS scope.
*
* This is expressed as a character
* string meeting the requirements of
* the domain name system and without
* a leading or trailing "dot".
*
* An implementation may elect to make
* this a single global value for the
* node or allow it to be specified
* with each separate NetBIOS name
* (thus permitting cross-scope
* references.)
*
* BROADCAST_ADDRESS An IP address composed of the
* nodes's network and subnetwork
* numbers with all remaining bits set
* to one.
*
* I.e. "Specific subnet" broadcast
* addressing according to section 2.3
* of RFC 950.
*
* BCAST_REQ_RETRY_TIMEOUT 250 milliseconds.
* An adaptive timer may be used.
*
* BCAST_REQ_RETRY_COUNT 3
*
* UCAST_REQ_RETRY_TIMEOUT 5 seconds
* An adaptive timer may be used.
*
* UCAST_REQ_RETRY_COUNT 3
*
* MAX_DATAGRAM_LENGTH 576 bytes (default)
*
*
* NAME SERVICE:
*
* REFRESH_TIMER Negotiated with NAME for each name.
*
* CONFLICT_TIMER 1 second
* Implementations may chose a longer
* value.
*
*
* NAME_SERVICE_TCP_PORT 137 (decimal)
*
* NAME_SERVICE_UDP_PORT 137 (decimal)
*
* INFINITE_TTL 0
*/
#include <unistd.h>
#include <syslog.h>
#include <stdlib.h>
#include <synch.h>
#include <errno.h>
#include <netdb.h>
#include <smbsrv/libsmbns.h>
#include <smbns_netbios.h>
#define NAME_HEADER_SIZE 12
typedef struct name_reply {
struct name_reply *forw;
struct name_reply *back;
struct name_packet *packet;
struct addr_entry *addr;
unsigned short name_trn_id;
unsigned short flags;
} name_reply;
static struct name_reply reply_queue;
static name_queue_t delete_queue;
static name_queue_t refresh_queue;
/*
* Flag to control whether or not NetBIOS name refresh requests
* are logged. Set to non-zero to enable logging.
*/
static unsigned short netbios_name_transcation_id = 1;
static int name_sock = 0;
static int bcast_num = 0;
static int nbns_num = 0;
static int smb_netbios_process_response(unsigned short, struct addr_entry *,
struct name_packet *, uint32_t);
struct name_packet *packet);
static int
{
int rc;
unsigned short tid;
struct resource_record *answer;
struct name_question question;
struct addr_entry *addr;
struct name_entry *destination;
struct name_packet packet;
/*
* The response packet has in it the address of the presumed owner
* of the name. Challenge that owner. If owner either does not
* respond or indicates that he no longer owns the name, claim the
* name. Otherwise, the name cannot be claimed.
*/
return (-1);
&packet, UCAST_REQ_RETRY_TIMEOUT)) != 0)
return (rc);
}
}
/* No reply */
return (0);
}
static struct name_reply *
{
unsigned short info;
struct resource_record *answer;
struct name_reply *reply;
if (reply != 0) {
(void) mutex_lock(&rq_mtx);
(void) mutex_unlock(&rq_mtx);
for (;;) {
(void) gettimeofday(&wt, 0);
(void) mutex_lock(&reply_mtx);
(void) mutex_unlock(&reply_mtx);
(void) mutex_lock(&rq_mtx);
(void) mutex_unlock(&rq_mtx);
continue;
}
return (reply);
}
(void) gettimeofday(&wt, 0);
(void) mutex_lock(&rq_mtx);
(void) mutex_unlock(&rq_mtx);
break;
}
}
}
return (0);
}
static void
{
struct name_reply *reply;
struct resource_record *answer;
(void) mutex_lock(&rq_mtx);
(void) mutex_unlock(&rq_mtx);
(void) mutex_lock(&reply_mtx);
(void) cond_signal(&reply_cv);
(void) mutex_unlock(&reply_mtx);
return;
}
}
(void) mutex_unlock(&rq_mtx);
/* Presumably nobody is waiting any more... */
if (answer)
}
static int
{
int rc = 0;
unsigned short info;
struct name_reply *reply;
struct resource_record *answer;
struct name_entry *name;
struct name_entry *entry;
struct name_question *question;
return (0); /* No reply: retry */
}
/* response */
switch (PACKET_TYPE(info)) {
case NAME_QUERY_RESPONSE:
if (POSITIVE_RESPONSE(info)) {
do {
/*
* Make sure that remote name is not
* flagged local
*/
rc = 1;
} else {
rc = -1;
}
break;
if (NEGATIVE_RESPONSE(info)) {
if (answer == 0) {
break;
}
if (entry) {
/*
* a name in the state "conflict
* detected" does not "logically" exist
* on that node. No further session
* will be accepted on that name.
* No datagrams can be sent against
* that name.
* Such an entry will not be used for
* purposes of processing incoming
* request packets.
* The only valid user NetBIOS operation
* against such a name is DELETE NAME.
*/
"NETBIOS Name conflict: %15.15s",
}
}
break;
}
/*
* name can be added:
* adjust refresh timeout value,
* TTL, for this name
*/
do {
if ((addr->refresh_ttl == 0) ||
}
rc = 1;
break;
case NAME_RELEASE_RESPONSE:
rc = 1;
break;
/*
* The response packet has in it the
* address of the presumed owner of the
* name. Challenge that owner. If
* owner either does not respond or
* indicates that he no longer owns the
* name, claim the name. Otherwise,
* the name cannot be claimed.
*/
break;
default:
rc = 0;
break;
}
if (answer)
return (rc); /* retry */
}
/*
* smb_name_buf_from_packet
*
* Description:
* Convert a NetBIOS Name Server Packet Block (npb)
* into the bits and bytes destined for the wire.
* The "buf" is used as a heap.
*
* Inputs:
* char * buf -> Buffer, from the wire
* unsigned n_buf -> Length of 'buf'
* name_packet *npb -> Packet block, decode into
* unsigned n_npb -> Max bytes in 'npb'
*
* Returns:
* >0 -> Encode successful, value is length of packet in "buf"
* -1 -> Hard error, can not possibly encode
* -2 -> Need more memory in buf -- it's too small
*/
static int
smb_name_buf_from_packet(unsigned char *buf,
int n_buf,
struct name_packet *npb)
{
struct addr_entry *raddr;
unsigned char *dnptrs[32];
unsigned char comp_name_buf[MAX_NAME_LENGTH];
unsigned int tmp;
int i, step;
if (n_buf < NAME_HEADER_SIZE)
return (-1); /* no header, impossible */
dnptrs[1] = 0;
heap += 2;
heap += 2;
heap += 2;
heap += 2;
heap += 2;
heap += 2;
return (-2);
comp_name_buf, sizeof (comp_name_buf));
heap += 2;
heap += 2;
}
struct resource_record *nrr;
int n;
/* truly ugly, but saves code copying */
if (step == 1) {
} else if (step == 2) {
} else { /* step == 3 */
}
for (i = 0; i < n; i++) {
return (-2);
comp_name_buf, sizeof (comp_name_buf));
heap += 2;
heap += 2;
heap += 4;
heap += 2;
return (-2);
heap += 2;
sizeof (uint32_t));
heap += 4;
} else {
}
}
}
}
}
/*
* strnchr
*
* Lookup for character 'c' in first 'n' chars of string 's'.
* Returns pointer to the found char, otherwise returns 0.
*/
static char *
strnchr(const char *s, char c, int n)
{
char *ps = (char *)s;
char *es = (char *)s + n;
if (*ps == c)
return (ps);
++ps;
}
return (ps);
return (0);
}
static boolean_t
is_multihome(char *name)
{
}
/*
* smb_netbios_getname
*
* Get the Netbios name part of the given record.
* Does some boundary checks.
*
* Returns the name length on success, otherwise
* returns 0.
*/
static int
{
char *name_end;
int name_len;
/* no room for a NB name */
return (0);
}
if (name_end == 0) {
/* not a valid NB name */
return (0);
}
return (name_len);
}
/*
* smb_name_buf_to_packet
*
* Description:
* Convert the bits and bytes that came from the wire
* into a NetBIOS Name Server Packet Block (npb).
* The "block" is used as a heap.
*
* Inputs:
* char * buf -> Buffer, from the wire
* int n_buf -> Length of 'buf'
* name_packet *npb -> Packet block, decode into
* int n_npb -> Max bytes in 'npb'
*
* Returns:
* >0 -> Decode (parse) successful, value is byte length of npb
* -1 -> Hard error, can not possibly decode
* -2 -> Need more memory in npb -- it's too small
*/
static struct name_packet *
{
struct name_packet *npb;
unsigned char *heap;
char name_buf[MAX_NAME_LENGTH];
struct resource_record *nrr = 0;
unsigned short name_trn_id, info;
struct addr_entry *next;
int name_len;
if (n_buf < NAME_HEADER_SIZE) {
/* truncated header */
n_buf);
return (0);
}
ns = sizeof (struct name_entry);
n = n_buf + sizeof (struct name_packet) +
return (0);
}
/* scan is in position for question entries */
/*
* Measure the space needed for the tables
*/
if (qdcount > 0) {
/* LINTED - E_BAD_PTR_CAST_ALIGN */
for (i = 0; i < qdcount; i++) {
/* LINTED - E_BAD_PTR_CAST_ALIGN */
heap += sizeof (struct name_entry);
}
}
/* LINTED - E_BAD_PTR_CAST_ALIGN */
if (ancount > 0) {
/* LINTED - E_BAD_PTR_CAST_ALIGN */
}
if (nscount > 0) {
/* LINTED - E_BAD_PTR_CAST_ALIGN */
}
if (arcount > 0) {
/* LINTED - E_BAD_PTR_CAST_ALIGN */
}
/*
* Populate each resource_record's .name field.
* Done as a second pass so that all resource records
* (answer, authority, additional) are consecutive via nrr[i].
*/
/* LINTED - E_BAD_PTR_CAST_ALIGN */
heap += sizeof (struct name_entry);
}
(char *)scan_end);
if (name_len <= 0) {
return (0);
}
smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
if (rc < 0) {
/* Couldn't decode the question name */
return (0);
}
/* no room for Question Type(2) and Class(2) fields */
return (0);
}
}
/*
* Cheat. Remaining sections are of the same resource_record
* format. Table space is consecutive.
*/
if (scan[0] == 0xc0) {
/* Namebuf is reused... */
rc = 2;
} else {
(char *)scan_end);
if (name_len <= 0) {
return (0);
}
}
/*
* no room for RR_TYPE (2), RR_CLASS (2), TTL (4) and
* RDLENGTH (2) fields.
*/
return (0);
}
smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
return (0);
}
/* no room for RDATA */
return (0);
}
nn = n;
while (nn) {
if (nn == 6)
else {
next = (struct addr_entry *)
sizeof (struct addr_entry));
if (next == 0) {
/* not enough memory */
return (0);
}
next);
}
(void) memcpy(
nn -= 6;
scan += 6;
}
} else {
scan += n;
}
heap += n;
}
}
return (npb);
}
/*
* smb_send_name_service_packet
*
* Description:
*
* Send out a name service packet to proper destination.
*
* Inputs:
* struct netbios_name *dest -> NETBIOS name of destination
* struct name_packet *packet -> Packet to send
*
* Returns:
* success -> >0
* failure -> <=0
*/
static int
struct name_packet *packet)
{
unsigned char buf[MAX_DATAGRAM_LENGTH];
int len;
return (-1);
}
}
/*
* 4.2.1.1. HEADER
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID | OPCODE | NM_FLAGS | RCODE |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | QDCOUNT | ANCOUNT |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NSCOUNT | ARCOUNT |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Field Description
*
* NAME_TRN_ID Transaction ID for Name Service Transaction.
* Requester places a unique value for each active
* transaction. Responder puts NAME_TRN_ID value
* from request packet in response packet.
*
* OPCODE Packet type code, see table below.
*
* NM_FLAGS Flags for operation, see table below.
*
* RCODE Result codes of request. Table of RCODE values
* for each response packet below.
*
* QDCOUNT Unsigned 16 bit integer specifying the number of
* entries in the question section of a Name
*
* Service packet. Always zero (0) for responses.
* Must be non-zero for all NetBIOS Name requests.
*
* ANCOUNT Unsigned 16 bit integer specifying the number of
* resource records in the answer section of a Name
* Service packet.
*
* NSCOUNT Unsigned 16 bit integer specifying the number of
* resource records in the authority section of a
* Name Service packet.
*
* ARCOUNT Unsigned 16 bit integer specifying the number of
* resource records in the additional records
* section of a Name Service packet.
*
* The OPCODE field is defined as:
*
* 0 1 2 3 4
* +---+---+---+---+---+
* | R | OPCODE |
* +---+---+---+---+---+
*
* Symbol Bit(s) Description
*
* OPCODE 1-4 Operation specifier:
* 0 = query
* 5 = registration
* 6 = release
* 7 = WACK
* 8 = refresh
*
* R 0 RESPONSE flag:
* if bit == 0 then request packet
* if bit == 1 then response packet.
*/
/*
* The NM_FLAGS field is defined as:
*
*
* 0 1 2 3 4 5 6
* +---+---+---+---+---+---+---+
* |AA |TC |RD |RA | 0 | 0 | B |
* +---+---+---+---+---+---+---+
*
* Symbol Bit(s) Description
*
* B 6 Broadcast Flag.
* = 1: packet was broadcast or multicast
* = 0: unicast
*
* RA 3 Recursion Available Flag.
*
* Only valid in responses from a NetBIOS Name
* Server -- must be zero in all other
* responses.
*
* If one (1) then the NAME supports recursive
* query, registration, and release.
*
* If zero (0) then the end-node must iterate
* for query and challenge for registration.
*
* RD 2 Recursion Desired Flag.
*
* May only be set on a request to a NetBIOS
* Name Server.
*
* The NAME will copy its state into the
* response packet.
*
* If one (1) the NAME will iterate on the
* query, registration, or release.
*
* TC 1 Truncation Flag.
*
* Set if this message was truncated because the
* datagram carrying it would be greater than
* 576 bytes in length. Use TCP to get the
* information from the NetBIOS Name Server.
*
* AA 0 Authoritative Answer flag.
*
* Must be zero (0) if R flag of OPCODE is zero
* (0).
*
* If R flag is one (1) then if AA is one (1)
* then the node responding is an authority for
* the domain name.
*
* End nodes responding to queries always set
* this bit in responses.
*
*/
/*
* 4.2.1.2. QUESTION SECTION
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / QUESTION_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | QUESTION_TYPE | QUESTION_CLASS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Field Description
*
* QUESTION_NAME The compressed name representation of the
* NetBIOS name for the request.
*
* QUESTION_TYPE The type of request. The values for this field
* are specified for each request.
*
* QUESTION_CLASS The class of the request. The values for this
* field are specified for each request.
*
* QUESTION_TYPE is defined as:
*
* Symbol Value Description:
*
* NB 0x0020 NetBIOS general Name Service Resource Record
* NBSTAT 0x0021 NetBIOS NODE STATUS Resource Record (See NODE
* STATUS REQUEST)
*
* QUESTION_CLASS is defined as:
*
* Symbol Value Description:
*
* IN 0x0001 Internet class
*/
#define QUESTION_TYPE_NETBIOS_GENERAL 0x20
#define QUESTION_TYPE_NETBIOS_STATUS 0x21
#define QUESTION_CLASS_INTERNET 0x0001
/*
*
* 4.2.1.3. RESOURCE RECORD
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | RR_TYPE | RR_CLASS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | RDLENGTH | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* / /
* / RDATA /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Field Description
*
* RR_NAME The compressed name representation of the
* NetBIOS name corresponding to this resource
* record.
*
* RR_TYPE Resource record type code
*
* RR_CLASS Resource record class code
*
* TTL The Time To Live of a the resource record's
* name.
*
* RDLENGTH Unsigned 16 bit integer that specifies the
* number of bytes in the RDATA field.
*
* RDATA RR_CLASS and RR_TYPE dependent field. Contains
* the resource information for the NetBIOS name.
*
* RESOURCE RECORD RR_TYPE field definitions:
*
* Symbol Value Description:
*
* A 0x0001 IP address Resource Record (See REDIRECT NAME
* QUERY RESPONSE)
* NS 0x0002 Name Server Resource Record (See REDIRECT
* NAME QUERY RESPONSE)
* NULL 0x000A NULL Resource Record (See WAIT FOR
* ACKNOWLEDGEMENT RESPONSE)
* NB 0x0020 NetBIOS general Name Service Resource Record
* (See NB_FLAGS and NB_ADDRESS, below)
* NBSTAT 0x0021 NetBIOS NODE STATUS Resource Record (See NODE
* STATUS RESPONSE)
*/
#define RR_TYPE_IP_ADDRESS_RESOURCE 0x0001
#define RR_TYPE_NAME_SERVER_RESOURCE 0x0002
#define RR_TYPE_NULL_RESOURCE 0x000A
#define RR_TYPE_NETBIOS_RESOURCE 0x0020
#define RR_TYPE_NETBIOS_STATUS 0x0021
/*
*
* RESOURCE RECORD RR_CLASS field definitions:
*
* Symbol Value Description:
*
* IN 0x0001 Internet class
*/
#define RR_CLASS_INTERNET_CLASS 0x0001
/*
*
* NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of
* "NB":
*
* 1 1 1 1 1 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | G | ONT | RESERVED |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
* Symbol Bit(s) Description:
*
* RESERVED 3-15 Reserved for future use. Must be zero (0).
* ONT 1,2 Owner Node Type:
* 00 = B node
* 01 = P node
* 10 = M node
* 11 = Reserved for future use
* For registration requests this is the
* claimant's type.
* For responses this is the actual owner's
* type.
*
* G 0 Group Name Flag.
* If one (1) then the RR_NAME is a GROUP
* NetBIOS name.
* If zero (0) then the RR_NAME is a UNIQUE
* NetBIOS name.
*
* The NB_ADDRESS field of the RESOURCE RECORD RDATA field for
* RR_TYPE of "NB" is the IP address of the name's owner.
*
*/
#define RR_FLAGS_NB_ONT_MASK 0x6000
#define RR_FLAGS_NB_ONT_B_NODE 0x0000
#define RR_FLAGS_NB_ONT_P_NODE 0x2000
#define RR_FLAGS_NB_ONT_M_NODE 0x4000
#define RR_FLAGS_NB_ONT_RESERVED 0x6000
#define RR_FLAGS_NB_GROUP_NAME 0x8000
/*
* smb_netbios_send_rcv
*
* This function sends the given NetBIOS packet to the given
* address and get back the response. If send operation is not
* successful, it's repeated 'retries' times.
*
* Returns:
* 0 Unsuccessful send operation; no reply
* 1 Got reply
*/
static int
struct name_packet *packet,
{
unsigned short tid;
int rc;
return (0);
return (1);
if (rc != 0)
return (0);
}
}
return (0);
}
/*
* 4.2.2. NAME REGISTRATION REQUEST
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |0| 0x5 |0|0|1|0|0 0|B| 0x0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0001 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0001 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / QUESTION_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0006 | NB_FLAGS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB_ADDRESS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Since the RR_NAME is the same name as the QUESTION_NAME, the
* RR_NAME representation must use pointers to the QUESTION_NAME
* name's labels to guarantee the length of the datagram is less
* than the maximum 576 bytes. See section above on name formats
* and also page 31 and 32 of RFC 883, Domain Names - Implementation
* and Specification, for a complete description of compressed name
* label pointers.
*/
static int
struct resource_record *additional)
{
int gotreply = 0;
struct addr_entry *destination;
struct name_packet packet;
unsigned char type;
" non-local name");
return (-1);
}
if (bcast_num == 0)
return (0);
} else {
if (nbns_num == 0)
return (0);
}
for (i = 0; i < addr_num; i++) {
/*
* Only register with the Primary WINS server,
* unless we got no reply.
*/
break;
if (rc == 1)
gotreply = 1;
}
return (gotreply);
}
/*
*
* 4.2.4. NAME REFRESH REQUEST
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |0| 0x8 |0|0|0|0|0 0|B| 0x0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0001 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0001 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / QUESTION_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0006 | NB_FLAGS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB_ADDRESS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/*ARGSUSED*/
static int
{
int rc = 0;
int gotreply = 0;
struct addr_entry *addr;
struct addr_entry *destination;
struct name_packet packet;
unsigned char type;
return (-1);
}
switch (bcast) {
case BROADCAST :
if (bcast_num == 0)
return (-1);
break;
case UNICAST :
if (nbns_num == 0)
return (-1);
break;
default:
/*
* the value of addr_num is irrelvant here, because
* the code is going to do special_process so it doesn't
* need the addr_num. We set a value here just to avoid
* compiler warning.
*/
addr_num = 0;
q_addrs = 1;
break;
}
if (q_addrs)
goto special_process;
for (i = 0; i < addr_num; i++) {
if (rc == 1)
gotreply = 1;
}
return (gotreply);
addr = destination;
do {
if (rc == 1)
gotreply = 1;
} while (addr != destination);
return (gotreply);
}
/*
* 4.2.5. POSITIVE NAME REGISTRATION RESPONSE
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| 0x0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0001 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0006 | NB_FLAGS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB_ADDRESS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*
*
* 4.2.6. NEGATIVE NAME REGISTRATION RESPONSE
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| RCODE |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0001 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0006 | NB_FLAGS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB_ADDRESS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* RCODE field values:
*
* Symbol Value Description:
*
* FMT_ERR 0x1 Format Error. Request was invalidly
* formatted.
* SRV_ERR 0x2 Server failure. Problem with NAME, cannot
* process name.
* IMP_ERR 0x4 Unsupported request error. Allowable only
* for challenging NAME when gets an Update type
* registration request.
* RFS_ERR 0x5 Refused error. For policy reasons server
* will not register this name from this host.
* ACT_ERR 0x6 Active error. Name is owned by another node.
* CFT_ERR 0x7 Name in conflict error. A UNIQUE name is
* owned by more than one node.
*/
static int
{
struct name_packet packet;
struct resource_record answer;
(rcode & NAME_RCODE_MASK);
}
/*
* 4.2.9. NAME RELEASE REQUEST & DEMAND
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |0| 0x6 |0|0|0|0|0 0|B| 0x0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0001 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0001 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / QUESTION_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x00000000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0006 | NB_FLAGS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB_ADDRESS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Since the RR_NAME is the same name as the QUESTION_NAME, the
* RR_NAME representation must use label string pointers to the
* QUESTION_NAME labels to guarantee the length of the datagram is
* less than the maximum 576 bytes. This is the same condition as
* with the NAME REGISTRATION REQUEST.
*/
static int
{
int gotreply = 0;
int i, rc;
int addr_num;
struct addr_entry *destination;
struct name_packet packet;
if (bcast_num == 0)
return (-1);
} else {
if (nbns_num == 0)
return (-1);
}
for (i = 0; i < addr_num; i++) {
if (rc == 1)
gotreply = 1;
}
return (gotreply);
}
/*
* 4.2.10. POSITIVE NAME RELEASE RESPONSE
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |1| 0x6 |1|0|0|0|0 0|0| 0x0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0001 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0006 | NB_FLAGS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB_ADDRESS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*
* 4.2.11. NEGATIVE NAME RELEASE RESPONSE
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |1| 0x6 |1|0|0|0|0 0|0| RCODE |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0001 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0006 | NB_FLAGS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB_ADDRESS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* RCODE field values:
*
* Symbol Value Description:
*
* FMT_ERR 0x1 Format Error. Request was invalidly
* formatted.
*
* SRV_ERR 0x2 Server failure. Problem with NAME, cannot
* process name.
*
* RFS_ERR 0x5 Refused error. For policy reasons server
* will not release this name from this host.
*
* ACT_ERR 0x6 Active error. Name is owned by another node.
* Only that node may release it. A NetBIOS
* Name Server can optionally allow a node to
* release a name it does not own. This would
* facilitate detection of inactive names for
* nodes that went down silently.
*/
static int
/* LINTED - E_STATIC_UNUSED */
{
struct name_packet packet;
struct resource_record answer;
}
/*
*
* 4.2.12. NAME QUERY REQUEST
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |0| 0x0 |0|0|1|0|0 0|B| 0x0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0001 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / QUESTION_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static int
{
int rc = 0;
unsigned short tid;
struct addr_entry *destination;
struct name_packet packet;
int i, addr_num;
if (bcast_num == 0)
return (-1);
} else {
if (nbns_num == 0)
return (-1);
}
for (i = 0; i < addr_num; i++) {
break;
if (smb_send_name_service_packet(&destination[i],
&packet) >= 0) {
&destination[i],
break;
}
}
}
return (rc);
}
/*
*
* 4.2.13. POSITIVE NAME QUERY RESPONSE
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |1| 0x0 |1|T|1|?|0 0|0| 0x0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0001 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB (0x0020) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | RDLENGTH | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* | |
* / ADDR_ENTRY ARRAY /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* The ADDR_ENTRY ARRAY a sequence of zero or more ADDR_ENTRY
* records. Each ADDR_ENTRY record represents an owner of a name.
* For group names there may be multiple entries. However, the list
* may be incomplete due to packet size limitations. Bit 22, "T",
* will be set to indicate truncated data.
*
* Each ADDR_ENTRY has the following format:
*
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB_FLAGS | NB_ADDRESS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NB_ADDRESS (continued) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*
*
* 4.2.14. NEGATIVE NAME QUERY RESPONSE
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |1| 0x0 |1|0|1|?|0 0|0| RCODE |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* / /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NULL (0x000A) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x00000000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* RCODE field values:
*
* Symbol Value Description
*
* FMT_ERR 0x1 Format Error. Request was invalidly
* formatted.
* SRV_ERR 0x2 Server failure. Problem with NAME, cannot
* process name.
* NAM_ERR 0x3 Name Error. The name requested does not
* exist.
* IMP_ERR 0x4 Unsupported request error. Allowable only
* for challenging NAME when gets an Update type
* registration request.
* RFS_ERR 0x5 Refused error. For policy reasons server
* will not register this name from this host.
*/
static int
unsigned short rcode)
{
struct addr_entry *raddr;
struct name_packet packet;
struct resource_record answer;
unsigned short attr;
unsigned char data[MAX_DATAGRAM_LENGTH];
if (rcode) {
} else {
do {
}
}
/*
* 4.2.18. NODE STATUS RESPONSE
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_TRN_ID |1| 0x0 |1|0|0|0|0 0|0| 0x0 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0001 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x0000 | 0x0000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / RR_NAME /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NBSTAT (0x0021) | IN (0x0001) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0x00000000 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | RDLENGTH | NUM_NAMES | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | |
* + +
* / NODE_NAME ARRAY /
* + +
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* + +
* / STATISTICS /
* + +
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* The NODE_NAME ARRAY is an array of zero or more NUM_NAMES entries
* of NODE_NAME records. Each NODE_NAME entry represents an active
* name in the same NetBIOS scope as the requesting name in the
* local name table of the responder. RR_NAME is the requesting
* name.
*
* NODE_NAME Entry:
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +--- ---+
* | |
* +--- NETBIOS FORMAT NAME ---+
* | |
* +--- ---+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NAME_FLAGS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* The NAME_FLAGS field:
*
* 1 1 1 1 1 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | G | ONT |DRG|CNF|ACT|PRM| RESERVED |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
* The NAME_FLAGS field is defined as:
*
* Symbol Bit(s) Description:
*
* RESERVED 7-15 Reserved for future use. Must be zero (0).
* PRM 6 Permanent Name Flag. If one (1) then entry
* is for the permanent node name. Flag is zero
* (0) for all other names.
* ACT 5 Active Name Flag. All entries have this flag
* set to one (1).
* CNF 4 Conflict Flag. If one (1) then name on this
* node is in conflict.
* DRG 3 Deregister Flag. If one (1) then this name
* is in the process of being deleted.
* ONT 1,2 Owner Node Type:
* 00 = B node
* 01 = P node
* 10 = M node
* 11 = Reserved for future use
* G 0 Group Name Flag.
* If one (1) then the name is a GROUP NetBIOS
* name.
* If zero (0) then it is a UNIQUE NetBIOS name.
*/
#define NAME_FLAGS_PERMANENT_NAME 0x0200
#define NAME_FLAGS_ACTIVE_NAME 0x0400
#define NAME_FLAGS_CONFLICT 0x0800
#define NAME_FLAGS_DEREGISTER 0x1000
#define NAME_FLAGS_ONT_MASK 0x6000
#define NAME_FLAGS_ONT_B_NODE 0x0000
#define NAME_FLAGS_ONT_P_NODE 0x2000
#define NAME_FLAGS_ONT_M_NODE 0x4000
#define NAME_FLAGS_ONT_RESERVED 0x6000
#define NAME_FLAGS_GROUP_NAME 0x8000
/*
* STATISTICS Field of the NODE STATUS RESPONSE:
*
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | UNIT_ID (Unique unit ID) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | UNIT_ID,continued | JUMPERS | TEST_RESULT |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | VERSION_NUMBER | PERIOD_OF_STATISTICS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_OF_CRCs | NUMBER_ALIGNMENT_ERRORS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_OF_COLLISIONS | NUMBER_SEND_ABORTS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_GOOD_SENDS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_GOOD_RECEIVES |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_RETRANSMITS | NUMBER_NO_RESOURCE_CONDITIONS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | NUMBER_FREE_COMMAND_BLOCKS | TOTAL_NUMBER_COMMAND_BLOCKS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |MAX_TOTAL_NUMBER_COMMAND_BLOCKS| NUMBER_PENDING_SESSIONS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MAX_NUMBER_PENDING_SESSIONS | MAX_TOTAL_SESSIONS_POSSIBLE |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SESSION_DATA_PACKET_SIZE |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define MAX_NETBIOS_REPLY_DATA_SIZE 500
static int
struct name_packet *original_packet)
{
struct name_packet packet;
struct resource_record answer;
unsigned char *scan;
unsigned char *scan_end;
unsigned char data[MAX_NETBIOS_REPLY_DATA_SIZE];
if (smb_nic_is_same_subnet(&ipaddr))
else
net_ipaddr = 0;
while (!scan_done) {
break;
}
if (net_ipaddr != 0) {
struct sockaddr_in *s_in;
int s;
/* LINTED - E_BAD_PTR_CAST_ALIGN */
} else {
}
(void) close(s);
} else {
}
scan += 6;
break;
}
scan += 26;
break;
}
break;
}
break;
}
break;
}
break;
}
break;
}
break;
}
break;
}
break;
}
}
}
/*
*
* 5.1. NAME SERVICE PROTOCOLS
*
* A REQUEST packet is always sent to the well known UDP port -
* NAME_SERVICE_UDP_PORT. The destination address is normally
* either the IP broadcast address or the address of the NAME - the
* address of the NAME server it set up at initialization time. In
* rare cases, a request packet will be sent to an end node, e.g. a
* NAME QUERY REQUEST sent to "challenge" a node.
*
* A RESPONSE packet is always sent to the source UDP port and
* source IP address of the request packet.
*
* A DEMAND packet must always be sent to the well known UDP port -
* NAME_SERVICE_UDP_PORT. There is no restriction on the target IP
* address.
*
* Terms used in this section:
*
* tid - Transaction ID. This is a value composed from
* the requestor's IP address and a unique 16 bit
* value generated by the originator of the
* transaction.
*/
/*
*
* 5.1.1. B-NODE ACTIVITY
*
* 5.1.1.1. B-NODE ADD NAME
*
* PROCEDURE add_name(name)
*
* (*
* * Host initiated processing for a B node
* *)
* BEGIN
*
* REPEAT
*
* (* build name service packet *)
*
* ONT = B_NODE; (* broadcast node *)
* G = UNIQUE; (* unique name *)
* TTL = 0;
*
* broadcast NAME REGISTRATION REQUEST packet;
*
* (*
* * remote node(s) will send response packet
* * if applicable
* *)
* pause(BCAST_REQ_RETRY_TIMEOUT);
*
* UNTIL response packet is received or
* retransmit count has been exceeded
*
* IF no response packet was received THEN
* BEGIN (* no response *)
* (*
* * Build packet
* *)
*
* ONT = B_NODE; (* broadcast node *)
* G = UNIQUE; (* unique name *)
* TTL = 0;
*
* (*
* * Let other nodes known you have the name
* *)
*
* broadcast NAME UPDATE REQUEST packet;
* (* name can be added to local name table *)
* return success;
* END (* no response *)
* ELSE
* BEGIN (* got response *)
*
* (*
* * Match return transaction id
* * against tid sent in request
* *)
*
* IF NOT response tid = request tid THEN
* BEGIN
* ignore response packet;
* END
* ELSE
* CASE packet type OF
*
* NEGATIVE NAME REGISTRATION RESPONSE:
*
* return failure; (* name cannot be added *)
*
* POSITIVE NAME REGISTRATION RESPONSE:
* END-NODE CHALLENGE NAME REGISTRATION RESPONSE:
*
* (*
* * B nodes should normally not get this
* * response.
* *)
*
* ignore packet;
* END (* case *);
* END (* got response *)
* END (* procedure *)
*
*
*
* 5.1.1.2. B-NODE ADD_GROUP NAME
*
* PROCEDURE add_group_name(name)
*
* (*
* * Host initiated processing for a B node
* *)
*
* BEGIN
* (*
* * same as for a unique name with the
* * exception that the group bit (G) must
* * be set in the request packets.
* *)
*
* ...
* G = GROUP;
* ...
* ...
*
* (*
* * broadcast request ...
* *)
*
*
* END
*/
static int
{
struct name_question question;
struct resource_record additional;
unsigned char data[8];
unsigned short attr;
struct addr_entry *addr;
int rc = 0;
do {
/* build name service packet */
/*
* question.name->attributes |= NAME_NB_FLAGS_ONT_B;
* This is commented because NAME_NB_FLAGS_ONT_B is 0
*/
additional.ttl = 0;
sizeof (uint32_t));
&additional);
return (rc);
}
/*
* 5.1.1.3. B-NODE FIND_NAME
*
* PROCEDURE find_name(name)
*
* (*
* * Host initiated processing for a B node
* *)
*
* BEGIN
*
* REPEAT
* (*
* * build packet
* *)
* ONT = B;
* TTL = 0;
* G = DONT CARE;
* raddr = raddr->forw;
*
* broadcast NAME QUERY REQUEST packet;
* (*
* * a node might send response packet
* *)
*
* pause(BCAST_REQ_RETRY_TIMEOUT);
* UNTIL response packet received OR
* max transmit threshold exceeded
*
* IF no response packet received THEN
* return failure;
* ELSE
* IF NOT response tid = request tid THEN
* ignore packet;
* ELSE
* CASE packet type OF
* POSITIVE NAME QUERY RESPONSE:
* (*
* * Start a timer to detect conflict.
* *
* * Be prepared to detect conflict if
* * any more response packets are received.
* *
* *)
*
* save response as authoritative response;
* start_timer(CONFLICT_TIMER);
* return success;
*
* NEGATIVE NAME QUERY RESPONSE:
* REDIRECT NAME QUERY RESPONSE:
*
* (*
* * B Node should normally not get either
* * response.
* *)
*
* ignore response packet;
*
* END (* case *)
* END (* procedure *)
*/
static int
{
struct name_question question;
}
/*
* 5.1.1.4. B NODE NAME RELEASE
*
* PROCEDURE delete_name (name)
* BEGIN
*
* REPEAT
*
* (*
* * build packet
* *)
* ...
*
* (*
* * send request
* *)
*
* broadcast NAME RELEASE REQUEST packet;
*
* (*
* * no response packet expected
* *)
*
* pause(BCAST_REQ_RETRY_TIMEOUT);
*
* UNTIL retransmit count has been exceeded
* END (* procedure *)
*/
static int
{
struct name_question question;
struct resource_record additional;
struct addr_entry *raddr;
unsigned char data[MAX_DATAGRAM_LENGTH];
/* build packet */
additional.ttl = 0;
additional.rdlength = 0;
do {
&question, &additional));
}
/*
*
* 5.1.2. P-NODE ACTIVITY
*
* All packets sent or received by P nodes are unicast UDP packets.
* A P node sends name service requests to the NAME node that is
* specified in the P-node configuration.
*
* 5.1.2.1. P-NODE ADD_NAME
*
* PROCEDURE add_name(name)
*
* (*
* * Host initiated processing for a P node
* *)
*
* BEGIN
*
* REPEAT
* (*
* * build packet
* *)
*
* ONT = P;
* G = UNIQUE;
* ...
*
* (*
* * send request
* *)
*
* unicast NAME REGISTRATION REQUEST packet;
*
* (*
* * NAME will send response packet
* *)
*
* IF receive a WACK RESPONSE THEN
* pause(time from TTL field of response);
* ELSE
* pause(UCAST_REQ_RETRY_TIMEOUT);
* UNTIL response packet is received OR
* retransmit count has been exceeded
*
* IF no response packet was received THEN
* BEGIN (* no response *)
* (*
* * NAME is down. Cannot claim name.
* *)
*
* return failure; (* name cannot be claimed *)
* END (* no response *)
* ELSE
* BEGIN (* response *)
* IF NOT response tid = request tid THEN
* BEGIN
* (* Packet may belong to another transaction *)
* ignore response packet;
* END
* ELSE
* CASE packet type OF
*
* POSITIVE NAME REGISTRATION RESPONSE:
*
* (*
* * name can be added
* *)
*
* adjust refresh timeout value, TTL, for this name;
* return success; (* name can be added *)
*
* NEGATIVE NAME REGISTRATION RESPONSE:
* return failure; (* name cannot be added *)
*
* END-NODE CHALLENGE REGISTRATION REQUEST:
* BEGIN (* end node challenge *)
*
* (*
* * The response packet has in it the
* * address of the presumed owner of the
* * name. Challenge that owner.
* * If owner either does not
* * respond or indicates that he no longer
* * owns the name, claim the name.
* * Otherwise, the name cannot be claimed.
* *
* *)
*
* REPEAT
* (*
* * build packet
* *)
* ...
*
* unicast NAME QUERY REQUEST packet to the
* address contained in the END NODE
* CHALLENGE RESPONSE packet;
*
* (*
* * remote node may send response packet
* *)
*
* pause(UCAST_REQ_RETRY_TIMEOUT);
*
* UNTIL response packet is received or
* retransmit count has been exceeded
* IF no response packet is received OR
* NEGATIVE NAME QUERY RESPONSE packet
* received THEN
* BEGIN (* update *)
*
* (*
* * name can be claimed
* *)
*
* REPEAT
*
* (*
* * build packet
* *)
* ...
*
* unicast NAME UPDATE REQUEST to NAME;
*
* (*
* * NAME node will send response packet
* *)
*
* IF receive a WACK RESPONSE THEN
* pause(time from TTL field of response);
* ELSE
* pause(UCAST_REQ_RETRY_TIMEOUT);
* UNTIL response packet is received or
* retransmit count has been exceeded
* IF no response packet received THEN
* BEGIN (* no response *)
*
* (*
* * name could not be claimed
* *)
*
* return failure;
* END (* no response *)
* ELSE
* CASE packet type OF
* POSITIVE NAME REGISTRATION RESPONSE:
* (*
* * add name
* *)
* return success;
* NEGATIVE NAME REGISTRATION RESPONSE:
*
* (*
* * you lose ...
* *)
* return failure;
* END (* case *)
* END (* update *)
* ELSE
*
* (*
* * received a positive response to the "challenge"
* * Remote node still has name
* *)
*
* return failure;
* END (* end node challenge *)
* END (* response *)
* END (* procedure *)
*
*
* 5.1.2.2. P-NODE ADD GROUP NAME
*
* PROCEDURE add_group_name(name)
*
* (*
* * Host initiated processing for a P node
* *)
*
* BEGIN
* (*
* * same as for a unique name, except that the
* * request packet must indicate that a
* * group name claim is being made.
* *)
*
* ...
* G = GROUP;
* ...
*
* (*
* * send packet
* *)
* ...
*
*
* END
*/
static int
{
struct name_question question;
struct resource_record additional;
unsigned char data[8];
unsigned short attr;
struct addr_entry *addr;
int rc = 0;
/* build packet */
do {
additional.ttl = 0;
sizeof (uint32_t));
&additional);
return (rc);
}
static int
{
struct name_question question;
struct resource_record additional;
unsigned char data[8];
unsigned short attr;
struct addr_entry *addr;
int rc = 0;
/* build packet */
do {
additional.ttl = 0;
sizeof (uint32_t));
&additional, 1);
return (rc);
}
/*
* 5.1.2.3. P-NODE FIND NAME
*
* PROCEDURE find_name(name)
*
* (*
* * Host initiated processing for a P node
* *)
*
* BEGIN
* REPEAT
* (*
* * build packet
* *)
*
* ONT = P;
* G = DONT CARE;
*
* unicast NAME QUERY REQUEST packet;
*
* (*
* * a NAME node might send response packet
* *)
*
* IF receive a WACK RESPONSE THEN
* pause(time from TTL field of response);
* ELSE
* pause(UCAST_REQ_RETRY_TIMEOUT);
* UNTIL response packet received OR
* max transmit threshold exceeded
*
* IF no response packet received THEN
* return failure;
* ELSE
* IF NOT response tid = request tid THEN
* ignore packet;
* ELSE
* CASE packet type OF
* POSITIVE NAME QUERY RESPONSE:
* return success;
*
* REDIRECT NAME QUERY RESPONSE:
*
* (*
* * NAME node wants this end node
* * to use some other NAME node
* * to resolve the query.
* *)
*
* repeat query with NAME address
* in the response packet;
* NEGATIVE NAME QUERY RESPONSE:
* return failure;
*
* END (* case *)
* END (* procedure *)
*/
static int
{
struct name_question question;
/*
* Host initiated processing for a P node
*/
}
/*
* 5.1.2.4. P-NODE DELETE_NAME
*
* PROCEDURE delete_name (name)
*
* (*
* * Host initiated processing for a P node
* *)
*
* BEGIN
*
* REPEAT
*
* (*
* * build packet
* *)
* ...
*
* (*
* * send request
* *)
*
* unicast NAME RELEASE REQUEST packet;
* IF receive a WACK RESPONSE THEN
* pause(time from TTL field of response);
* ELSE
* pause(UCAST_REQ_RETRY_TIMEOUT);
* UNTIL retransmit count has been exceeded
* or response been received
*
* IF response has been received THEN
* CASE packet type OF
* POSITIVE NAME RELEASE RESPONSE:
* return success;
* NEGATIVE NAME RELEASE RESPONSE:
*
* (*
* * NAME does want node to delete this
* * name !!!
* *)
*
* return failure;
* END (* case *)
* END (* procedure *)
*/
static int
{
struct name_question question;
struct resource_record additional;
struct addr_entry *raddr;
unsigned char data[MAX_DATAGRAM_LENGTH];
/* build packet */
additional.ttl = 0;
additional.rdlength = 0;
do {
&question, &additional);
return (1);
}
/*
* 5.1.3. M-NODE ACTIVITY
*
* M nodes behavior is similar to that of P nodes with the addition
* of some B node-like broadcast actions. M node name service
* proceeds in two steps:
*
* 1.Use broadcast UDP based name service. Depending on the
* operation, goto step 2.
*
* 2.Use directed UDP name service.
*
* The following code for M nodes is exactly the same as for a P
* node, with the exception that broadcast operations are done
* before P type operation is attempted.
*
* 5.1.3.1. M-NODE ADD NAME
*
* PROCEDURE add_name(name)
*
* (*
* * Host initiated processing for a M node
* *)
*
* BEGIN
*
* (*
* * check if name exists on the
* * broadcast area
* *)
* REPEAT
* (* build packet *)
*
* ....
* broadcast NAME REGISTRATION REQUEST packet;
* pause(BCAST_REQ_RETRY_TIMEOUT);
*
* UNTIL response packet is received or
* retransmit count has been exceeded
*
* IF valid response received THEN
* BEGIN
* (* cannot claim name *)
*
* return failure;
* END
*
* (*
* * No objections received within the
* * broadcast area.
* * Send request to name server.
* *)
*
* REPEAT
* (*
* * build packet
* *)
*
* ONT = M;
* ...
*
* unicast NAME REGISTRATION REQUEST packet;
*
* (*
* * remote NAME will send response packet
* *)
*
* IF receive a WACK RESPONSE THEN
* pause(time from TTL field of response);
* ELSE
* pause(UCAST_REQ_RETRY_TIMEOUT);
*
* UNTIL response packet is received or
* retransmit count has been exceeded
*
* IF no response packet was received THEN
* BEGIN (* no response *)
* (*
* * NAME is down. Cannot claim name.
* *)
* return failure; (* name cannot be claimed *)
* END (* no response *)
* ELSE
* BEGIN (* response *)
* IF NOT response tid = request tid THEN
* BEGIN
* ignore response packet;
* END
* ELSE
* CASE packet type OF
* POSITIVE NAME REGISTRATION RESPONSE:
*
* (*
* * name can be added
* *)
*
* adjust refresh timeout value, TTL;
* return success; (* name can be added *)
*
* NEGATIVE NAME REGISTRATION RESPONSE:
* return failure; (* name cannot be added *)
*
* END-NODE CHALLENGE REGISTRATION REQUEST:
* BEGIN (* end node challenge *)
*
* (*
* * The response packet has in it the
* * address of the presumed owner of the
* * name. Challenge that owner.
* * If owner either does not
* * respond or indicates that he no longer
* * owns the name, claim the name.
* * Otherwise, the name cannot be claimed.
* *
* *)
*
* REPEAT
* (*
* * build packet
* *)
* ...
*
* (*
* * send packet to address contained in the
* * response packet
* *)
*
* unicast NAME QUERY REQUEST packet;
*
* (*
* * remote node may send response packet
* *)
*
* pause(UCAST_REQ_RETRY_TIMEOUT);
*
* UNTIL response packet is received or
* retransmit count has been exceeded
* IF no response packet is received THEN
* BEGIN (* no response *)
*
* (*
* * name can be claimed
* *)
* REPEAT
*
* (*
* * build packet
* *)
* ...
*
* unicast NAME UPDATE REQUEST to NAME;
*
* (*
* * NAME node will send response packet
* *)
*
* IF receive a WACK RESPONSE THEN
* pause(time from TTL field of response);
* ELSE
* pause(UCAST_REQ_RETRY_TIMEOUT);
*
* UNTIL response packet is received or
* retransmit count has been exceeded
* IF no response packet received THEN
* BEGIN (* no response *)
*
* (*
* * name could not be claimed
* *)
*
* return failure;
* END (* no response *)
* ELSE
* CASE packet type OF
* POSITIVE NAME REGISTRATION RESPONSE:
* (*
* * add name
* *)
*
* return success;
* NEGATIVE NAME REGISTRATION RESPONSE:
* (*
* * you lose ...
* *)
*
* return failure;
* END (* case *)
* END (* no response *)
* ELSE
* IF NOT response tid = request tid THEN
* BEGIN
* ignore response packet;
* END
*
* (*
* * received a response to the "challenge"
* * packet
* *)
*
* CASE packet type OF
* POSITIVE NAME QUERY:
*
* (*
* * remote node still has name.
* *)
*
* return failure;
* NEGATIVE NAME QUERY:
*
* (*
* * remote node no longer has name
* *)
*
* return success;
* END (* case *)
* END (* end node challenge *)
* END (* case *)
* END (* response *)
* END (* procedure *)
*
*
* 5.1.3.2. M-NODE ADD GROUP NAME
*
* PROCEDURE add_group_name(name)
*
* (*
* * Host initiated processing for a P node
* *)
*
* BEGIN
* (*
* * same as for a unique name, except that the
* * request packet must indicate that a
* * group name claim is being made.
* *)
*
* ...
* G = GROUP;
* ...
*
* (*
* * send packet
* *)
* ...
*
*
* END
*/
static int
{
if (smb_name_Bnode_add_name(name) > 0) {
if (nbns_num == 0)
return (1); /* No name server configured */
return (smb_name_Pnode_add_name(name));
}
return (-1);
}
static int
{
if (nbns_num > 0) {
return (1);
}
return (smb_name_Bnode_add_name(name));
}
/*
* 5.1.3.3. M-NODE FIND NAME
*
* PROCEDURE find_name(name)
*
* (*
* * Host initiated processing for a M node
* *)
*
* BEGIN
* (*
* * check if any node on the broadcast
* * area has the name
* *)
*
* REPEAT
* (* build packet *)
* ...
*
* broadcast NAME QUERY REQUEST packet;
* pause(BCAST_REQ_RETRY_TIMEOUT);
* UNTIL response packet received OR
* max transmit threshold exceeded
*
* IF valid response received THEN
* BEGIN
* save response as authoritative response;
* start_timer(CONFLICT_TIMER);
* return success;
* END
*
* (*
* * no valid response on the b'cast segment.
* * Try the name server.
* *)
*
* REPEAT
* (*
* * build packet
* *)
*
* ONT = M;
* G = DONT CARE;
*
* unicast NAME QUERY REQUEST packet to NAME;
*
* (*
* * a NAME node might send response packet
* *)
*
* IF receive a WACK RESPONSE THEN
* pause(time from TTL field of response);
* ELSE
* pause(UCAST_REQ_RETRY_TIMEOUT);
* UNTIL response packet received OR
* max transmit threshold exceeded
*
* IF no response packet received THEN
* return failure;
* ELSE
* IF NOT response tid = request tid THEN
* ignore packet;
* ELSE
* CASE packet type OF
* POSITIVE NAME QUERY RESPONSE:
* return success;
*
* REDIRECT NAME QUERY RESPONSE:
*
* (*
* * NAME node wants this end node
* * to use some other NAME node
* * to resolve the query.
* *)
*
* repeat query with NAME address
* in the response packet;
* NEGATIVE NAME QUERY RESPONSE:
* return failure;
*
* END (* case *)
* END (* procedure *)
*/
static int
{
return (1);
if (nbns_num == 0)
return (1); /* No name server configured */
return (smb_name_Pnode_find_name(name));
}
static int
{
if (nbns_num > 0)
return (1);
return (smb_name_Bnode_find_name(name));
}
/*
* 5.1.3.4. M-NODE DELETE NAME
*
* PROCEDURE delete_name (name)
*
* (*
* * Host initiated processing for a P node
* *)
*
* BEGIN
* (*
* * First, delete name on NAME
* *)
*
* REPEAT
*
* (*
* * build packet
* struct addr_entry *addr;
* *)
* ...
*
* (*
* * send request
* *)
*
* unicast NAME RELEASE REQUEST packet to NAME;
*
* IF receive a WACK RESPONSE THEN
* pause(time from TTL field of response);
* ELSE
* pause(UCAST_REQ_RETRY_TIMEOUT);
* UNTIL retransmit count has been exceeded
* or response been received
*
* IF response has been received THEN
* CASE packet type OF
* POSITIVE NAME RELEASE RESPONSE:
* (*
* * Deletion of name on b'cast segment is deferred
* * until after NAME has deleted the name
* *)
*
* REPEAT
* (* build packet *)
*
* ...
* broadcast NAME RELEASE REQUEST;
* pause(BCAST_REQ_RETRY_TIMEOUT);
* UNTIL rexmt threshold exceeded
*
* return success;
* NEGATIVE NAME RELEASE RESPONSE:
*
* (*
* * NAME does want node to delete this
* * name
* *)
* return failure;
* END (* case *)
* END (* procedure *)
*/
static int
{
(void) smb_name_Bnode_delete_name(name);
if (nbns_num == 0)
return (-1); /* No name server configured */
if (smb_name_Pnode_delete_name(name) > 0)
return (1);
return (-1);
}
static int
{
if (nbns_num > 0)
if (smb_name_Pnode_delete_name(name) > 0)
return (1);
return (smb_name_Bnode_delete_name(name));
}
/*
* 5.1.1.5. B-NODE INCOMING PACKET PROCESSING
*
* Following processing is done when broadcast or unicast packets
* are received at the NAME_SERVICE_UDP_PORT.
*
* PROCEDURE process_incoming_packet(packet)
*
* (*
* * Processing initiated by incoming packets for a B node
* *)
*
* BEGIN
* (*
* * Note: response packets are always sent
* * to:
* * source IP address of request packet
* * source UDP port of request packet
* *)
*
* CASE packet type OF
*
* NAME REGISTRATION REQUEST (UNIQUE):
* IF name exists in local name table THEN
* send NEGATIVE_NAME_REGISTRATION_RESPONSE ;
* NAME REGISTRATION REQUEST (GROUP):
* IF name exists in local name table THEN
* BEGIN
* IF local entry is a unique name THEN
* send NEGATIVE_NAME_REGISTRATION_RESPONSE ;
* END
* NAME QUERY REQUEST:
* IF name exists in local name table THEN
* BEGIN
* build response packet;
* send POSITIVE_NAME_QUERY_RESPONSE;
* POSITIVE NAME QUERY RESPONSE:
* IF name conflict timer is not active THEN
* BEGIN
* (*
* * timer has expired already... ignore this
* * packet
* *)
*
* return;
* END
* ELSE (* timer is active *)
* IF a response for this name has previously been
* received THEN
* BEGIN (* existing entry *)
*
* (*
* * we sent out a request packet, and
* * have already received (at least)
* * one response
* *
* * Check if conflict exists.
* * If so, send out a conflict packet.
* *
* * Note: detecting conflict does NOT
* * affect any existing sessions.
* *
* *)
*
* (*
* * Check for name conflict.
* * See "Name Conflict" in Concepts and Methods
* *)
* check saved authoritative response against
* information in this response packet;
* IF conflict detected THEN
* BEGIN
* unicast NAME CONFLICT DEMAND packet;
* IF entry exists in cache THEN
* BEGIN
* remove entry from cache;
* END
* END
* END (* existing entry *)
* ELSE
* BEGIN
* (*
* * Note: If this was the first response
* * to a name query, it would have been
* * handled in the
* * find_name() procedure.
* *)
*
* ignore packet;
* END
* NAME CONFLICT DEMAND:
* IF name exists in local name table THEN
* BEGIN
* mark name as conflict detected;
*
* (*
* * a name in the state "conflict detected"
* * does not "logically" exist on that node.
* * No further session will be accepted on
* * that name.
* * No datagrams can be sent against that name.
* * Such an entry will not be used for
* * purposes of processing incoming request
* * packets.
* * The only valid user NetBIOS operation
* * against such a name is DELETE NAME.
* *)
* END
* NAME RELEASE REQUEST:
* IF caching is being done THEN
* BEGIN
* remove entry from cache;
* END
* NAME UPDATE REQUEST:
* IF caching is being done THEN
* BEGIN
* IF entry exists in cache already,
* update cache;
* ELSE IF name is "interesting" THEN
* BEGIN
* add entry to cache;
* END
* END
*
* NODE STATUS REQUEST:
* IF name exists in local name table THEN
* BEGIN
* (*
* * send only those names that are
* * in the same scope as the scope
* * field in the request packet
* *)
*
* send NODE STATUS RESPONSE;
* END
* END
*/
static void
struct addr_entry *addr)
{
struct name_entry *name;
struct name_entry *entry;
struct name_question *question;
struct resource_record *additional;
case NAME_OPCODE_REFRESH:
/* Guard against malformed packets */
if ((question == 0) || (additional == 0))
break;
break;
}
else
break;
case NAME_OPCODE_QUERY:
/*
* This opcode covers both NAME_QUERY_REQUEST and
* NODE_STATUS_REQUEST. They can be distinguished
* based on the type of question entry.
*/
/* All query requests have to have question entry */
if (question == 0)
break;
(void) smb_send_name_query_response(addr,
}
}
else
/*
* Name of "*" may be used to force node to
* divulge status for administrative purposes
*/
entry = 0;
if (entry)
/*
* send only those names that are
* in the same scope as the scope
* field in the request packet
*/
(void) smb_send_node_status_response(addr,
packet);
}
}
break;
default:
break;
}
}
/*
* 5.1.2.5. P-NODE INCOMING PACKET PROCESSING
*
* Processing initiated by reception of packets at a P node
*
* PROCEDURE process_incoming_packet(packet)
*
* (*
* * Processing initiated by incoming packets at a P node
* *)
*
* BEGIN
* (*
* * always ignore UDP broadcast packets
* *)
*
* IF packet was sent as a broadcast THEN
* BEGIN
* ignore packet;
* return;
* END
* CASE packet type of
*
* NAME CONFLICT DEMAND:
* IF name exists in local name table THEN
* mark name as in conflict;
* return;
*
* NAME QUERY REQUEST:
* IF name exists in local name table THEN
* BEGIN (* name exists *)
*
* (*
* * build packet
* *)
* ...
*
* (*
* * send response to the IP address and port
* * number from which the request was received.
* *)
*
* send POSITIVE_NAME_QUERY_RESPONSE ;
* return;
* END (* exists *)
* ELSE
* BEGIN (* does not exist *)
*
* (*
* * send response to the requestor
* *)
*
* send NEGATIVE_NAME_QUERY_RESPONSE ;
* return;
* END (* does not exist *)
* NODE STATUS REQUEST:
* (*
* * Name of "*" may be used for force node to
* * divulge status for administrative purposes
* *)
* IF name in local name table OR name = "*" THEN
* BEGIN
* (*
* * Build response packet and
* * send to requestor node
* * Send only those names that are
* * in the same scope as the scope
* * in the request packet.
* *)
*
* send NODE_STATUS_RESPONSE;
* END
*
* NAME RELEASE REQUEST:
* (*
* * This will be received if the NAME wants to flush the
* * name from the local name table, or from the local
* * cache.
* *)
*
* IF name exists in the local name table THEN
* BEGIN
* delete name from local name table;
* inform user that name has been deleted;
* END
* END (* case *)
* END (* procedure *)
*
* (*
* * Incoming packet processing on a NS node
* *)
*
* BEGIN
* IF packet was sent as a broadcast THEN
* BEGIN
* discard packet;
* return;
* END
* CASE packet type of
*
* NAME REGISTRATION REQUEST (UNIQUE):
* IF unique name exists in data base THEN
* BEGIN (* unique name exists *)
* (*
* * NAME node may be a "passive"
* * server in that it expects the
* * end node to do the challenge
* * server. Such a NAME node is
* * called a "non-secure" server.
* * A "secure" server will do the
* * challenging before it sends
* * back a response packet.
* *)
*
* IF non-secure THEN
* BEGIN
* (*
* * build response packet
* *)
* ...
*
*
* (*
* * let end node do the challenge
* *)
*
* send END-NODE CHALLENGE NAME REGISTRATION
* RESPONSE;
* return;
* END
* ELSE
* (*
* * secure server - do the name
* * challenge operation
* *)
*
* REPEAT
* send NAME QUERY REQUEST;
* pause(UCAST_REQ_RETRY_TIMEOUT);
* UNTIL response has been received or
* retransmit count has been exceeded
* IF no response was received THEN
* BEGIN
*
* (* node down *)
*
* update data base - remove entry;
* update data base - add new entry;
* send POSITIVE NAME REGISTRATION RESPONSE;
* return;
* END
* ELSE
* BEGIN (* challenged node replied *)
* (*
* * challenged node replied with
* * a response packet
* *)
*
* CASE packet type
*
* POSITIVE NAME QUERY RESPONSE:
*
* (*
* * name still owned by the
* * challenged node
* *
* * build packet and send response
* *)
* ...
*
*
* (*
* * Note: The NAME will need to
* * keep track (based on transaction id) of
* * the IP address and port number
* * of the original requestor.
* *)
*
* send NEGATIVE NAME REGISTRATION RESPONSE;
* return;
* NEGATIVE NAME QUERY RESPONSE:
*
* update data base - remove entry;
* update data base - add new entry;
*
* (*
* * build response packet and send
* * response
* *)
* send POSITIVE NAME REGISTRATION RESPONSE;
* return;
* END (* case *)
* END (* challenged node replied *)
* END (* unique name exists in data base *)
* ELSE
* IF group name exists in data base THEN
* BEGIN (* group names exists *)
*
* (*
* * Members of a group name are NOT
* * challenged.
* * Make the assumption that
* * at least some of the group members
* * are still alive.
* * Refresh mechanism will
* * allow the NAME to detect when all
* * members of a group no longer use that
* * name
* *)
*
* send NEGATIVE NAME REGISTRATION RESPONSE;
* END (* group name exists *)
* ELSE
* BEGIN (* name does not exist *)
*
* (*
* * Name does not exist in data base
* *
* * This code applies to both non-secure
* * and secure server.
* *)
*
* update data base - add new entry;
* send POSITIVE NAME REGISTRATION RESPONSE;
* return;
* END
*
* NAME QUERY REQUEST:
* IF name exists in data base THEN
* BEGIN
* (*
* * build response packet and send to
* * requestor
* *)
* ...
*
* send POSITIVE NAME QUERY RESPONSE;
* return;
* ELSE
* BEGIN
* (*
* * build response packet and send to
* * requestor
* *)
* ...
*
* send NEGATIVE NAME QUERY RESPONSE;
* return;
* END
*
* NAME REGISTRATION REQUEST (GROUP):
* IF name exists in data base THEN
* BEGIN
* IF local entry is a unique name THEN
* BEGIN (* local is unique *)
*
* IF non-secure THEN
* BEGIN
* send END-NODE CHALLENGE NAME
* REGISTRATION RESPONSE;
* return;
* END
*
* REPEAT
* send NAME QUERY REQUEST;
* pause(UCAST_REQ_RETRY_TIMEOUT);
* UNTIL response received or
* retransmit count exceeded
* IF no response received or
* NEGATIVE NAME QUERY RESPONSE
* received THEN
* BEGIN
* update data base - remove entry;
* update data base - add new entry;
* send POSITIVE NAME REGISTRATION RESPONSE;
* return;
* END
* ELSE
* BEGIN
* (*
* * name still being held
* * by challenged node
* *)
*
* send NEGATIVE NAME REGISTRATION RESPONSE;
* END
* END (* local is unique *)
* ELSE
* BEGIN (* local is group *)
* (*
* * existing entry is a group name
* *)
*
* update data base - remove entry;
* update data base - add new entry;
* send POSITIVE NAME REGISTRATION RESPONSE;
* return;
* END (* local is group *)
* END (* names exists *)
* ELSE
* BEGIN (* does not exist *)
*
* (* name does not exist in data base *)
*
* update data base - add new entry;
* send POSITIVE NAME REGISTRATION RESPONSE;
* return;
* END (* does not exist *)
*
* NAME RELEASE REQUEST:
*
* (*
* * secure server may choose to disallow
* * a node from deleting a name
* *)
*
* update data base - remove entry;
* send POSITIVE NAME RELEASE RESPONSE;
* return;
*
* NAME UPDATE REQUEST:
*
* (*
* * End-node completed a successful challenge,
* * no update database
* *)
*
* IF secure server THEN
* send NEGATIVE NAME REGISTRATION RESPONSE;
* ELSE
* BEGIN (* new entry *)
* IF entry already exists THEN
* update data base - remove entry;
* update data base - add new entry;
* send POSITIVE NAME REGISTRATION RESPONSE;
* start_timer(TTL);
* END
*
* NAME REFRESH REQUEST:
* check for consistency;
*
* IF node not allowed to have name THEN
* BEGIN
*
* (*
* * tell end node that it can't have name
* *)
* send NEGATIVE NAME REGISTRATION RESPONSE;
* END
* ELSE
* BEGIN
*
* (*
* * send confirmation response to the
* * end node.
* *)
* send POSITIVE NAME REGISTRATION;
* start_timer(TTL);
* END
* return;
* END (* case *)
* END (* procedure *)
*/
static void
struct addr_entry *addr)
{
struct name_entry *name;
struct name_entry *entry;
struct name_question *question;
struct resource_record *additional;
/*
* always ignore UDP broadcast packets
*/
return;
}
case NAME_OPCODE_REFRESH:
/* Guard against malformed packets */
if ((question == 0) || (additional == 0))
break;
break;
}
else
(void) smb_netbios_cache_insert(name);
break;
case NAME_OPCODE_QUERY:
/*
* This opcode covers both NAME_QUERY_REQUEST and
* NODE_STATUS_REQUEST. They can be distinguished
* based on the type of question entry.
*/
/* All query requests have to have question entry */
if (question == 0)
break;
/*
* send response to the IP address and port
* number from which the request was received.
*/
(void) smb_send_name_query_response(addr,
} else {
/*
* send response to the requestor
*/
(void) smb_send_name_query_response(addr,
}
}
else
/*
* Name of "*" may be used to force node to
* divulge status for administrative purposes
*/
entry = 0;
/*
* send only those names that are
* in the same scope as the scope
* field in the request packet
*/
if (entry)
(void) smb_send_node_status_response(addr,
packet);
}
}
break;
default:
break;
}
}
/*
* 5.1.3.5. M-NODE INCOMING PACKET PROCESSING
*
* Processing initiated by reception of packets at a M node
*
* PROCEDURE process_incoming_packet(packet)
*
* (*
* * Processing initiated by incoming packets at a M node
* *)
*
* BEGIN
* CASE packet type of
*
* NAME CONFLICT DEMAND:
* IF name exists in local name table THEN
* mark name as in conflict;
* return;
*
* NAME QUERY REQUEST:
* IF name exists in local name table THEN
* BEGIN (* name exists *)
*
* (*
* * build packet
* *)
* ...
*
* (*
* * send response to the IP address and port
* * number from which the request was received.
* *)
*
* send POSITIVE NAME QUERY RESPONSE ;
* return;
* END (* exists *)
* ELSE
* BEGIN (* does not exist *)
*
* (*
* * send response to the requestor
* *)
*
* IF request NOT broadcast THEN
* (*
* * Don't send negative responses to
* * queries sent by B nodes
* *)
* send NEGATIVE NAME QUERY RESPONSE ;
* return;
* END (* does not exist *)
* NODE STATUS REQUEST:
* BEGIN
* (*
* * Name of "*" may be used to force node to
* * divulge status for administrative purposes
* *)
* IF name in local name table OR name = "*" THEN
* (*
* * Build response packet and
* * send to requestor node
* * Send only those names that are
* * in the same scope as the scope
* * in the request packet.
* *)
*
* send NODE STATUS RESPONSE;
* END
*
* NAME RELEASE REQUEST:
* (*
* * This will be received if the NAME wants to flush the
* * name from the local name table, or from the local
* * cache.
* *)
*
* IF name exists in the local name table THEN
* BEGIN
* delete name from local name table;
* inform user that name has been deleted;
* END
* NAME REGISTRATION REQUEST (UNIQUE):
* IF name exists in local name table THEN
* send NEGATIVE NAME REGISTRATION RESPONSE ;
* NAME REGISTRATION REQUEST (GROUP):
* IF name exists in local name table THEN
* BEGIN
* IF local entry is a unique name THEN
* send NEGATIVE NAME REGISTRATION RESPONSE ;
* END
* END (* case *)
* END (* procedure *)
*/
static void
struct addr_entry *addr)
{
else
}
static void
struct addr_entry *addr)
{
else
}
/*
* smb_netbios_name_tick
*
* Called once a second to handle name server timeouts.
*/
void
smb_netbios_name_tick(void)
{
struct name_entry *name;
struct name_entry *entry;
(void) smb_name_Pnode_refresh_name(name);
}
} else {
}
}
}
/*
* smb_name_find_name
*
* Lookup name cache for the given name.
* If it's not in the cache it'll send a
* name query request and then lookup the
* cache again. Note that if a name is
* returned it's locked and called MUST
* unlock it by calling smb_name_unlock_name()
*/
struct name_entry *
{
struct name_entry *result;
switch (smb_node_type) {
case 'B':
(void) smb_name_Bnode_find_name(name);
break;
case 'P':
(void) smb_name_Pnode_find_name(name);
break;
case 'M':
(void) smb_name_Mnode_find_name(name);
break;
case 'H':
default:
(void) smb_name_Hnode_find_name(name);
break;
}
return (smb_netbios_cache_lookup(name));
}
return (result);
}
void
{
}
int
{
int rc = 1;
switch (smb_node_type) {
case 'B':
break;
case 'P':
break;
case 'M':
break;
case 'H':
default:
break;
}
if (rc >= 0)
(void) smb_netbios_cache_insert(name);
return (rc);
}
int
{
int rc;
unsigned char type;
"netbios: error trying to delete non-local name");
return (-1);
}
switch (smb_node_type) {
case 'B':
break;
case 'P':
break;
case 'M':
break;
case 'H':
default:
break;
}
if (rc > 0)
return (0);
return (-1);
}
typedef struct {
struct addr_entry *addr;
char *buf;
int length;
/*
* smb_netbios_worker
*
* name service (on port 138).
*/
void *
smb_netbios_worker(void *arg)
{
struct name_packet *packet;
/* Reply packet */
free(p);
return (0);
}
/* Request packet */
switch (smb_node_type) {
case 'B':
break;
case 'P':
break;
case 'M':
break;
case 'H':
default:
break;
}
} else {
}
free(p);
return (0);
}
static void
smb_netbios_wins_config(char *ip)
{
if (ipaddr != INADDR_NONE) {
}
}
static void
{
struct name_entry *name;
int rc;
while (rc == 0) {
(void) smb_netbios_name_logf(name);
switch (smb_node_type) {
case SMB_NODETYPE_B:
(void) smb_name_Bnode_add_name(name);
break;
case SMB_NODETYPE_P:
(void) smb_name_Pnode_add_name(name);
break;
case SMB_NODETYPE_M:
(void) smb_name_Mnode_add_name(name);
break;
case SMB_NODETYPE_H:
default:
(void) smb_name_Hnode_add_name(name);
break;
}
}
}
}
void
smb_netbios_name_config(void)
{
struct name_entry name;
char wins_ip[16];
int rc;
/* Start with no broadcast addresses */
bcast_num = 0;
/* Add all of the broadcast addresses */
while (rc == 0) {
(SMB_NICF_ALIAS | SMB_NICF_NBEXCL)) {
continue;
}
}
/* Start with no WINS */
nbns_num = 0;
/* add any configured WINS */
if (smb_nic_getfirst(&ni) != 0)
return;
do {
continue;
(void) smb_netbios_cache_insert(&name);
(void) smb_netbios_cache_insert(&name);
} while (smb_nic_getnext(&ni) == 0);
}
void
{
struct name_entry *name;
(void) smb_name_delete_name(name);
}
}
void
{
}
/*
* process_incoming Function: void smb_netbios_name_service_daemon(void)
*
* Description:
*
* Put test description here.
*
* Inputs:
* Nothing
*
* Returns:
* int -> Description
*/
/*ARGSUSED*/
void *
{
struct sockaddr_in sin;
struct addr_entry *addr;
int len;
int flag = 1;
char *buf;
/*
* Initialize reply_queue
*/
if (!smb_netbios_cache_init())
return (0);
bcast_num = 0;
"smbd: Could not create AF_INET, SOCK_DGRAM, socket");
return (0);
}
sizeof (flag));
"smbd: Bind to name service port %d failed (%d)",
return (0);
}
/* Sleep for 10 sec and try again */
(void) sleep(10);
continue;
}
if ((addr = (struct addr_entry *)
malloc(sizeof (struct addr_entry))) == 0) {
/* Sleep for 10 sec and try again */
(void) sleep(10);
continue;
}
/* Sleep for 10 sec and try again */
(void) sleep(10);
continue;
}
"smbd: NETBIOS name service - recvfrom failed");
goto shutdown;
}
/* Ignore any incoming packets from myself... */
if (smb_nic_is_local(&ipaddr))
goto ignore;
/*
* Launch a netbios worker to process the received packet.
*/
worker_param = (worker_param_t *)
malloc(sizeof (worker_param_t));
if (worker_param) {
(void) pthread_attr_init(&tattr);
(void) pthread_attr_setdetachstate(&tattr,
(void) pthread_attr_destroy(&tattr);
}
}
/* this might delay shutdown, do we want to do this? */
/*
* it'll send name release requests but nobody's waiting
* for response and it'll eventually timeout.
*/
}
return (0);
}