da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or http://www.opensolaris.org/os/licensing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * NetBIOS name resolution node types.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * A B-node (broadcast node) uses broadcasts for name registration
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * and resolution. Routers typically do not forward broadcasts and
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * only computers on the local subnet will respond.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * A P-node (peer-to-peer node) uses a NetBIOS name server (WINS)
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * to resolve NetBIOS names, which allows it to work across routers.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * In order to function in a P-node environment, all computers must
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * be configured to use the NetBIOS name server because P-nodes do
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * not broadcast on the network.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * A mixed node (M-node) behaves as a B-node by default. If it cannot
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * resolve the name via broadcast then it tries a NetBIOS name server
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * lookup (P-node).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * A hybrid node (H-node) behaves as a P-node by default. If it cannot
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * resolve the name using a NetBIOS name server then it resorts to
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * broadcasts (B-node).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * NetBIOS Name Service Protocols
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * A REQUEST packet is always sent to the well known UDP port 137.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * The destination address is normally either the IP broadcast address or
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * the address of the NAME - the address of the NAME server it set up at
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * initialization time. In rare cases, a request packet will be sent to
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * an end node, e.g. a NAME QUERY REQUEST sent to "challenge" a node.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * A RESPONSE packet is always sent to the source UDP port and source IP
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * address of the request packet.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * A DEMAND packet must always be sent to the well known UDP port 137.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * There is no restriction on the target IP address.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * A transaction ID is a value composed from the requestor's IP address and
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * a unique 16 bit value generated by the originator of the transaction.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <unistd.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <syslog.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdlib.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <synch.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <errno.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <netdb.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/socket.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/sockio.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <arpa/inet.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <net/if_arp.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/libsmbns.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbns_netbios.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.1.1. HEADER
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define QUESTION_TYPE_NETBIOS_GENERAL 0x20
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define QUESTION_TYPE_NETBIOS_STATUS 0x21
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define QUESTION_CLASS_INTERNET 0x0001
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.1.3. RESOURCE RECORD
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_TYPE_IP_ADDRESS_RESOURCE 0x0001
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_TYPE_NAME_SERVER_RESOURCE 0x0002
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_TYPE_NULL_RESOURCE 0x000A
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_TYPE_NETBIOS_RESOURCE 0x0020
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_TYPE_NETBIOS_STATUS 0x0021
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RESOURCE RECORD RR_CLASS field definitions
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_CLASS_INTERNET_CLASS 0x0001
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of NB.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_FLAGS_NB_ONT_MASK 0x6000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_FLAGS_NB_ONT_B_NODE 0x0000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_FLAGS_NB_ONT_P_NODE 0x2000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_FLAGS_NB_ONT_M_NODE 0x4000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_FLAGS_NB_ONT_RESERVED 0x6000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define RR_FLAGS_NB_GROUP_NAME 0x8000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_PERMANENT_NAME 0x0200
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_ACTIVE_NAME 0x0400
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_CONFLICT 0x0800
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_DEREGISTER 0x1000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_ONT_MASK 0x6000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_ONT_B_NODE 0x0000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_ONT_P_NODE 0x2000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_ONT_M_NODE 0x4000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_ONT_RESERVED 0x6000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_FLAGS_GROUP_NAME 0x8000
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define MAX_NETBIOS_REPLY_DATA_SIZE 500
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright#define NAME_HEADER_SIZE 12
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrighttypedef struct nbt_name_reply {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright struct nbt_name_reply *forw;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright struct nbt_name_reply *back;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright struct name_packet *packet;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *addr;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t name_trn_id;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright boolean_t reply_ready;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright} nbt_name_reply_t;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic nbt_name_reply_t reply_queue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic mutex_t rq_mtx;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic cond_t rq_cv;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic mutex_t nbt_name_config_mtx;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic name_queue_t delete_queue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic name_queue_t refresh_queue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int name_sock = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int bcast_num = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int nbns_num = 0;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic addr_entry_t smb_bcast_list[SMB_PI_MAX_NETWORKS];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic addr_entry_t smb_nbns[SMB_PI_MAX_WINS];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic int smb_netbios_process_response(uint16_t, addr_entry_t *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet *, uint32_t);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic int smb_send_name_service_packet(addr_entry_t *addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet *packet);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * Allocate a transaction id.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic uint16_t
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_netbios_name_trn_id(void)
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright{
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright static uint16_t trn_id;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright static mutex_t trn_id_mtx;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) mutex_lock(&trn_id_mtx);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright do {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright ++trn_id;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright } while (trn_id == 0 || trn_id == (uint16_t)-1);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) mutex_unlock(&trn_id_mtx);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (trn_id);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright}
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_end_node_challenge(nbt_name_reply_t *reply_info)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t retry;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t tid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question question;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *destination;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct timespec st;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The response packet has in it the address of the presumed owner
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of the name. Challenge that owner. If owner either does not
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * respond or indicates that he no longer owns the name, claim the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name. Otherwise, the name cannot be claimed.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((answer = reply_info->packet->answer) == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = answer->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name = answer->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_QUERY_REQUEST | NM_FLAGS_UNICAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.qdcount = 1; /* question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.question = &question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.ancount = 0; /* answer recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.answer = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.nscount = 0; /* authority recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.authority = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.arcount = 0; /* additional recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.additional = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = &destination->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (retry = 0; retry < UCAST_REQ_RETRY_COUNT; retry++) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright tid = smb_netbios_name_trn_id();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.name_trn_id = tid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_send_name_service_packet(addr, &packet) >= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((rc = smb_netbios_process_response(tid, addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &packet, UCAST_REQ_RETRY_TIMEOUT)) != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw st.tv_sec = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw st.tv_nsec = (UCAST_REQ_RETRY_TIMEOUT * 1000000);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) nanosleep(&st, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* No reply */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic nbt_name_reply_t *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_get_reply(uint16_t tid, uint32_t timeout)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t info;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *answer;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright nbt_name_reply_t *reply;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t wait_time, to_save; /* in millisecond */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct timeval wt;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timestruc_t to;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw to_save = timeout;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright reply = malloc(sizeof (nbt_name_reply_t));
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if (reply != NULL) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright reply->reply_ready = B_FALSE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw reply->name_trn_id = tid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_lock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw QUEUE_INSERT_TAIL(&reply_queue, reply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_unlock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (;;) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gettimeofday(&wt, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wait_time = wt.tv_usec / 1000;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw to.tv_sec = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw to.tv_nsec = timeout * 1000000;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) mutex_lock(&rq_mtx);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) cond_reltimedwait(&rq_cv, &rq_mtx, &to);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) mutex_unlock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if (reply->reply_ready) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw info = reply->packet->info;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (PACKET_TYPE(info) == WACK_RESPONSE) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer = reply->packet->answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wait_time = (answer) ?
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw TO_MILLISECONDS(answer->ttl) :
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DEFAULT_TTL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(reply->addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(reply->packet);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = to_save + wait_time;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright reply->reply_ready = B_FALSE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw reply->name_trn_id = tid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_lock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw QUEUE_INSERT_TAIL(&reply_queue, reply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_unlock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (reply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) gettimeofday(&wt, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wait_time = (wt.tv_usec / 1000) - wait_time;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (wait_time >= timeout) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_lock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw QUEUE_CLIP(reply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_unlock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(reply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout -= wait_time;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_reply_ready(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright nbt_name_reply_t *reply;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_lock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (reply = reply_queue.forw; reply != &reply_queue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw reply = reply->forw) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (reply->name_trn_id == packet->name_trn_id) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw QUEUE_CLIP(reply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw reply->addr = addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw reply->packet = packet;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright reply->reply_ready = B_TRUE;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) cond_signal(&rq_cv);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) mutex_unlock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_unlock(&rq_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Presumably nobody is waiting any more... */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer = packet->answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (answer)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_name_freeaddrs(answer->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(packet);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_netbios_process_response(uint16_t tid, addr_entry_t *addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet *packet, uint32_t timeout)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = 0;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t info;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright nbt_name_reply_t *reply;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *entry;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question *question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t ttl;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((reply = smb_name_get_reply(tid, timeout)) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0); /* No reply: retry */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw info = reply->packet->info;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer = reply->packet->answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* response */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (PACKET_TYPE(info)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NAME_QUERY_RESPONSE:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (POSITIVE_RESPONSE(info)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = &answer->name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Make sure that remote name is not
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * flagged local
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr->attributes &= ~NAME_ATTR_LOCAL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if (answer->ttl)
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr->ttl = answer->ttl;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright else
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr->ttl = DEFAULT_TTL;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr->refresh_ttl = TO_SECONDS(addr->ttl);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr->ttl = addr->refresh_ttl;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = addr->forw;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (addr != &answer->name->addr_list);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_name_logf(answer->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_netbios_cache_insert_list(answer->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = -1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NAME_REGISTRATION_RESPONSE:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (NEGATIVE_RESPONSE(info)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RCODE(info) == RCODE_CFT_ERR) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (answer == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = -RCODE(info);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name = answer->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw entry = smb_netbios_cache_lookup(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (entry) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * a name in the state "conflict
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * detected" does not "logically" exist
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * on that node. No further session
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * will be accepted on that name.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * No datagrams can be sent against
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * that name.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Such an entry will not be used for
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * purposes of processing incoming
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * request packets.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The only valid user NetBIOS operation
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * against such a name is DELETE NAME.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw entry->attributes |= NAME_ATTR_CONFLICT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright "nbns: name conflict: %15.15s",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw entry->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_unlock_entry(entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = -RCODE(info);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name can be added:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * adjust refresh timeout value,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * TTL, for this name
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question = packet->question;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright ttl = (answer && answer->ttl) ? answer->ttl : DEFAULT_TTL;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright ttl = TO_SECONDS(ttl);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((entry = smb_netbios_cache_lookup(question->name)) != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = &entry->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((addr->refresh_ttl == 0) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (ttl < addr->refresh_ttl))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr->refresh_ttl = addr->ttl = ttl;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = addr->forw;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (addr != &entry->addr_list);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_unlock_entry(entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NAME_RELEASE_RESPONSE:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case END_NODE_CHALLENGE_REGISTRATION_REQUEST:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The response packet has in it the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * address of the presumed owner of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name. Challenge that owner. If
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * owner either does not respond or
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * indicates that he no longer owns the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name, claim the name. Otherwise,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the name cannot be claimed.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_end_node_challenge(reply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (answer)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_name_freeaddrs(answer->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(reply->addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(reply->packet);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(reply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (rc); /* retry */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_name_buf_from_packet
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Description:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Convert a NetBIOS Name Server Packet Block (npb)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * into the bits and bytes destined for the wire.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The "buf" is used as a heap.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Inputs:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * char * buf -> Buffer, from the wire
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unsigned n_buf -> Length of 'buf'
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name_packet *npb -> Packet block, decode into
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unsigned n_npb -> Max bytes in 'npb'
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * >0 -> Encode successful, value is length of packet in "buf"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -1 -> Hard error, can not possibly encode
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * -2 -> Need more memory in buf -- it's too small
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_buf_from_packet(unsigned char *buf, int n_buf,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet *npb)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *raddr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *heap = buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *end_heap = heap + n_buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *dnptrs[32];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char comp_name_buf[MAX_NAME_LENGTH];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned int tmp;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int i, step;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (n_buf < NAME_HEADER_SIZE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1); /* no header, impossible */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dnptrs[0] = heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dnptrs[1] = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, npb->name_trn_id);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, npb->info);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, npb->qdcount);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, npb->ancount);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, npb->nscount);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, npb->arcount);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < npb->qdcount; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((heap + 34 + 4) > end_heap)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_first_level_name_encode(npb->question[i].name,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw comp_name_buf, sizeof (comp_name_buf));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) strcpy((char *)heap, (char *)comp_name_buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += strlen((char *)comp_name_buf) + 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, npb->question[i].question_type);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, npb->question[i].question_class);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (step = 1; step <= 3; step++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *nrr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int n;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* truly ugly, but saves code copying */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (step == 1) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw n = npb->ancount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr = npb->answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else if (step == 2) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw n = npb->nscount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr = npb->authority;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else { /* step == 3 */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw n = npb->arcount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr = npb->additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < n; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((heap + 34 + 10) > end_heap)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_first_level_name_encode(nrr->name,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw comp_name_buf, sizeof (comp_name_buf));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) strcpy((char *)heap, (char *)comp_name_buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += strlen((char *)comp_name_buf) + 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, nrr[i].rr_type);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, nrr[i].rr_class);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT32(heap, nrr[i].ttl);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 4;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, nrr[i].rdlength);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((tmp = nrr[i].rdlength) > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((heap + tmp) > end_heap)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nrr[i].rr_type == NAME_RR_TYPE_NB &&
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].rr_class == NAME_RR_CLASS_IN &&
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tmp >= 6 && nrr[i].rdata == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw tmp = nrr[i].name->attributes &
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (NAME_ATTR_GROUP |
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NAME_ATTR_OWNER_NODE_TYPE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(heap, tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw raddr = &nrr[i].name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(heap,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &raddr->sin.sin_addr.s_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (uint32_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += 4;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bcopy(nrr[i].rdata, heap, tmp);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += tmp;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (heap - buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * strnchr
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Lookup for character 'c' in first 'n' chars of string 's'.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns pointer to the found char, otherwise returns 0.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstrnchr(const char *s, char c, int n)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *ps = (char *)s;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *es = (char *)s + n;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (ps < es && *ps) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*ps == c)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (ps);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ++ps;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*ps == '\0' && c == '\0')
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (ps);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic boolean_t
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwis_multihome(char *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return (smb_nic_getnum(name) > 1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netbios_getname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get the Netbios name part of the given record.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Does some boundary checks.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns the name length on success, otherwise
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * returns 0.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_netbios_getname(char *name, char *buf, char *buf_end)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *name_end;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int name_len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (buf >= buf_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* no room for a NB name */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name_end = strnchr(buf, '\0', buf_end - buf + 1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (name_end == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* not a valid NB name */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name_len = name_end - buf + 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) strlcpy(name, buf, name_len);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (name_len);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_name_buf_to_packet
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * Convert the bits and bytes that came from the wire into a NetBIOS
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * Name Server Packet Block (npb). The "block" is used as a heap.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * Returns a pointer to a name packet on success. Otherwise, returns
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * a NULL pointer.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic struct name_packet *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_buf_to_packet(char *buf, int n_buf)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet *npb;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *scan = (unsigned char *)buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *scan_end = scan + n_buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char name_buf[MAX_NAME_LENGTH];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *nrr = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc, i, n, nn, ns;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t name_trn_id, info;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t qdcount, ancount, nscount, arcount;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *next;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int name_len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (n_buf < NAME_HEADER_SIZE) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* truncated header */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_DEBUG, "nbns: short packet (%d bytes)", n_buf);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name_trn_id = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw info = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw qdcount = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ancount = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nscount = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw arcount = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ns = sizeof (struct name_entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw n = n_buf + sizeof (struct name_packet) +
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ((unsigned)qdcount * (sizeof (struct name_question) + ns)) +
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ((unsigned)ancount * (sizeof (struct resource_record) + ns)) +
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ((unsigned)nscount * (sizeof (struct resource_record) + ns)) +
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ((unsigned)arcount * (sizeof (struct resource_record) + ns));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((npb = malloc(n)) == NULL)
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bzero(npb, n);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap = npb->block_data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->name_trn_id = name_trn_id;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->info = info;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->qdcount = qdcount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->ancount = ancount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->nscount = nscount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->arcount = arcount;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* scan is in position for question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Measure the space needed for the tables
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (qdcount > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->question = (struct name_question *)heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += qdcount * sizeof (struct name_question);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < qdcount; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->question[i].name = (struct name_entry *)heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += sizeof (struct name_entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr = (struct resource_record *)heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ancount > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->answer = (struct resource_record *)heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += ancount * sizeof (struct resource_record);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nscount > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->authority = (struct resource_record *)heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += nscount * sizeof (struct resource_record);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (arcount > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->additional = (struct resource_record *)heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += arcount * sizeof (struct resource_record);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Populate each resource_record's .name field.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Done as a second pass so that all resource records
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * (answer, authority, additional) are consecutive via nrr[i].
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < (ancount + nscount + arcount); i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].name = (struct name_entry *)heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += sizeof (struct name_entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < npb->qdcount; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name_len = smb_netbios_getname(name_buf, (char *)scan,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (char *)scan_end);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (name_len <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(npb);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->question[i].name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_first_level_name_decode((unsigned char *)name_buf,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->question[i].name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Couldn't decode the question name */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(npb);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan += name_len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (scan + 4 > scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* no room for Question Type(2) and Class(2) fields */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(npb);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->question[i].question_type = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->question[i].question_class = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Cheat. Remaining sections are of the same resource_record
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * format. Table space is consecutive.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < (ancount + nscount + arcount); i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (scan[0] == 0xc0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Namebuf is reused... */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name_len = smb_netbios_getname(name_buf, (char *)scan,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (char *)scan_end);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (name_len <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(npb);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = name_len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan += rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (scan + 10 > scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * no room for RR_TYPE (2), RR_CLASS (2), TTL (4) and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * RDLENGTH (2) fields.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(npb);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((rc = smb_first_level_name_decode((unsigned char *)name_buf,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].name)) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(npb);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].rr_type = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].rr_class = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].ttl = BE_IN32(scan); scan += 4;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].rdlength = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((n = nrr[i].rdlength) > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + n) > scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* no room for RDATA */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(npb);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bcopy(scan, heap, n);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nn = n;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nrr[i].rr_type == 0x0020 &&
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].rr_class == 0x01 && n >= 6) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (nn) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nn == 6)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw next = &nrr[i].name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright next = malloc(
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright sizeof (addr_entry_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (next == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* not enough memory */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(npb);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw QUEUE_INSERT_TAIL(
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &nrr[i].name->addr_list,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw next);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].name->attributes =
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_IN16(scan);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw next->sin.sin_family = AF_INET;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw next->sinlen = sizeof (next->sin);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &next->sin.sin_addr.s_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan + 2, sizeof (uint32_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw next->sin.sin_port =
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright htons(IPPORT_NETBIOS_DGM);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nn -= 6;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan += 6;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nrr[i].rdata = heap;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan += n;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw heap += n;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (npb);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_send_name_service_packet
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Description:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send out a name service packet to proper destination.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Inputs:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * struct netbios_name *dest -> NETBIOS name of destination
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * struct name_packet *packet -> Packet to send
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * success -> >0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * failure -> <=0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_send_name_service_packet(addr_entry_t *addr, struct name_packet *packet)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char buf[MAX_DATAGRAM_LENGTH];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((len = smb_name_buf_from_packet(buf, sizeof (buf), packet)) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw errno = EINVAL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (sendto(name_sock, buf, len, MSG_EOR,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (struct sockaddr *)&addr->sin, addr->sinlen));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netbios_send_rcv
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function sends the given NetBIOS packet to the given
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * address and get back the response. If send operation is not
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * successful, it's repeated 'retries' times.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 Unsuccessful send operation; no reply
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 1 Got reply
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_netbios_send_rcv(int bcast, addr_entry_t *destination,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright struct name_packet *packet, uint32_t retries, uint32_t timeout)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t retry;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t tid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct timespec st;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (retry = 0; retry < retries; retry++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((destination->flags & ADDR_FLAG_VALID) == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright tid = smb_netbios_name_trn_id();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet->name_trn_id = tid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_send_name_service_packet(destination, packet) >= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_netbios_process_response(tid, destination,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet, timeout);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((rc > 0) || (bcast == BROADCAST))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw st.tv_sec = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw st.tv_nsec = (timeout * 1000000);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) nanosleep(&st, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.2. NAME REGISTRATION REQUEST
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_send_name_registration_request(int bcast, struct name_question *question,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *additional)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int gotreply = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t retries;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t timeout;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *destination;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char type;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int i, addr_num, rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw type = question->name->name[15];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_DEBUG, "nbns: name registration bad type (0x%02x)",
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright type);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_name_logf(question->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question->name->attributes &= ~NAME_ATTR_LOCAL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bcast == BROADCAST) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bcast_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = smb_bcast_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_num = bcast_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries = BCAST_REQ_RETRY_COUNT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = BCAST_REQ_RETRY_TIMEOUT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REGISTRATION_REQUEST | NM_FLAGS_BROADCAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = smb_nbns;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_num = nbns_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries = UCAST_REQ_RETRY_COUNT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = UCAST_REQ_RETRY_TIMEOUT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REGISTRATION_REQUEST | NM_FLAGS_UNICAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.qdcount = 1; /* question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.question = question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.ancount = 0; /* answer recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.answer = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.nscount = 0; /* authority recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.authority = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.arcount = 1; /* additional recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.additional = additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (IS_UNIQUE(question->name->attributes) &&
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (is_multihome((char *)(question->name->name))))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_MULTIHOME_REGISTRATION_REQUEST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < addr_num; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Only register with the Primary WINS server,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unless we got no reply.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((bcast == UNICAST) && gotreply)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_netbios_send_rcv(bcast, &destination[i], &packet,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries, timeout);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == 1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gotreply = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (gotreply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.4. NAME REFRESH REQUEST
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_send_name_refresh_request(int bcast, struct name_question *question,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *additional, int force)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int gotreply = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t retries;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t timeout;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *addr;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *destination;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char type;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int i, addr_num, q_addrs = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw type = question->name->name[15];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_DEBUG, "nbns: name refresh bad type (0x%02x)", type);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_name_logf(question->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question->name->attributes &= ~NAME_ATTR_LOCAL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (bcast) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case BROADCAST :
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bcast_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = smb_bcast_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_num = bcast_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries = BCAST_REQ_RETRY_COUNT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = BCAST_REQ_RETRY_TIMEOUT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_BROADCAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case UNICAST :
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = smb_nbns;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_num = nbns_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries = UCAST_REQ_RETRY_COUNT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = UCAST_REQ_RETRY_TIMEOUT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_UNICAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = &question->name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the value of addr_num is irrelvant here, because
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the code is going to do special_process so it doesn't
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * need the addr_num. We set a value here just to avoid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * compiler warning.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_num = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries = UCAST_REQ_RETRY_COUNT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = UCAST_REQ_RETRY_TIMEOUT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_UNICAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw q_addrs = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (IS_UNIQUE(question->name->attributes) &&
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (is_multihome((char *)(question->name->name))))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_MULTIHOME_REGISTRATION_REQUEST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.qdcount = 1; /* question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.question = question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.ancount = 0; /* answer recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.answer = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.nscount = 0; /* authority recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.authority = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.arcount = 1; /* additional recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.additional = additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (q_addrs)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto special_process;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < addr_num; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_netbios_send_rcv(bcast, &destination[i], &packet,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries, timeout);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == 1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gotreply = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (gotreply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwspecial_process:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = destination;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_netbios_send_rcv(bcast, addr, &packet,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries, timeout);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == 1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gotreply = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = addr->forw;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (addr != destination);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (gotreply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.5. POSITIVE NAME REGISTRATION RESPONSE
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.6. NEGATIVE NAME REGISTRATION RESPONSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_send_name_registration_response(addr_entry_t *addr,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright struct name_packet *original_packet, uint16_t rcode)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(&packet, sizeof (struct name_packet));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(&answer, sizeof (struct resource_record));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.name_trn_id = original_packet->name_trn_id;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REGISTRATION_RESPONSE | NAME_NM_FLAGS_RA |
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (rcode & NAME_RCODE_MASK);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.qdcount = 0; /* question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.question = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.ancount = 1; /* answer recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.answer = &answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.nscount = 0; /* authority recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.authority = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.arcount = 0; /* additional recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.additional = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.name = original_packet->question->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rr_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rr_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.ttl = original_packet->additional->ttl;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdlength = original_packet->additional->rdlength;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdata = original_packet->additional->rdata;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_service_packet(addr, &packet));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.9. NAME RELEASE REQUEST & DEMAND
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_send_name_release_request_and_demand(int bcast,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question *question, struct resource_record *additional)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int gotreply = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int i, rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int addr_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t retries;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t timeout;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *destination;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bcast == BROADCAST) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bcast_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = smb_bcast_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_num = bcast_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries = 1; /* BCAST_REQ_RETRY_COUNT */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = 100; /* BCAST_REQ_RETRY_TIMEOUT */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_RELEASE_REQUEST | NM_FLAGS_BROADCAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = smb_nbns;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_num = nbns_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries = 1; /* UCAST_REQ_RETRY_COUNT */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = 100; /* UCAST_REQ_RETRY_TIMEOUT */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_RELEASE_REQUEST | NM_FLAGS_UNICAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.qdcount = 1; /* question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.question = question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.ancount = 0; /* answer recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.answer = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.nscount = 0; /* authority recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.authority = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.arcount = 1; /* additional recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.additional = additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < addr_num; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_netbios_send_rcv(bcast, &destination[i], &packet,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries, timeout);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == 1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw gotreply = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (gotreply);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.10. POSITIVE NAME RELEASE RESPONSE
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.11. NEGATIVE NAME RELEASE RESPONSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* LINTED - E_STATIC_UNUSED */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_send_name_release_response(addr_entry_t *addr,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright struct name_packet *original_packet, uint16_t rcode)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(&packet, sizeof (struct name_packet));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(&answer, sizeof (struct resource_record));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.name_trn_id = original_packet->name_trn_id;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_RELEASE_RESPONSE | (rcode & NAME_RCODE_MASK);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.qdcount = 0; /* question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.question = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.ancount = 1; /* answer recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.answer = &answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.nscount = 0; /* authority recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.authority = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.arcount = 0; /* additional recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.additional = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.name = original_packet->question->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rr_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rr_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.ttl = original_packet->additional->ttl;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdlength = original_packet->additional->rdlength;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdata = original_packet->additional->rdata;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_service_packet(addr, &packet));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.12. NAME QUERY REQUEST
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_send_name_query_request(int bcast, struct name_question *question)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t retry, retries;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t timeout;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t tid;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *destination;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int i, addr_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct timespec st;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bcast == BROADCAST) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bcast_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = smb_bcast_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_num = bcast_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries = BCAST_REQ_RETRY_COUNT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = BCAST_REQ_RETRY_TIMEOUT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_QUERY_REQUEST | NM_FLAGS_BROADCAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw destination = smb_nbns;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr_num = nbns_num;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw retries = UCAST_REQ_RETRY_COUNT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw timeout = UCAST_REQ_RETRY_TIMEOUT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_QUERY_REQUEST | NM_FLAGS_UNICAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.qdcount = 1; /* question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.question = question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.ancount = 0; /* answer recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.answer = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.nscount = 0; /* authority recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.authority = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.arcount = 0; /* additional recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.additional = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < addr_num; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (retry = 0; retry < retries; retry++) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((destination[i].flags & ADDR_FLAG_VALID) == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright tid = smb_netbios_name_trn_id();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.name_trn_id = tid;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_send_name_service_packet(&destination[i],
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &packet) >= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((rc = smb_netbios_process_response(tid,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &destination[i],
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &packet, timeout)) != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw st.tv_sec = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw st.tv_nsec = (timeout * 1000000);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) nanosleep(&st, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.13. POSITIVE NAME QUERY RESPONSE
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.14. NEGATIVE NAME QUERY RESPONSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_send_name_query_response(addr_entry_t *addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet *original_packet, struct name_entry *entry,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t rcode)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *raddr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record answer;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t attr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char data[MAX_DATAGRAM_LENGTH];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *scan = data;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright uint32_t ret_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.name_trn_id = original_packet->name_trn_id;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_QUERY_RESPONSE | (rcode & NAME_RCODE_MASK);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.qdcount = 0; /* question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.question = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.ancount = 1; /* answer recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.answer = &answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.nscount = 0; /* authority recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.authority = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.arcount = 0; /* additional recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.additional = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.name = entry;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rr_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.ttl = entry->addr_list.ttl;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdata = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rcode) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rr_type = NAME_RR_TYPE_NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdlength = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(data, 6);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdlength = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rr_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw raddr = &entry->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw attr = entry->attributes & (NAME_ATTR_GROUP |
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NAME_ATTR_OWNER_NODE_TYPE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, attr); scan += 2;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright ret_addr = LE_32(raddr->sin.sin_addr.s_addr);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr >> 8;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr >> 16;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr >> 24;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdlength += 6;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw raddr = raddr->forw;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (raddr != &entry->addr_list);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_service_packet(addr, &packet));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.18. NODE STATUS RESPONSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_send_node_status_response(addr_entry_t *addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet *original_packet)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as uint32_t net_ipaddr;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as int64_t max_connections;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct arpreq arpreq;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *scan;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *scan_end;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char data[MAX_NETBIOS_REPLY_DATA_SIZE];
55bf511df53aad0fdb7eb3fa349f0308cc05234cas boolean_t scan_done = B_FALSE;
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego smb_inaddr_t ipaddr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(&packet, sizeof (struct name_packet));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(&answer, sizeof (struct resource_record));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.name_trn_id = original_packet->name_trn_id;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NODE_STATUS_RESPONSE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.qdcount = 0; /* question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.question = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.ancount = 1; /* answer recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.answer = &answer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.nscount = 0; /* authority recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.authority = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.arcount = 0; /* additional recs */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.additional = NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.name = original_packet->question->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rr_type = NAME_RR_TYPE_NBSTAT;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rr_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.ttl = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdata = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan = smb_netbios_cache_status(data, MAX_NETBIOS_REPLY_DATA_SIZE,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw original_packet->question->name->scope);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan_end = data + MAX_NETBIOS_REPLY_DATA_SIZE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego ipaddr.a_family = AF_INET;
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright if (smb_nic_is_same_subnet(&ipaddr))
7b59d02d2a384be9a08087b14defadd214b3c1ddjb net_ipaddr = addr->sin.sin_addr.s_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
7b59d02d2a384be9a08087b14defadd214b3c1ddjb net_ipaddr = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &max_connections);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as
55bf511df53aad0fdb7eb3fa349f0308cc05234cas while (!scan_done) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 6) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (net_ipaddr != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct sockaddr_in *s_in;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int s;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw s = socket(AF_INET, SOCK_DGRAM, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw s_in = (struct sockaddr_in *)&arpreq.arp_pa;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw s_in->sin_family = AF_INET;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw s_in->sin_addr.s_addr = net_ipaddr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (ioctl(s, SIOCGARP, (caddr_t)&arpreq) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(scan, 6);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bcopy(&arpreq.arp_ha.sa_data, scan, 6);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(scan, 6);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan += 6;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 26) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(scan, 26);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan += 26;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 2) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, 0); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 2) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, 0); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 2) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, 0); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 2) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, 0); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 2) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, 0); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 2) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, 0); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 2) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, 0); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 2) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, max_connections); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((scan + 2) >= scan_end) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info |= NAME_NM_FLAGS_TC;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, 0); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
55bf511df53aad0fdb7eb3fa349f0308cc05234cas scan_done = B_TRUE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdlength = scan - data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_service_packet(addr, &packet));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Bnode_add_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char data[8];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t attr;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = &name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build name service packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * question.name->attributes |= NAME_NB_FLAGS_ONT_B;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is commented because NAME_NB_FLAGS_ONT_B is 0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.ttl = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdata = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdlength = 6;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw attr = name->attributes & (NAME_ATTR_GROUP |
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NAME_ATTR_OWNER_NODE_TYPE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(&data[0], attr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(&data[2], &addr->sin.sin_addr.s_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (uint32_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc |= smb_send_name_registration_request(BROADCAST, &question,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &additional);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = addr->forw;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (addr != &name->addr_list);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Bnode_find_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_query_request(BROADCAST, &question));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Bnode_delete_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record additional;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *raddr;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright unsigned char data[MAX_DATAGRAM_LENGTH];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright unsigned char *scan = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t attr;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright uint32_t ret_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.ttl = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdata = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdlength = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw raddr = &name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw attr = name->attributes & (NAME_ATTR_GROUP |
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NAME_ATTR_OWNER_NODE_TYPE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, attr); scan += 2;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright ret_addr = LE_32(raddr->sin.sin_addr.s_addr);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr >> 8;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr >> 16;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr >> 24;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdlength += 6;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (raddr != &name->addr_list);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_release_request_and_demand(BROADCAST,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &question, &additional));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Pnode_add_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char data[8];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t attr;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = &name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.ttl = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdata = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdlength = 6;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw attr = name->attributes &
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (NAME_ATTR_GROUP | NAME_ATTR_OWNER_NODE_TYPE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(&data[0], attr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(&data[2], &addr->sin.sin_addr.s_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (uint32_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc |= smb_send_name_registration_request(UNICAST, &question,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &additional);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = addr->forw;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (addr != &name->addr_list);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Pnode_refresh_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char data[8];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint16_t attr;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = &name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.ttl = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdata = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdlength = 6;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw attr = name->attributes &
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (NAME_ATTR_GROUP | NAME_ATTR_OWNER_NODE_TYPE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(&data[0], attr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) memcpy(&data[2], &addr->sin.sin_addr.s_addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (uint32_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc |= smb_send_name_refresh_request(UNICAST, &question,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &additional, 1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr = addr->forw;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (addr != &name->addr_list);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Pnode_find_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Host initiated processing for a P node
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name->attributes |= NAME_NB_FLAGS_ONT_P;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_query_request(UNICAST, &question));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Pnode_delete_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record additional;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *raddr;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright unsigned char data[MAX_DATAGRAM_LENGTH];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright unsigned char *scan = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t attr;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright uint32_t ret_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.name->attributes |= NAME_NB_FLAGS_ONT_P;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question.question_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.name = name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_class = NAME_QUESTION_CLASS_IN;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.ttl = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdata = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdlength = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rr_type = NAME_QUESTION_TYPE_NB;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw raddr = &name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw do {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan = data;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw attr = name->attributes & (NAME_ATTR_GROUP |
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NAME_ATTR_OWNER_NODE_TYPE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw BE_OUT16(scan, attr); scan += 2;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright ret_addr = LE_32(raddr->sin.sin_addr.s_addr);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr >> 8;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr >> 16;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright *scan++ = ret_addr >> 24;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional.rdlength = 6;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw raddr = raddr->forw;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_send_name_release_request_and_demand(UNICAST,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &question, &additional);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } while (raddr != &name->addr_list);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Mnode_add_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_name_Bnode_add_name(name) > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1); /* No name server configured */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_name_Pnode_add_name(name));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Hnode_add_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num > 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_name_Pnode_add_name(name) == 1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_name_Bnode_add_name(name));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Mnode_find_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_name_Bnode_find_name(name) == 1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1); /* No name server configured */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_name_Pnode_find_name(name));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Hnode_find_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num > 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_name_Pnode_find_name(name) == 1)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_name_Bnode_find_name(name));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Mnode_delete_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_name_Bnode_delete_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1); /* No name server configured */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_name_Pnode_delete_name(name) > 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_Hnode_delete_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbns_num > 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_name_Pnode_delete_name(name) > 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_name_Bnode_delete_name(name));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_process_Bnode_packet(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *entry;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question *question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question = packet->question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional = packet->additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (packet->info & NAME_OPCODE_OPCODE_MASK) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NAME_OPCODE_REFRESH:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Guard against malformed packets */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((question == 0) || (additional == 0))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (additional->name->addr_list.sin.sin_addr.s_addr == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name = question->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->addr_list.ttl = additional->ttl;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->attributes = additional->name->attributes;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->addr_list.sin = additional->name->addr_list.sin;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->addr_list.forw = name->addr_list.back = &name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((entry = smb_netbios_cache_lookup_addr(name)) != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_update_entry(entry, question->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_unlock_entry(entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_netbios_cache_insert(question->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NAME_OPCODE_QUERY:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This opcode covers both NAME_QUERY_REQUEST and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * NODE_STATUS_REQUEST. They can be distinguished
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * based on the type of question entry.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* All query requests have to have question entry */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (question == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (question->question_type == NAME_QUESTION_TYPE_NB) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name = question->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((entry = smb_netbios_cache_lookup(name)) != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_send_name_query_response(addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet, entry, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_unlock_entry(entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (question->question_type == NAME_QUESTION_TYPE_NBSTAT) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Name of "*" may be used to force node to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * divulge status for administrative purposes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name = question->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw entry = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (NETBIOS_NAME_IS_STAR(name->name) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ((entry = smb_netbios_cache_lookup(name)) != 0)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (entry)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_unlock_entry(entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * send only those names that are
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in the same scope as the scope
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * field in the request packet
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_send_node_status_response(addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_process_Pnode_packet(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *entry;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question *question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct resource_record *additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw question = packet->question;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw additional = packet->additional;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (packet->info & NAME_NM_FLAGS_B) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * always ignore UDP broadcast packets
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (packet->info & NAME_OPCODE_OPCODE_MASK) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NAME_OPCODE_REFRESH:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Guard against malformed packets */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((question == 0) || (additional == 0))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (additional->name->addr_list.sin.sin_addr.s_addr == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name = question->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->addr_list.ttl = additional->ttl;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->attributes = additional->name->attributes;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->addr_list.sin = additional->name->addr_list.sin;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->addr_list.forw = name->addr_list.back = &name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((entry = smb_netbios_cache_lookup(name)) != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_update_entry(entry, name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_unlock_entry(entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_netbios_cache_insert(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_send_name_registration_response(addr, packet, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case NAME_OPCODE_QUERY:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This opcode covers both NAME_QUERY_REQUEST and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * NODE_STATUS_REQUEST. They can be distinguished
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * based on the type of question entry.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* All query requests have to have question entry */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (question == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (question->question_type == NAME_QUESTION_TYPE_NB) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name = question->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((entry = smb_netbios_cache_lookup(name)) != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * send response to the IP address and port
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * number from which the request was received.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_send_name_query_response(addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet, entry, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_unlock_entry(entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * send response to the requestor
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_send_name_query_response(addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet, name, RCODE_NAM_ERR);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (question->question_type == NAME_QUESTION_TYPE_NBSTAT) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Name of "*" may be used to force node to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * divulge status for administrative purposes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name = question->name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw entry = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (NETBIOS_NAME_IS_STAR(name->name) ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ((entry = smb_netbios_cache_lookup(name)) != 0)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * send only those names that are
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in the same scope as the scope
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * field in the request packet
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (entry)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_unlock_entry(entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_send_node_status_response(addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_process_Mnode_packet(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (packet->info & NAME_NM_FLAGS_B)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_name_process_Bnode_packet(packet, addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_name_process_Pnode_packet(packet, addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_process_Hnode_packet(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (packet->info & NAME_NM_FLAGS_B)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_name_process_Bnode_packet(packet, addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_name_process_Pnode_packet(packet, addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netbios_name_tick
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Called once a second to handle name server timeouts.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_netbios_name_tick(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *entry;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_lock(&refresh_queue.mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_refresh(&refresh_queue);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while ((name = refresh_queue.head.forw) != &refresh_queue.head) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw QUEUE_CLIP(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (IS_LOCAL(name->attributes)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (IS_UNIQUE(name->attributes)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_name_Pnode_refresh_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw entry = smb_name_find_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_name_unlock_name(entry);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_unlock(&refresh_queue.mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_reset_ttl();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_name_find_name
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Lookup name cache for the given name.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If it's not in the cache it'll send a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name query request and then lookup the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * cache again. Note that if a name is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * returned it's locked and called MUST
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unlock it by calling smb_name_unlock_name()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstruct name_entry *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_find_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *result;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((result = smb_netbios_cache_lookup(name)) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (smb_node_type) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'B':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_name_Bnode_find_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'P':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_name_Pnode_find_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'M':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_name_Mnode_find_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'H':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_name_Hnode_find_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_netbios_cache_lookup(name));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (result);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_unlock_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_unlock_entry(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_add_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_name_logf(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (smb_node_type) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'B':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_name_Bnode_add_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'P':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_name_Pnode_add_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'M':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_name_Mnode_add_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'H':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_name_Hnode_add_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc >= 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_netbios_cache_insert(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_name_delete_name(struct name_entry *name)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char type;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw type = name->name[15];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_DEBUG, "nbns: name delete bad type (0x%02x)", type);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_name_logf(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->attributes &= ~NAME_ATTR_LOCAL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_delete(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (smb_node_type) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'B':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_name_Bnode_delete_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'P':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_name_Pnode_delete_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'M':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_name_Mnode_delete_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'H':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_name_Hnode_delete_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc > 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int length;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw} worker_param_t;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netbios_worker
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Process incoming request/response packets for Netbios
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name service (on port 138).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_netbios_worker(void *arg)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw worker_param_t *p = (worker_param_t *)arg;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *addr = p->addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet *packet;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((packet = smb_name_buf_to_packet(p->buf, p->length)) != NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (packet->info & NAME_OPCODE_R) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Reply packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_reply_ready(packet, addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(p->buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(p);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Request packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (smb_node_type) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'B':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_name_process_Bnode_packet(packet, addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'P':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_name_process_Pnode_packet(packet, addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'M':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_name_process_Mnode_packet(packet, addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw case 'H':
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw default:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_name_process_Hnode_packet(packet, addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (packet->answer)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_name_freeaddrs(packet->answer->name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(packet);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb } else {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_ERR, "nbns: packet decode failed");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(p->buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(p);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * Configure the node type. If a WINS server has been specified,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * act like an H-node. Otherwise, behave like a B-node.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_netbios_node_config(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright static smb_cfg_id_t wins[SMB_PI_MAX_WINS] = {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright SMB_CI_WINS_SRV1,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright SMB_CI_WINS_SRV2
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright };
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright char ipstr[16];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright uint32_t ipaddr;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright int i;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_node_type = SMB_NODETYPE_B;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright nbns_num = 0;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright for (i = 0; i < SMB_PI_MAX_WINS; ++i) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright ipstr[0] = '\0';
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) smb_config_getstr(wins[i], ipstr, sizeof (ipstr));
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((ipaddr = inet_addr(ipstr)) == INADDR_NONE)
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright continue;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_node_type = SMB_NODETYPE_H;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_nbns[nbns_num].flags = ADDR_FLAG_VALID;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_nbns[nbns_num].sinlen = sizeof (struct sockaddr_in);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_nbns[nbns_num].sin.sin_family = AF_INET;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_nbns[nbns_num].sin.sin_addr.s_addr = ipaddr;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_nbns[nbns_num].sin.sin_port = htons(IPPORT_NETBIOS_NS);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright nbns_num++;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic void
7b59d02d2a384be9a08087b14defadd214b3c1ddjbsmb_netbios_name_registration(void)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb nbcache_iter_t nbc_iter;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct name_entry *name;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb int rc;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb rc = smb_netbios_cache_getfirst(&nbc_iter);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb while (rc == 0) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb name = nbc_iter.nbc_entry;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb (void) smb_netbios_name_logf(name);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (IS_UNIQUE(name->attributes) && IS_LOCAL(name->attributes)) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb switch (smb_node_type) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb case SMB_NODETYPE_B:
7b59d02d2a384be9a08087b14defadd214b3c1ddjb (void) smb_name_Bnode_add_name(name);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb break;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb case SMB_NODETYPE_P:
7b59d02d2a384be9a08087b14defadd214b3c1ddjb (void) smb_name_Pnode_add_name(name);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb break;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb case SMB_NODETYPE_M:
7b59d02d2a384be9a08087b14defadd214b3c1ddjb (void) smb_name_Mnode_add_name(name);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb break;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb case SMB_NODETYPE_H:
7b59d02d2a384be9a08087b14defadd214b3c1ddjb default:
7b59d02d2a384be9a08087b14defadd214b3c1ddjb (void) smb_name_Hnode_add_name(name);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb break;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb free(name);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb rc = smb_netbios_cache_getnext(&nbc_iter);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * Note that the node configuration must be setup before calling
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * smb_init_name_struct().
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_netbios_name_config(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *bcast_entry;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright struct name_entry name;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_niciter_t ni;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright int rc;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) mutex_lock(&nbt_name_config_mtx);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_node_config();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bcast_num = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjb rc = smb_nic_getfirst(&ni);
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States while (rc == SMB_NIC_SUCCESS) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) ||
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS)) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb rc = smb_nic_getnext(&ni);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bcast_entry = &smb_bcast_list[bcast_num];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bcast_entry->flags = ADDR_FLAG_VALID;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bcast_entry->attributes = NAME_ATTR_LOCAL;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bcast_entry->sinlen = sizeof (struct sockaddr_in);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bcast_entry->sin.sin_family = AF_INET;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bcast_entry->sin.sin_port = htons(IPPORT_NETBIOS_NS);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bcast_entry->sin.sin_addr.s_addr = ni.ni_nic.nic_bcast;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bcast_num++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjb smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright NBT_WKSTA, 0, ni.ni_nic.nic_ip.a_ipv4,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright htons(IPPORT_NETBIOS_DGM),
7b59d02d2a384be9a08087b14defadd214b3c1ddjb NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb (void) smb_netbios_cache_insert(&name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
7b59d02d2a384be9a08087b14defadd214b3c1ddjb smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright NBT_SERVER, 0, ni.ni_nic.nic_ip.a_ipv4,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright htons(IPPORT_NETBIOS_DGM),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb (void) smb_netbios_cache_insert(&name);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright rc = smb_nic_getnext(&ni);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb smb_netbios_name_registration();
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) mutex_unlock(&nbt_name_config_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_netbios_name_unconfig(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_entry *name;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) mutex_lock(&nbt_name_config_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_lock(&delete_queue.mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_cache_delete_locals(&delete_queue);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while ((name = delete_queue.head.forw) != &delete_queue.head) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw QUEUE_CLIP(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_name_delete_name(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_unlock(&delete_queue.mtx);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) mutex_unlock(&nbt_name_config_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_netbios_name_reconfig(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_name_unconfig();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_name_config();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * NetBIOS Name Service (port 137)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid *
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_netbios_name_service(void *arg)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct sockaddr_in sin;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr_entry_t *addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int flag = 1;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright char *buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw worker_param_t *worker_param;
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego smb_inaddr_t ipaddr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Initialize reply_queue
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(&reply_queue, sizeof (reply_queue));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw reply_queue.forw = reply_queue.back = &reply_queue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((name_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_ERR, "nbns: socket failed: %m");
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_event(NETBIOS_EVENT_ERROR);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright flag = 1;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) setsockopt(name_sock, SOL_SOCKET, SO_REUSEADDR, &flag,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright sizeof (flag));
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright flag = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) setsockopt(name_sock, SOL_SOCKET, SO_BROADCAST, &flag,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (flag));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(&sin, sizeof (struct sockaddr_in));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sin.sin_family = AF_INET;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright sin.sin_port = htons(IPPORT_NETBIOS_NS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bind(name_sock, (struct sockaddr *)&sin, sizeof (sin)) != 0) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_ERR, "nbns: bind(%d) failed: %m",
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright IPPORT_NETBIOS_NS);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(name_sock);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_event(NETBIOS_EVENT_ERROR);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_event(NETBIOS_EVENT_NS_START);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright while (smb_netbios_running()) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright buf = malloc(MAX_DATAGRAM_LENGTH);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright addr = malloc(sizeof (addr_entry_t));
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((buf == NULL) || (addr == NULL)) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright /* Sleep for 10 seconds and try again */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright free(addr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(buf);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_sleep(10);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightignore: bzero(addr, sizeof (addr_entry_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr->sinlen = sizeof (addr->sin);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw addr->forw = addr->back = addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((len = recvfrom(name_sock, buf, MAX_DATAGRAM_LENGTH,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 0, (struct sockaddr *)&addr->sin, &addr->sinlen)) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (errno == ENOMEM || errno == ENFILE ||
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw errno == EMFILE) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright /* Sleep for 10 seconds and try again */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(addr);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_sleep(10);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw continue;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_ERR, "nbns: recvfrom failed: %m");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(buf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw free(addr);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_event(NETBIOS_EVENT_ERROR);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto shutdown;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Ignore any incoming packets from myself... */
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego ipaddr.a_family = AF_INET;
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright if (smb_nic_is_local(&ipaddr))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw goto ignore;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Launch a netbios worker to process the received packet.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright worker_param = malloc(sizeof (worker_param_t));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (worker_param) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pthread_t worker;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pthread_attr_t tattr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw worker_param->addr = addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw worker_param->buf = buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw worker_param->length = len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) pthread_attr_init(&tattr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) pthread_attr_setdetachstate(&tattr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PTHREAD_CREATE_DETACHED);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) pthread_create(&worker, &tattr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_worker, worker_param);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) pthread_attr_destroy(&tattr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwshutdown:
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_event(NETBIOS_EVENT_NS_STOP);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_netbios_wait(NETBIOS_EVENT_BROWSER_STOP);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if (!smb_netbios_error())
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netbios_name_unconfig();
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(name_sock);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright return (NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}