da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
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 * CDDL HEADER END
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * NetBIOS name resolution node types.
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.
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.
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).
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).
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * NetBIOS Name Service Protocols
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.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * A RESPONSE packet is always sent to the source UDP port and source IP
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * address of the request packet.
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.
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.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.1.1. HEADER
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.1.3. RESOURCE RECORD
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RESOURCE RECORD RR_CLASS field definitions
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of NB.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic addr_entry_t smb_bcast_list[SMB_PI_MAX_NETWORKS];
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic int smb_netbios_process_response(uint16_t, addr_entry_t *,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightstatic int smb_send_name_service_packet(addr_entry_t *addr,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * Allocate a transaction id.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright } while (trn_id == 0 || trn_id == (uint16_t)-1);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_end_node_challenge(nbt_name_reply_t *reply_info)
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 return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (retry = 0; retry < UCAST_REQ_RETRY_COUNT; retry++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* No reply */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_get_reply(uint16_t tid, uint32_t timeout)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (;;) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_reply_ready(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Presumably nobody is waiting any more... */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_netbios_process_response(uint16_t tid, addr_entry_t *addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0); /* No reply: retry */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* response */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Make sure that remote name is not
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * flagged local
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (answer == 0) {
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.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright "nbns: name conflict: %15.15s",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name can be added:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * adjust refresh timeout value,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * TTL, for this name
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright ttl = (answer && answer->ttl) ? answer->ttl : DEFAULT_TTL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((entry = smb_netbios_cache_lookup(question->name)) != 0) {
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 * smb_name_buf_from_packet
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 * 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 * 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
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_buf_from_packet(unsigned char *buf, int n_buf,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_first_level_name_encode(npb->question[i].name,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* truly ugly, but saves code copying */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else { /* step == 3 */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < n; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Lookup for character 'c' in first 'n' chars of string 's'.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns pointer to the found char, otherwise returns 0.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic char *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*ps == c)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netbios_getname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Get the Netbios name part of the given record.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Does some boundary checks.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns the name length on success, otherwise
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * returns 0.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_netbios_getname(char *name, char *buf, char *buf_end)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* no room for a NB name */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (name_end == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* not a valid NB name */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_name_buf_to_packet
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.
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * Returns a pointer to a name packet on success. Otherwise, returns
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * a NULL pointer.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic struct name_packet *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* truncated header */
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_DEBUG, "nbns: short packet (%d bytes)", n_buf);
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 /* scan is in position for question entries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Measure the space needed for the tables
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < qdcount; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
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 /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (name_len <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_first_level_name_decode((unsigned char *)name_buf,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Couldn't decode the question name */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* no room for Question Type(2) and Class(2) fields */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->question[i].question_type = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw npb->question[i].question_class = BE_IN16(scan); scan += 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Cheat. Remaining sections are of the same resource_record
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * format. Table space is consecutive.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Namebuf is reused... */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (name_len <= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * no room for RR_TYPE (2), RR_CLASS (2), TTL (4) and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * RDLENGTH (2) fields.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((rc = smb_first_level_name_decode((unsigned char *)name_buf,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* no room for RDATA */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (next == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* not enough memory */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_send_name_service_packet
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Description:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send out a name service packet to proper destination.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * struct netbios_name *dest -> NETBIOS name of destination
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * struct name_packet *packet -> Packet to send
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * success -> >0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * failure -> <=0
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_send_name_service_packet(addr_entry_t *addr, struct name_packet *packet)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((len = smb_name_buf_from_packet(buf, sizeof (buf), packet)) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netbios_send_rcv
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 * Returns:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0 Unsuccessful send operation; no reply
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 1 Got reply
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_netbios_send_rcv(int bcast, addr_entry_t *destination,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright struct name_packet *packet, uint32_t retries, uint32_t timeout)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_send_name_service_packet(destination, packet) >= 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.2. NAME REGISTRATION REQUEST
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_send_name_registration_request(int bcast, struct name_question *question,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_DEBUG, "nbns: name registration bad type (0x%02x)",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REGISTRATION_REQUEST | NM_FLAGS_BROADCAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REGISTRATION_REQUEST | NM_FLAGS_UNICAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < addr_num; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Only register with the Primary WINS server,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unless we got no reply.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_netbios_send_rcv(bcast, &destination[i], &packet,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.4. NAME REFRESH REQUEST
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_send_name_refresh_request(int bcast, struct name_question *question,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_DEBUG, "nbns: name refresh bad type (0x%02x)", type);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw switch (bcast) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_BROADCAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
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 for (i = 0; i < addr_num; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_netbios_send_rcv(bcast, &destination[i], &packet,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.5. POSITIVE NAME REGISTRATION RESPONSE
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.6. NEGATIVE NAME REGISTRATION RESPONSE
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_send_name_registration_response(addr_entry_t *addr,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright struct name_packet *original_packet, uint16_t rcode)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_REGISTRATION_RESPONSE | NAME_NM_FLAGS_RA |
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdlength = original_packet->additional->rdlength;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.9. NAME RELEASE REQUEST & DEMAND
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_question *question, struct resource_record *additional)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_RELEASE_REQUEST | NM_FLAGS_BROADCAST;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < addr_num; i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_netbios_send_rcv(bcast, &destination[i], &packet,
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.10. POSITIVE NAME RELEASE RESPONSE
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.11. NEGATIVE NAME RELEASE RESPONSE
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 packet.info = NAME_RELEASE_RESPONSE | (rcode & NAME_RCODE_MASK);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw answer.rdlength = original_packet->additional->rdlength;
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.12. NAME QUERY REQUEST
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_send_name_query_request(int bcast, struct name_question *question)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < addr_num; i++) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((destination[i].flags & ADDR_FLAG_VALID) == 0)
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.13. POSITIVE NAME QUERY RESPONSE
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.14. NEGATIVE NAME QUERY RESPONSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct name_packet *original_packet, struct name_entry *entry,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw packet.info = NAME_QUERY_RESPONSE | (rcode & NAME_RCODE_MASK);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * RFC 1002 4.2.18. NODE STATUS RESPONSE
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_send_node_status_response(addr_entry_t *addr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw scan = smb_netbios_cache_status(data, MAX_NETBIOS_REPLY_DATA_SIZE,
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &max_connections);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* LINTED - E_BAD_PTR_CAST_ALIGN */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) close(s);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build name service packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * question.name->attributes |= NAME_NB_FLAGS_ONT_B;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is commented because NAME_NB_FLAGS_ONT_B is 0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc |= smb_send_name_registration_request(BROADCAST, &question,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_query_request(BROADCAST, &question));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_release_request_and_demand(BROADCAST,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc |= smb_send_name_registration_request(UNICAST, &question,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Host initiated processing for a P node
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (smb_send_name_query_request(UNICAST, &question));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* build packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_send_name_release_request_and_demand(UNICAST,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_process_Bnode_packet(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Guard against malformed packets */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (additional->name->addr_list.sin.sin_addr.s_addr == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->addr_list.forw = name->addr_list.back = &name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((entry = smb_netbios_cache_lookup_addr(name)) != 0) {
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 /* All query requests have to have question entry */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (question->question_type == NAME_QUESTION_TYPE_NBSTAT) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Name of "*" may be used to force node to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * divulge status for administrative purposes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * send only those names that are
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in the same scope as the scope
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * field in the request packet
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_process_Pnode_packet(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * always ignore UDP broadcast packets
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Guard against malformed packets */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (additional->name->addr_list.sin.sin_addr.s_addr == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw name->addr_list.forw = name->addr_list.back = &name->addr_list;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) smb_send_name_registration_response(addr, packet, 0);
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 /* All query requests have to have question entry */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * send response to the IP address and port
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * number from which the request was received.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * send response to the requestor
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (question->question_type == NAME_QUESTION_TYPE_NBSTAT) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Name of "*" may be used to force node to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * divulge status for administrative purposes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * send only those names that are
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in the same scope as the scope
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * field in the request packet
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_process_Mnode_packet(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightsmb_name_process_Hnode_packet(struct name_packet *packet, addr_entry_t *addr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netbios_name_tick
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Called once a second to handle name server timeouts.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while ((name = refresh_queue.head.forw) != &refresh_queue.head) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_name_find_name
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()
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((type != NBT_WKSTA) && (type != NBT_SERVER)) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_DEBUG, "nbns: name delete bad type (0x%02x)", type);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netbios_worker
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Process incoming request/response packets for Netbios
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * name service (on port 138).
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright if ((packet = smb_name_buf_to_packet(p->buf, p->length)) != NULL) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Reply packet */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Request packet */
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.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright for (i = 0; i < SMB_PI_MAX_WINS; ++i) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) smb_config_getstr(wins[i], ipstr, sizeof (ipstr));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_nbns[nbns_num].sinlen = sizeof (struct sockaddr_in);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smb_nbns[nbns_num].sin.sin_port = htons(IPPORT_NETBIOS_NS);
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic void
7b59d02d2a384be9a08087b14defadd214b3c1ddjb while (rc == 0) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (IS_UNIQUE(name->attributes) && IS_LOCAL(name->attributes)) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * Note that the node configuration must be setup before calling
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * smb_init_name_struct().
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS);
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 bcast_entry->sinlen = sizeof (struct sockaddr_in);
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;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host,
7b59d02d2a384be9a08087b14defadd214b3c1ddjb smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while ((name = delete_queue.head.forw) != &delete_queue.head) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright * NetBIOS Name Service (port 137)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Initialize reply_queue
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright (void) setsockopt(name_sock, SOL_SOCKET, SO_REUSEADDR, &flag,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) setsockopt(name_sock, SOL_SOCKET, SO_BROADCAST, &flag,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (flag));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bind(name_sock, (struct sockaddr *)&sin, sizeof (sin)) != 0) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright /* Sleep for 10 seconds and try again */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((len = recvfrom(name_sock, buf, MAX_DATAGRAM_LENGTH,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 0, (struct sockaddr *)&addr->sin, &addr->sinlen)) < 0) {
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright /* Sleep for 10 seconds and try again */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Ignore any incoming packets from myself... */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Launch a netbios worker to process the received packet.