1*da6c28aaSamw /* 2*da6c28aaSamw * CDDL HEADER START 3*da6c28aaSamw * 4*da6c28aaSamw * The contents of this file are subject to the terms of the 5*da6c28aaSamw * Common Development and Distribution License (the "License"). 6*da6c28aaSamw * You may not use this file except in compliance with the License. 7*da6c28aaSamw * 8*da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10*da6c28aaSamw * See the License for the specific language governing permissions 11*da6c28aaSamw * and limitations under the License. 12*da6c28aaSamw * 13*da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14*da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16*da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17*da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18*da6c28aaSamw * 19*da6c28aaSamw * CDDL HEADER END 20*da6c28aaSamw */ 21*da6c28aaSamw /* 22*da6c28aaSamw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*da6c28aaSamw * Use is subject to license terms. 24*da6c28aaSamw */ 25*da6c28aaSamw 26*da6c28aaSamw #pragma ident "%Z%%M% %I% %E% SMI" 27*da6c28aaSamw 28*da6c28aaSamw /* 29*da6c28aaSamw * Description: 30*da6c28aaSamw * 31*da6c28aaSamw * Contains base code for netbios name service. 32*da6c28aaSamw * 33*da6c28aaSamw * 34*da6c28aaSamw * 6. DEFINED CONSTANTS AND VARIABLES 35*da6c28aaSamw * 36*da6c28aaSamw * GENERAL: 37*da6c28aaSamw * 38*da6c28aaSamw * SCOPE_ID The name of the NetBIOS scope. 39*da6c28aaSamw * 40*da6c28aaSamw * This is expressed as a character 41*da6c28aaSamw * string meeting the requirements of 42*da6c28aaSamw * the domain name system and without 43*da6c28aaSamw * a leading or trailing "dot". 44*da6c28aaSamw * 45*da6c28aaSamw * An implementation may elect to make 46*da6c28aaSamw * this a single global value for the 47*da6c28aaSamw * node or allow it to be specified 48*da6c28aaSamw * with each separate NetBIOS name 49*da6c28aaSamw * (thus permitting cross-scope 50*da6c28aaSamw * references.) 51*da6c28aaSamw * 52*da6c28aaSamw * BROADCAST_ADDRESS An IP address composed of the 53*da6c28aaSamw * nodes's network and subnetwork 54*da6c28aaSamw * numbers with all remaining bits set 55*da6c28aaSamw * to one. 56*da6c28aaSamw * 57*da6c28aaSamw * I.e. "Specific subnet" broadcast 58*da6c28aaSamw * addressing according to section 2.3 59*da6c28aaSamw * of RFC 950. 60*da6c28aaSamw * 61*da6c28aaSamw * BCAST_REQ_RETRY_TIMEOUT 250 milliseconds. 62*da6c28aaSamw * An adaptive timer may be used. 63*da6c28aaSamw * 64*da6c28aaSamw * BCAST_REQ_RETRY_COUNT 3 65*da6c28aaSamw * 66*da6c28aaSamw * UCAST_REQ_RETRY_TIMEOUT 5 seconds 67*da6c28aaSamw * An adaptive timer may be used. 68*da6c28aaSamw * 69*da6c28aaSamw * UCAST_REQ_RETRY_COUNT 3 70*da6c28aaSamw * 71*da6c28aaSamw * MAX_DATAGRAM_LENGTH 576 bytes (default) 72*da6c28aaSamw * 73*da6c28aaSamw * 74*da6c28aaSamw * NAME SERVICE: 75*da6c28aaSamw * 76*da6c28aaSamw * REFRESH_TIMER Negotiated with NAME for each name. 77*da6c28aaSamw * 78*da6c28aaSamw * CONFLICT_TIMER 1 second 79*da6c28aaSamw * Implementations may chose a longer 80*da6c28aaSamw * value. 81*da6c28aaSamw * 82*da6c28aaSamw * 83*da6c28aaSamw * NAME_SERVICE_TCP_PORT 137 (decimal) 84*da6c28aaSamw * 85*da6c28aaSamw * NAME_SERVICE_UDP_PORT 137 (decimal) 86*da6c28aaSamw * 87*da6c28aaSamw * INFINITE_TTL 0 88*da6c28aaSamw */ 89*da6c28aaSamw 90*da6c28aaSamw #include <unistd.h> 91*da6c28aaSamw #include <syslog.h> 92*da6c28aaSamw #include <stdlib.h> 93*da6c28aaSamw #include <synch.h> 94*da6c28aaSamw #include <errno.h> 95*da6c28aaSamw #include <netdb.h> 96*da6c28aaSamw #include <sys/socket.h> 97*da6c28aaSamw #include <sys/sockio.h> 98*da6c28aaSamw #include <arpa/inet.h> 99*da6c28aaSamw #include <net/if_arp.h> 100*da6c28aaSamw 101*da6c28aaSamw #include <smbsrv/libsmbns.h> 102*da6c28aaSamw #include <smbns_netbios.h> 103*da6c28aaSamw 104*da6c28aaSamw #define NAME_HEADER_SIZE 12 105*da6c28aaSamw 106*da6c28aaSamw typedef struct name_reply { 107*da6c28aaSamw struct name_reply *forw; 108*da6c28aaSamw struct name_reply *back; 109*da6c28aaSamw struct name_packet *packet; 110*da6c28aaSamw struct addr_entry *addr; 111*da6c28aaSamw unsigned short name_trn_id; 112*da6c28aaSamw unsigned short flags; 113*da6c28aaSamw } name_reply; 114*da6c28aaSamw 115*da6c28aaSamw static struct name_reply reply_queue; 116*da6c28aaSamw static mutex_t rq_mtx; 117*da6c28aaSamw 118*da6c28aaSamw static mutex_t reply_mtx; 119*da6c28aaSamw static cond_t reply_cv; 120*da6c28aaSamw 121*da6c28aaSamw static name_queue_t delete_queue; 122*da6c28aaSamw static name_queue_t refresh_queue; 123*da6c28aaSamw 124*da6c28aaSamw /* 125*da6c28aaSamw * Flag to control whether or not NetBIOS name refresh requests 126*da6c28aaSamw * are logged. Set to non-zero to enable logging. 127*da6c28aaSamw */ 128*da6c28aaSamw 129*da6c28aaSamw static unsigned short netbios_name_transcation_id = 1; 130*da6c28aaSamw static int name_sock = 0; 131*da6c28aaSamw 132*da6c28aaSamw static int bcast_num = 0; 133*da6c28aaSamw static int nbns_num = 0; 134*da6c28aaSamw static struct addr_entry smb_bcast_list[SMB_PI_MAX_NETWORKS]; 135*da6c28aaSamw static struct addr_entry smb_nbns[SMB_PI_MAX_WINS]; 136*da6c28aaSamw 137*da6c28aaSamw static int smb_netbios_process_response(unsigned short, struct addr_entry *, 138*da6c28aaSamw struct name_packet *, uint32_t); 139*da6c28aaSamw 140*da6c28aaSamw static int smb_send_name_service_packet(struct addr_entry *addr, 141*da6c28aaSamw struct name_packet *packet); 142*da6c28aaSamw 143*da6c28aaSamw static int 144*da6c28aaSamw smb_end_node_challenge(struct name_reply *reply_info) 145*da6c28aaSamw { 146*da6c28aaSamw int rc; 147*da6c28aaSamw uint32_t retry; 148*da6c28aaSamw unsigned short tid; 149*da6c28aaSamw struct resource_record *answer; 150*da6c28aaSamw struct name_question question; 151*da6c28aaSamw struct addr_entry *addr; 152*da6c28aaSamw struct name_entry *destination; 153*da6c28aaSamw struct name_packet packet; 154*da6c28aaSamw struct timespec st; 155*da6c28aaSamw 156*da6c28aaSamw /* 157*da6c28aaSamw * The response packet has in it the address of the presumed owner 158*da6c28aaSamw * of the name. Challenge that owner. If owner either does not 159*da6c28aaSamw * respond or indicates that he no longer owns the name, claim the 160*da6c28aaSamw * name. Otherwise, the name cannot be claimed. 161*da6c28aaSamw */ 162*da6c28aaSamw 163*da6c28aaSamw if ((answer = reply_info->packet->answer) == 0) 164*da6c28aaSamw return (-1); 165*da6c28aaSamw 166*da6c28aaSamw destination = answer->name; 167*da6c28aaSamw question.name = answer->name; 168*da6c28aaSamw 169*da6c28aaSamw packet.info = NAME_QUERY_REQUEST | NM_FLAGS_UNICAST; 170*da6c28aaSamw packet.qdcount = 1; /* question entries */ 171*da6c28aaSamw packet.question = &question; 172*da6c28aaSamw packet.ancount = 0; /* answer recs */ 173*da6c28aaSamw packet.answer = NULL; 174*da6c28aaSamw packet.nscount = 0; /* authority recs */ 175*da6c28aaSamw packet.authority = NULL; 176*da6c28aaSamw packet.arcount = 0; /* additional recs */ 177*da6c28aaSamw packet.additional = NULL; 178*da6c28aaSamw 179*da6c28aaSamw addr = &destination->addr_list; 180*da6c28aaSamw for (retry = 0; retry < UCAST_REQ_RETRY_COUNT; retry++) { 181*da6c28aaSamw tid = netbios_name_transcation_id++; 182*da6c28aaSamw packet.name_trn_id = tid; 183*da6c28aaSamw if (smb_send_name_service_packet(addr, &packet) >= 0) { 184*da6c28aaSamw if ((rc = smb_netbios_process_response(tid, addr, 185*da6c28aaSamw &packet, UCAST_REQ_RETRY_TIMEOUT)) != 0) 186*da6c28aaSamw return (rc); 187*da6c28aaSamw } 188*da6c28aaSamw st.tv_sec = 0; 189*da6c28aaSamw st.tv_nsec = (UCAST_REQ_RETRY_TIMEOUT * 1000000); 190*da6c28aaSamw (void) nanosleep(&st, 0); 191*da6c28aaSamw } 192*da6c28aaSamw /* No reply */ 193*da6c28aaSamw return (0); 194*da6c28aaSamw } 195*da6c28aaSamw 196*da6c28aaSamw 197*da6c28aaSamw static struct name_reply * 198*da6c28aaSamw smb_name_get_reply(unsigned short tid, uint32_t timeout) 199*da6c28aaSamw { 200*da6c28aaSamw unsigned short info; 201*da6c28aaSamw struct resource_record *answer; 202*da6c28aaSamw struct name_reply *reply; 203*da6c28aaSamw uint32_t wait_time, to_save; /* in millisecond */ 204*da6c28aaSamw struct timeval wt; 205*da6c28aaSamw timestruc_t to; 206*da6c28aaSamw 207*da6c28aaSamw to_save = timeout; 208*da6c28aaSamw reply = (struct name_reply *)malloc(sizeof (struct name_reply)); 209*da6c28aaSamw if (reply != 0) { 210*da6c28aaSamw reply->flags = 0; 211*da6c28aaSamw reply->name_trn_id = tid; 212*da6c28aaSamw (void) mutex_lock(&rq_mtx); 213*da6c28aaSamw QUEUE_INSERT_TAIL(&reply_queue, reply); 214*da6c28aaSamw (void) mutex_unlock(&rq_mtx); 215*da6c28aaSamw 216*da6c28aaSamw for (;;) { 217*da6c28aaSamw (void) gettimeofday(&wt, 0); 218*da6c28aaSamw wait_time = wt.tv_usec / 1000; 219*da6c28aaSamw 220*da6c28aaSamw (void) mutex_lock(&reply_mtx); 221*da6c28aaSamw to.tv_sec = 0; 222*da6c28aaSamw to.tv_nsec = timeout * 1000000; 223*da6c28aaSamw (void) cond_reltimedwait(&reply_cv, &reply_mtx, &to); 224*da6c28aaSamw (void) mutex_unlock(&reply_mtx); 225*da6c28aaSamw 226*da6c28aaSamw if (reply->flags != 0) { 227*da6c28aaSamw info = reply->packet->info; 228*da6c28aaSamw if (PACKET_TYPE(info) == WACK_RESPONSE) { 229*da6c28aaSamw answer = reply->packet->answer; 230*da6c28aaSamw wait_time = (answer) ? 231*da6c28aaSamw TO_MILLISECONDS(answer->ttl) : 232*da6c28aaSamw DEFAULT_TTL; 233*da6c28aaSamw free(reply->addr); 234*da6c28aaSamw free(reply->packet); 235*da6c28aaSamw timeout = to_save + wait_time; 236*da6c28aaSamw reply->flags = 0; 237*da6c28aaSamw reply->name_trn_id = tid; 238*da6c28aaSamw (void) mutex_lock(&rq_mtx); 239*da6c28aaSamw QUEUE_INSERT_TAIL(&reply_queue, reply); 240*da6c28aaSamw (void) mutex_unlock(&rq_mtx); 241*da6c28aaSamw continue; 242*da6c28aaSamw } 243*da6c28aaSamw return (reply); 244*da6c28aaSamw } 245*da6c28aaSamw (void) gettimeofday(&wt, 0); 246*da6c28aaSamw wait_time = (wt.tv_usec / 1000) - wait_time; 247*da6c28aaSamw if (wait_time >= timeout) { 248*da6c28aaSamw (void) mutex_lock(&rq_mtx); 249*da6c28aaSamw QUEUE_CLIP(reply); 250*da6c28aaSamw (void) mutex_unlock(&rq_mtx); 251*da6c28aaSamw free(reply); 252*da6c28aaSamw break; 253*da6c28aaSamw } 254*da6c28aaSamw timeout -= wait_time; 255*da6c28aaSamw } 256*da6c28aaSamw } 257*da6c28aaSamw 258*da6c28aaSamw return (0); 259*da6c28aaSamw } 260*da6c28aaSamw 261*da6c28aaSamw static void 262*da6c28aaSamw smb_reply_ready(struct name_packet *packet, struct addr_entry *addr) 263*da6c28aaSamw { 264*da6c28aaSamw struct name_reply *reply; 265*da6c28aaSamw struct resource_record *answer; 266*da6c28aaSamw 267*da6c28aaSamw (void) mutex_lock(&rq_mtx); 268*da6c28aaSamw for (reply = reply_queue.forw; reply != &reply_queue; 269*da6c28aaSamw reply = reply->forw) { 270*da6c28aaSamw if (reply->name_trn_id == packet->name_trn_id) { 271*da6c28aaSamw QUEUE_CLIP(reply); 272*da6c28aaSamw (void) mutex_unlock(&rq_mtx); 273*da6c28aaSamw 274*da6c28aaSamw reply->addr = addr; 275*da6c28aaSamw reply->packet = packet; 276*da6c28aaSamw 277*da6c28aaSamw (void) mutex_lock(&reply_mtx); 278*da6c28aaSamw reply->flags |= 0x0001; /* reply ready */ 279*da6c28aaSamw (void) cond_signal(&reply_cv); 280*da6c28aaSamw (void) mutex_unlock(&reply_mtx); 281*da6c28aaSamw 282*da6c28aaSamw return; 283*da6c28aaSamw } 284*da6c28aaSamw } 285*da6c28aaSamw (void) mutex_unlock(&rq_mtx); 286*da6c28aaSamw 287*da6c28aaSamw /* Presumably nobody is waiting any more... */ 288*da6c28aaSamw free(addr); 289*da6c28aaSamw 290*da6c28aaSamw answer = packet->answer; 291*da6c28aaSamw if (answer) 292*da6c28aaSamw smb_netbios_name_freeaddrs(answer->name); 293*da6c28aaSamw free(packet); 294*da6c28aaSamw } 295*da6c28aaSamw 296*da6c28aaSamw static int 297*da6c28aaSamw smb_netbios_process_response(unsigned short tid, struct addr_entry *addr, 298*da6c28aaSamw struct name_packet *packet, uint32_t timeout) 299*da6c28aaSamw { 300*da6c28aaSamw int rc = 0; 301*da6c28aaSamw unsigned short info; 302*da6c28aaSamw struct name_reply *reply; 303*da6c28aaSamw struct resource_record *answer; 304*da6c28aaSamw struct name_entry *name; 305*da6c28aaSamw struct name_entry *entry; 306*da6c28aaSamw struct name_question *question; 307*da6c28aaSamw uint32_t ttl; 308*da6c28aaSamw 309*da6c28aaSamw if ((reply = smb_name_get_reply(tid, timeout)) == 0) { 310*da6c28aaSamw return (0); /* No reply: retry */ 311*da6c28aaSamw } 312*da6c28aaSamw info = reply->packet->info; 313*da6c28aaSamw answer = reply->packet->answer; 314*da6c28aaSamw 315*da6c28aaSamw /* response */ 316*da6c28aaSamw switch (PACKET_TYPE(info)) { 317*da6c28aaSamw case NAME_QUERY_RESPONSE: 318*da6c28aaSamw if (POSITIVE_RESPONSE(info)) { 319*da6c28aaSamw addr = &answer->name->addr_list; 320*da6c28aaSamw do { 321*da6c28aaSamw /* 322*da6c28aaSamw * Make sure that remote name is not 323*da6c28aaSamw * flagged local 324*da6c28aaSamw */ 325*da6c28aaSamw addr->attributes &= ~NAME_ATTR_LOCAL; 326*da6c28aaSamw 327*da6c28aaSamw addr->refresh_ttl = addr->ttl = 328*da6c28aaSamw (answer && answer->ttl) ? 329*da6c28aaSamw (answer->ttl >> 1) : 330*da6c28aaSamw TO_SECONDS(DEFAULT_TTL); 331*da6c28aaSamw addr = addr->forw; 332*da6c28aaSamw } while (addr != &answer->name->addr_list); 333*da6c28aaSamw smb_netbios_name_dump(answer->name); 334*da6c28aaSamw (void) smb_netbios_cache_insert_list(answer->name); 335*da6c28aaSamw rc = 1; 336*da6c28aaSamw } else { 337*da6c28aaSamw rc = -1; 338*da6c28aaSamw } 339*da6c28aaSamw break; 340*da6c28aaSamw 341*da6c28aaSamw case NAME_REGISTRATION_RESPONSE: 342*da6c28aaSamw if (NEGATIVE_RESPONSE(info)) { 343*da6c28aaSamw if (RCODE(info) == RCODE_CFT_ERR) { 344*da6c28aaSamw if (answer == 0) { 345*da6c28aaSamw rc = -RCODE(info); 346*da6c28aaSamw break; 347*da6c28aaSamw } 348*da6c28aaSamw 349*da6c28aaSamw name = answer->name; 350*da6c28aaSamw entry = smb_netbios_cache_lookup(name); 351*da6c28aaSamw if (entry) { 352*da6c28aaSamw /* 353*da6c28aaSamw * a name in the state "conflict 354*da6c28aaSamw * detected" does not "logically" exist 355*da6c28aaSamw * on that node. No further session 356*da6c28aaSamw * will be accepted on that name. 357*da6c28aaSamw * No datagrams can be sent against 358*da6c28aaSamw * that name. 359*da6c28aaSamw * Such an entry will not be used for 360*da6c28aaSamw * purposes of processing incoming 361*da6c28aaSamw * request packets. 362*da6c28aaSamw * The only valid user NetBIOS operation 363*da6c28aaSamw * against such a name is DELETE NAME. 364*da6c28aaSamw */ 365*da6c28aaSamw entry->attributes |= NAME_ATTR_CONFLICT; 366*da6c28aaSamw syslog(LOG_DEBUG, 367*da6c28aaSamw "NETBIOS Name conflict: %15.15s", 368*da6c28aaSamw entry->name); 369*da6c28aaSamw smb_netbios_cache_unlock_entry(entry); 370*da6c28aaSamw } 371*da6c28aaSamw } 372*da6c28aaSamw rc = -RCODE(info); 373*da6c28aaSamw break; 374*da6c28aaSamw } 375*da6c28aaSamw 376*da6c28aaSamw /* 377*da6c28aaSamw * name can be added: 378*da6c28aaSamw * adjust refresh timeout value, 379*da6c28aaSamw * TTL, for this name 380*da6c28aaSamw */ 381*da6c28aaSamw question = packet->question; 382*da6c28aaSamw ttl = (answer && answer->ttl) ? answer->ttl >> 1 383*da6c28aaSamw : TO_SECONDS(DEFAULT_TTL); 384*da6c28aaSamw if ((entry = smb_netbios_cache_lookup(question->name)) != 0) { 385*da6c28aaSamw addr = &entry->addr_list; 386*da6c28aaSamw do { 387*da6c28aaSamw if ((addr->refresh_ttl == 0) || 388*da6c28aaSamw (ttl < addr->refresh_ttl)) 389*da6c28aaSamw addr->refresh_ttl = addr->ttl = ttl; 390*da6c28aaSamw addr = addr->forw; 391*da6c28aaSamw } while (addr != &entry->addr_list); 392*da6c28aaSamw smb_netbios_cache_unlock_entry(entry); 393*da6c28aaSamw } 394*da6c28aaSamw 395*da6c28aaSamw rc = 1; 396*da6c28aaSamw break; 397*da6c28aaSamw 398*da6c28aaSamw case NAME_RELEASE_RESPONSE: 399*da6c28aaSamw rc = 1; 400*da6c28aaSamw break; 401*da6c28aaSamw 402*da6c28aaSamw case END_NODE_CHALLENGE_REGISTRATION_REQUEST: 403*da6c28aaSamw /* 404*da6c28aaSamw * The response packet has in it the 405*da6c28aaSamw * address of the presumed owner of the 406*da6c28aaSamw * name. Challenge that owner. If 407*da6c28aaSamw * owner either does not respond or 408*da6c28aaSamw * indicates that he no longer owns the 409*da6c28aaSamw * name, claim the name. Otherwise, 410*da6c28aaSamw * the name cannot be claimed. 411*da6c28aaSamw */ 412*da6c28aaSamw rc = smb_end_node_challenge(reply); 413*da6c28aaSamw break; 414*da6c28aaSamw 415*da6c28aaSamw default: 416*da6c28aaSamw rc = 0; 417*da6c28aaSamw break; 418*da6c28aaSamw } 419*da6c28aaSamw 420*da6c28aaSamw if (answer) 421*da6c28aaSamw smb_netbios_name_freeaddrs(answer->name); 422*da6c28aaSamw free(reply->addr); 423*da6c28aaSamw free(reply->packet); 424*da6c28aaSamw free(reply); 425*da6c28aaSamw return (rc); /* retry */ 426*da6c28aaSamw } 427*da6c28aaSamw 428*da6c28aaSamw /* 429*da6c28aaSamw * smb_name_buf_from_packet 430*da6c28aaSamw * 431*da6c28aaSamw * Description: 432*da6c28aaSamw * Convert a NetBIOS Name Server Packet Block (npb) 433*da6c28aaSamw * into the bits and bytes destined for the wire. 434*da6c28aaSamw * The "buf" is used as a heap. 435*da6c28aaSamw * 436*da6c28aaSamw * Inputs: 437*da6c28aaSamw * char * buf -> Buffer, from the wire 438*da6c28aaSamw * unsigned n_buf -> Length of 'buf' 439*da6c28aaSamw * name_packet *npb -> Packet block, decode into 440*da6c28aaSamw * unsigned n_npb -> Max bytes in 'npb' 441*da6c28aaSamw * 442*da6c28aaSamw * Returns: 443*da6c28aaSamw * >0 -> Encode successful, value is length of packet in "buf" 444*da6c28aaSamw * -1 -> Hard error, can not possibly encode 445*da6c28aaSamw * -2 -> Need more memory in buf -- it's too small 446*da6c28aaSamw */ 447*da6c28aaSamw 448*da6c28aaSamw static int 449*da6c28aaSamw smb_name_buf_from_packet(unsigned char *buf, 450*da6c28aaSamw int n_buf, 451*da6c28aaSamw struct name_packet *npb) 452*da6c28aaSamw { 453*da6c28aaSamw struct addr_entry *raddr; 454*da6c28aaSamw unsigned char *heap = buf; 455*da6c28aaSamw unsigned char *end_heap = heap + n_buf; 456*da6c28aaSamw unsigned char *dnptrs[32]; 457*da6c28aaSamw unsigned char comp_name_buf[MAX_NAME_LENGTH]; 458*da6c28aaSamw unsigned int tmp; 459*da6c28aaSamw int i, step; 460*da6c28aaSamw 461*da6c28aaSamw if (n_buf < NAME_HEADER_SIZE) 462*da6c28aaSamw return (-1); /* no header, impossible */ 463*da6c28aaSamw 464*da6c28aaSamw dnptrs[0] = heap; 465*da6c28aaSamw dnptrs[1] = 0; 466*da6c28aaSamw 467*da6c28aaSamw BE_OUT16(heap, npb->name_trn_id); 468*da6c28aaSamw heap += 2; 469*da6c28aaSamw 470*da6c28aaSamw BE_OUT16(heap, npb->info); 471*da6c28aaSamw heap += 2; 472*da6c28aaSamw 473*da6c28aaSamw BE_OUT16(heap, npb->qdcount); 474*da6c28aaSamw heap += 2; 475*da6c28aaSamw 476*da6c28aaSamw BE_OUT16(heap, npb->ancount); 477*da6c28aaSamw heap += 2; 478*da6c28aaSamw 479*da6c28aaSamw BE_OUT16(heap, npb->nscount); 480*da6c28aaSamw heap += 2; 481*da6c28aaSamw 482*da6c28aaSamw BE_OUT16(heap, npb->arcount); 483*da6c28aaSamw heap += 2; 484*da6c28aaSamw 485*da6c28aaSamw for (i = 0; i < npb->qdcount; i++) { 486*da6c28aaSamw if ((heap + 34 + 4) > end_heap) 487*da6c28aaSamw return (-2); 488*da6c28aaSamw 489*da6c28aaSamw (void) smb_first_level_name_encode(npb->question[i].name, 490*da6c28aaSamw comp_name_buf, sizeof (comp_name_buf)); 491*da6c28aaSamw (void) strcpy((char *)heap, (char *)comp_name_buf); 492*da6c28aaSamw heap += strlen((char *)comp_name_buf) + 1; 493*da6c28aaSamw 494*da6c28aaSamw BE_OUT16(heap, npb->question[i].question_type); 495*da6c28aaSamw heap += 2; 496*da6c28aaSamw 497*da6c28aaSamw BE_OUT16(heap, npb->question[i].question_class); 498*da6c28aaSamw heap += 2; 499*da6c28aaSamw } 500*da6c28aaSamw 501*da6c28aaSamw for (step = 1; step <= 3; step++) { 502*da6c28aaSamw struct resource_record *nrr; 503*da6c28aaSamw int n; 504*da6c28aaSamw 505*da6c28aaSamw /* truly ugly, but saves code copying */ 506*da6c28aaSamw if (step == 1) { 507*da6c28aaSamw n = npb->ancount; 508*da6c28aaSamw nrr = npb->answer; 509*da6c28aaSamw } else if (step == 2) { 510*da6c28aaSamw n = npb->nscount; 511*da6c28aaSamw nrr = npb->authority; 512*da6c28aaSamw } else { /* step == 3 */ 513*da6c28aaSamw n = npb->arcount; 514*da6c28aaSamw nrr = npb->additional; 515*da6c28aaSamw } 516*da6c28aaSamw 517*da6c28aaSamw for (i = 0; i < n; i++) { 518*da6c28aaSamw if ((heap + 34 + 10) > end_heap) 519*da6c28aaSamw return (-2); 520*da6c28aaSamw 521*da6c28aaSamw (void) smb_first_level_name_encode(nrr->name, 522*da6c28aaSamw comp_name_buf, sizeof (comp_name_buf)); 523*da6c28aaSamw (void) strcpy((char *)heap, (char *)comp_name_buf); 524*da6c28aaSamw heap += strlen((char *)comp_name_buf) + 1; 525*da6c28aaSamw 526*da6c28aaSamw BE_OUT16(heap, nrr[i].rr_type); 527*da6c28aaSamw heap += 2; 528*da6c28aaSamw 529*da6c28aaSamw BE_OUT16(heap, nrr[i].rr_class); 530*da6c28aaSamw heap += 2; 531*da6c28aaSamw 532*da6c28aaSamw BE_OUT32(heap, nrr[i].ttl); 533*da6c28aaSamw heap += 4; 534*da6c28aaSamw 535*da6c28aaSamw BE_OUT16(heap, nrr[i].rdlength); 536*da6c28aaSamw heap += 2; 537*da6c28aaSamw 538*da6c28aaSamw if ((tmp = nrr[i].rdlength) > 0) { 539*da6c28aaSamw if ((heap + tmp) > end_heap) 540*da6c28aaSamw return (-2); 541*da6c28aaSamw 542*da6c28aaSamw if (nrr[i].rr_type == NAME_RR_TYPE_NB && 543*da6c28aaSamw nrr[i].rr_class == NAME_RR_CLASS_IN && 544*da6c28aaSamw tmp >= 6 && nrr[i].rdata == 0) { 545*da6c28aaSamw tmp = nrr[i].name->attributes & 546*da6c28aaSamw (NAME_ATTR_GROUP | 547*da6c28aaSamw NAME_ATTR_OWNER_NODE_TYPE); 548*da6c28aaSamw BE_OUT16(heap, tmp); 549*da6c28aaSamw heap += 2; 550*da6c28aaSamw 551*da6c28aaSamw raddr = &nrr[i].name->addr_list; 552*da6c28aaSamw (void) memcpy(heap, 553*da6c28aaSamw &raddr->sin.sin_addr.s_addr, 554*da6c28aaSamw sizeof (uint32_t)); 555*da6c28aaSamw heap += 4; 556*da6c28aaSamw } else { 557*da6c28aaSamw bcopy(nrr[i].rdata, heap, tmp); 558*da6c28aaSamw heap += tmp; 559*da6c28aaSamw } 560*da6c28aaSamw } 561*da6c28aaSamw } 562*da6c28aaSamw } 563*da6c28aaSamw return (heap - buf); 564*da6c28aaSamw } 565*da6c28aaSamw 566*da6c28aaSamw /* 567*da6c28aaSamw * strnchr 568*da6c28aaSamw * 569*da6c28aaSamw * Lookup for character 'c' in first 'n' chars of string 's'. 570*da6c28aaSamw * Returns pointer to the found char, otherwise returns 0. 571*da6c28aaSamw */ 572*da6c28aaSamw static char * 573*da6c28aaSamw strnchr(const char *s, char c, int n) 574*da6c28aaSamw { 575*da6c28aaSamw char *ps = (char *)s; 576*da6c28aaSamw char *es = (char *)s + n; 577*da6c28aaSamw 578*da6c28aaSamw while (ps < es && *ps) { 579*da6c28aaSamw if (*ps == c) 580*da6c28aaSamw return (ps); 581*da6c28aaSamw 582*da6c28aaSamw ++ps; 583*da6c28aaSamw } 584*da6c28aaSamw 585*da6c28aaSamw if (*ps == '\0' && c == '\0') 586*da6c28aaSamw return (ps); 587*da6c28aaSamw 588*da6c28aaSamw return (0); 589*da6c28aaSamw } 590*da6c28aaSamw 591*da6c28aaSamw /*ARGSUSED*/ 592*da6c28aaSamw static int 593*da6c28aaSamw is_multihome(char *name) 594*da6c28aaSamw { 595*da6c28aaSamw return ((smb_nic_get_num() > 1) ? 1 : 0); 596*da6c28aaSamw } 597*da6c28aaSamw 598*da6c28aaSamw /* 599*da6c28aaSamw * smb_netbios_getname 600*da6c28aaSamw * 601*da6c28aaSamw * Get the Netbios name part of the given record. 602*da6c28aaSamw * Does some boundary checks. 603*da6c28aaSamw * 604*da6c28aaSamw * Returns the name length on success, otherwise 605*da6c28aaSamw * returns 0. 606*da6c28aaSamw */ 607*da6c28aaSamw static int 608*da6c28aaSamw smb_netbios_getname(char *name, char *buf, char *buf_end) 609*da6c28aaSamw { 610*da6c28aaSamw char *name_end; 611*da6c28aaSamw int name_len; 612*da6c28aaSamw 613*da6c28aaSamw if (buf >= buf_end) { 614*da6c28aaSamw /* no room for a NB name */ 615*da6c28aaSamw return (0); 616*da6c28aaSamw } 617*da6c28aaSamw 618*da6c28aaSamw name_end = strnchr(buf, '\0', buf_end - buf + 1); 619*da6c28aaSamw if (name_end == 0) { 620*da6c28aaSamw /* not a valid NB name */ 621*da6c28aaSamw return (0); 622*da6c28aaSamw } 623*da6c28aaSamw 624*da6c28aaSamw name_len = name_end - buf + 1; 625*da6c28aaSamw 626*da6c28aaSamw (void) strlcpy(name, buf, name_len); 627*da6c28aaSamw return (name_len); 628*da6c28aaSamw } 629*da6c28aaSamw 630*da6c28aaSamw 631*da6c28aaSamw /* 632*da6c28aaSamw * smb_name_buf_to_packet 633*da6c28aaSamw * 634*da6c28aaSamw * Description: 635*da6c28aaSamw * Convert the bits and bytes that came from the wire 636*da6c28aaSamw * into a NetBIOS Name Server Packet Block (npb). 637*da6c28aaSamw * The "block" is used as a heap. 638*da6c28aaSamw * 639*da6c28aaSamw * Inputs: 640*da6c28aaSamw * char * buf -> Buffer, from the wire 641*da6c28aaSamw * int n_buf -> Length of 'buf' 642*da6c28aaSamw * name_packet *npb -> Packet block, decode into 643*da6c28aaSamw * int n_npb -> Max bytes in 'npb' 644*da6c28aaSamw * 645*da6c28aaSamw * Returns: 646*da6c28aaSamw * >0 -> Decode (parse) successful, value is byte length of npb 647*da6c28aaSamw * -1 -> Hard error, can not possibly decode 648*da6c28aaSamw * -2 -> Need more memory in npb -- it's too small 649*da6c28aaSamw */ 650*da6c28aaSamw 651*da6c28aaSamw static struct name_packet * 652*da6c28aaSamw smb_name_buf_to_packet(char *buf, int n_buf) 653*da6c28aaSamw { 654*da6c28aaSamw struct name_packet *npb; 655*da6c28aaSamw unsigned char *heap; 656*da6c28aaSamw unsigned char *scan = (unsigned char *)buf; 657*da6c28aaSamw unsigned char *scan_end = scan + n_buf; 658*da6c28aaSamw char name_buf[MAX_NAME_LENGTH]; 659*da6c28aaSamw struct resource_record *nrr = 0; 660*da6c28aaSamw int rc, i, n, nn, ns; 661*da6c28aaSamw unsigned short name_trn_id, info; 662*da6c28aaSamw unsigned short qdcount, ancount, nscount, arcount; 663*da6c28aaSamw struct addr_entry *next; 664*da6c28aaSamw int name_len; 665*da6c28aaSamw 666*da6c28aaSamw if (n_buf < NAME_HEADER_SIZE) { 667*da6c28aaSamw /* truncated header */ 668*da6c28aaSamw syslog(LOG_DEBUG, "SmbNBNS: packet is too short (%d)", 669*da6c28aaSamw n_buf); 670*da6c28aaSamw return (0); 671*da6c28aaSamw } 672*da6c28aaSamw 673*da6c28aaSamw name_trn_id = BE_IN16(scan); scan += 2; 674*da6c28aaSamw info = BE_IN16(scan); scan += 2; 675*da6c28aaSamw qdcount = BE_IN16(scan); scan += 2; 676*da6c28aaSamw ancount = BE_IN16(scan); scan += 2; 677*da6c28aaSamw nscount = BE_IN16(scan); scan += 2; 678*da6c28aaSamw arcount = BE_IN16(scan); scan += 2; 679*da6c28aaSamw 680*da6c28aaSamw ns = sizeof (struct name_entry); 681*da6c28aaSamw n = n_buf + sizeof (struct name_packet) + 682*da6c28aaSamw ((unsigned)qdcount * (sizeof (struct name_question) + ns)) + 683*da6c28aaSamw ((unsigned)ancount * (sizeof (struct resource_record) + ns)) + 684*da6c28aaSamw ((unsigned)nscount * (sizeof (struct resource_record) + ns)) + 685*da6c28aaSamw ((unsigned)arcount * (sizeof (struct resource_record) + ns)); 686*da6c28aaSamw 687*da6c28aaSamw if ((npb = (struct name_packet *)malloc(n)) == 0) { 688*da6c28aaSamw return (0); 689*da6c28aaSamw } 690*da6c28aaSamw bzero(npb, n); 691*da6c28aaSamw 692*da6c28aaSamw heap = npb->block_data; 693*da6c28aaSamw npb->name_trn_id = name_trn_id; 694*da6c28aaSamw npb->info = info; 695*da6c28aaSamw npb->qdcount = qdcount; 696*da6c28aaSamw npb->ancount = ancount; 697*da6c28aaSamw npb->nscount = nscount; 698*da6c28aaSamw npb->arcount = arcount; 699*da6c28aaSamw 700*da6c28aaSamw /* scan is in position for question entries */ 701*da6c28aaSamw 702*da6c28aaSamw /* 703*da6c28aaSamw * Measure the space needed for the tables 704*da6c28aaSamw */ 705*da6c28aaSamw if (qdcount > 0) { 706*da6c28aaSamw /* LINTED - E_BAD_PTR_CAST_ALIGN */ 707*da6c28aaSamw npb->question = (struct name_question *)heap; 708*da6c28aaSamw heap += qdcount * sizeof (struct name_question); 709*da6c28aaSamw for (i = 0; i < qdcount; i++) { 710*da6c28aaSamw /* LINTED - E_BAD_PTR_CAST_ALIGN */ 711*da6c28aaSamw npb->question[i].name = (struct name_entry *)heap; 712*da6c28aaSamw heap += sizeof (struct name_entry); 713*da6c28aaSamw } 714*da6c28aaSamw } 715*da6c28aaSamw 716*da6c28aaSamw /* LINTED - E_BAD_PTR_CAST_ALIGN */ 717*da6c28aaSamw nrr = (struct resource_record *)heap; 718*da6c28aaSamw 719*da6c28aaSamw if (ancount > 0) { 720*da6c28aaSamw /* LINTED - E_BAD_PTR_CAST_ALIGN */ 721*da6c28aaSamw npb->answer = (struct resource_record *)heap; 722*da6c28aaSamw heap += ancount * sizeof (struct resource_record); 723*da6c28aaSamw } 724*da6c28aaSamw 725*da6c28aaSamw if (nscount > 0) { 726*da6c28aaSamw /* LINTED - E_BAD_PTR_CAST_ALIGN */ 727*da6c28aaSamw npb->authority = (struct resource_record *)heap; 728*da6c28aaSamw heap += nscount * sizeof (struct resource_record); 729*da6c28aaSamw } 730*da6c28aaSamw 731*da6c28aaSamw if (arcount > 0) { 732*da6c28aaSamw /* LINTED - E_BAD_PTR_CAST_ALIGN */ 733*da6c28aaSamw npb->additional = (struct resource_record *)heap; 734*da6c28aaSamw heap += arcount * sizeof (struct resource_record); 735*da6c28aaSamw } 736*da6c28aaSamw 737*da6c28aaSamw /* 738*da6c28aaSamw * Populate each resource_record's .name field. 739*da6c28aaSamw * Done as a second pass so that all resource records 740*da6c28aaSamw * (answer, authority, additional) are consecutive via nrr[i]. 741*da6c28aaSamw */ 742*da6c28aaSamw for (i = 0; i < (ancount + nscount + arcount); i++) { 743*da6c28aaSamw /* LINTED - E_BAD_PTR_CAST_ALIGN */ 744*da6c28aaSamw nrr[i].name = (struct name_entry *)heap; 745*da6c28aaSamw heap += sizeof (struct name_entry); 746*da6c28aaSamw } 747*da6c28aaSamw 748*da6c28aaSamw 749*da6c28aaSamw for (i = 0; i < npb->qdcount; i++) { 750*da6c28aaSamw name_len = smb_netbios_getname(name_buf, (char *)scan, 751*da6c28aaSamw (char *)scan_end); 752*da6c28aaSamw if (name_len <= 0) { 753*da6c28aaSamw free(npb); 754*da6c28aaSamw return (0); 755*da6c28aaSamw } 756*da6c28aaSamw 757*da6c28aaSamw smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0, 758*da6c28aaSamw npb->question[i].name); 759*da6c28aaSamw rc = smb_first_level_name_decode((unsigned char *)name_buf, 760*da6c28aaSamw npb->question[i].name); 761*da6c28aaSamw if (rc < 0) { 762*da6c28aaSamw /* Couldn't decode the question name */ 763*da6c28aaSamw free(npb); 764*da6c28aaSamw return (0); 765*da6c28aaSamw } 766*da6c28aaSamw 767*da6c28aaSamw scan += name_len; 768*da6c28aaSamw if (scan + 4 > scan_end) { 769*da6c28aaSamw /* no room for Question Type(2) and Class(2) fields */ 770*da6c28aaSamw free(npb); 771*da6c28aaSamw return (0); 772*da6c28aaSamw } 773*da6c28aaSamw 774*da6c28aaSamw npb->question[i].question_type = BE_IN16(scan); scan += 2; 775*da6c28aaSamw npb->question[i].question_class = BE_IN16(scan); scan += 2; 776*da6c28aaSamw } 777*da6c28aaSamw 778*da6c28aaSamw /* 779*da6c28aaSamw * Cheat. Remaining sections are of the same resource_record 780*da6c28aaSamw * format. Table space is consecutive. 781*da6c28aaSamw */ 782*da6c28aaSamw 783*da6c28aaSamw for (i = 0; i < (ancount + nscount + arcount); i++) { 784*da6c28aaSamw if (scan[0] == 0xc0) { 785*da6c28aaSamw /* Namebuf is reused... */ 786*da6c28aaSamw rc = 2; 787*da6c28aaSamw } else { 788*da6c28aaSamw name_len = smb_netbios_getname(name_buf, (char *)scan, 789*da6c28aaSamw (char *)scan_end); 790*da6c28aaSamw if (name_len <= 0) { 791*da6c28aaSamw free(npb); 792*da6c28aaSamw return (0); 793*da6c28aaSamw } 794*da6c28aaSamw rc = name_len; 795*da6c28aaSamw } 796*da6c28aaSamw scan += rc; 797*da6c28aaSamw 798*da6c28aaSamw if (scan + 10 > scan_end) { 799*da6c28aaSamw /* 800*da6c28aaSamw * no room for RR_TYPE (2), RR_CLASS (2), TTL (4) and 801*da6c28aaSamw * RDLENGTH (2) fields. 802*da6c28aaSamw */ 803*da6c28aaSamw free(npb); 804*da6c28aaSamw return (0); 805*da6c28aaSamw } 806*da6c28aaSamw 807*da6c28aaSamw smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0, 808*da6c28aaSamw nrr[i].name); 809*da6c28aaSamw if ((rc = smb_first_level_name_decode((unsigned char *)name_buf, 810*da6c28aaSamw nrr[i].name)) < 0) { 811*da6c28aaSamw free(npb); 812*da6c28aaSamw return (0); 813*da6c28aaSamw } 814*da6c28aaSamw 815*da6c28aaSamw nrr[i].rr_type = BE_IN16(scan); scan += 2; 816*da6c28aaSamw nrr[i].rr_class = BE_IN16(scan); scan += 2; 817*da6c28aaSamw nrr[i].ttl = BE_IN32(scan); scan += 4; 818*da6c28aaSamw nrr[i].rdlength = BE_IN16(scan); scan += 2; 819*da6c28aaSamw 820*da6c28aaSamw if ((n = nrr[i].rdlength) > 0) { 821*da6c28aaSamw if ((scan + n) > scan_end) { 822*da6c28aaSamw /* no room for RDATA */ 823*da6c28aaSamw free(npb); 824*da6c28aaSamw return (0); 825*da6c28aaSamw } 826*da6c28aaSamw bcopy(scan, heap, n); 827*da6c28aaSamw 828*da6c28aaSamw nn = n; 829*da6c28aaSamw if (nrr[i].rr_type == 0x0020 && 830*da6c28aaSamw nrr[i].rr_class == 0x01 && n >= 6) { 831*da6c28aaSamw while (nn) { 832*da6c28aaSamw if (nn == 6) 833*da6c28aaSamw next = &nrr[i].name->addr_list; 834*da6c28aaSamw else { 835*da6c28aaSamw next = (struct addr_entry *) 836*da6c28aaSamw malloc( 837*da6c28aaSamw sizeof (struct addr_entry)); 838*da6c28aaSamw if (next == 0) { 839*da6c28aaSamw /* not enough memory */ 840*da6c28aaSamw free(npb); 841*da6c28aaSamw return (0); 842*da6c28aaSamw } 843*da6c28aaSamw QUEUE_INSERT_TAIL( 844*da6c28aaSamw &nrr[i].name->addr_list, 845*da6c28aaSamw next); 846*da6c28aaSamw } 847*da6c28aaSamw nrr[i].name->attributes = 848*da6c28aaSamw BE_IN16(scan); 849*da6c28aaSamw next->sin.sin_family = AF_INET; 850*da6c28aaSamw next->sinlen = sizeof (next->sin); 851*da6c28aaSamw (void) memcpy( 852*da6c28aaSamw &next->sin.sin_addr.s_addr, 853*da6c28aaSamw scan + 2, sizeof (uint32_t)); 854*da6c28aaSamw next->sin.sin_port = 855*da6c28aaSamw htons(DGM_SRVC_UDP_PORT); 856*da6c28aaSamw nn -= 6; 857*da6c28aaSamw scan += 6; 858*da6c28aaSamw } 859*da6c28aaSamw } else { 860*da6c28aaSamw nrr[i].rdata = heap; 861*da6c28aaSamw scan += n; 862*da6c28aaSamw } 863*da6c28aaSamw heap += n; 864*da6c28aaSamw } 865*da6c28aaSamw } 866*da6c28aaSamw return (npb); 867*da6c28aaSamw } 868*da6c28aaSamw 869*da6c28aaSamw 870*da6c28aaSamw /* 871*da6c28aaSamw * smb_send_name_service_packet 872*da6c28aaSamw * 873*da6c28aaSamw * Description: 874*da6c28aaSamw * 875*da6c28aaSamw * Send out a name service packet to proper destination. 876*da6c28aaSamw * 877*da6c28aaSamw * Inputs: 878*da6c28aaSamw * struct netbios_name *dest -> NETBIOS name of destination 879*da6c28aaSamw * struct name_packet *packet -> Packet to send 880*da6c28aaSamw * 881*da6c28aaSamw * Returns: 882*da6c28aaSamw * success -> >0 883*da6c28aaSamw * failure -> <=0 884*da6c28aaSamw */ 885*da6c28aaSamw 886*da6c28aaSamw static int 887*da6c28aaSamw smb_send_name_service_packet(struct addr_entry *addr, 888*da6c28aaSamw struct name_packet *packet) 889*da6c28aaSamw { 890*da6c28aaSamw unsigned char buf[MAX_DATAGRAM_LENGTH]; 891*da6c28aaSamw int len; 892*da6c28aaSamw 893*da6c28aaSamw if ((len = smb_name_buf_from_packet(buf, sizeof (buf), packet)) < 0) { 894*da6c28aaSamw errno = EINVAL; 895*da6c28aaSamw return (-1); 896*da6c28aaSamw } 897*da6c28aaSamw 898*da6c28aaSamw return (sendto(name_sock, buf, len, MSG_EOR, 899*da6c28aaSamw (struct sockaddr *)&addr->sin, addr->sinlen)); 900*da6c28aaSamw } 901*da6c28aaSamw 902*da6c28aaSamw /* 903*da6c28aaSamw * 4.2.1.1. HEADER 904*da6c28aaSamw * 905*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 906*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 907*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 908*da6c28aaSamw * | NAME_TRN_ID | OPCODE | NM_FLAGS | RCODE | 909*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 910*da6c28aaSamw * | QDCOUNT | ANCOUNT | 911*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 912*da6c28aaSamw * | NSCOUNT | ARCOUNT | 913*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 914*da6c28aaSamw * 915*da6c28aaSamw * Field Description 916*da6c28aaSamw * 917*da6c28aaSamw * NAME_TRN_ID Transaction ID for Name Service Transaction. 918*da6c28aaSamw * Requester places a unique value for each active 919*da6c28aaSamw * transaction. Responder puts NAME_TRN_ID value 920*da6c28aaSamw * from request packet in response packet. 921*da6c28aaSamw * 922*da6c28aaSamw * OPCODE Packet type code, see table below. 923*da6c28aaSamw * 924*da6c28aaSamw * NM_FLAGS Flags for operation, see table below. 925*da6c28aaSamw * 926*da6c28aaSamw * RCODE Result codes of request. Table of RCODE values 927*da6c28aaSamw * for each response packet below. 928*da6c28aaSamw * 929*da6c28aaSamw * QDCOUNT Unsigned 16 bit integer specifying the number of 930*da6c28aaSamw * entries in the question section of a Name 931*da6c28aaSamw * 932*da6c28aaSamw * Service packet. Always zero (0) for responses. 933*da6c28aaSamw * Must be non-zero for all NetBIOS Name requests. 934*da6c28aaSamw * 935*da6c28aaSamw * ANCOUNT Unsigned 16 bit integer specifying the number of 936*da6c28aaSamw * resource records in the answer section of a Name 937*da6c28aaSamw * Service packet. 938*da6c28aaSamw * 939*da6c28aaSamw * NSCOUNT Unsigned 16 bit integer specifying the number of 940*da6c28aaSamw * resource records in the authority section of a 941*da6c28aaSamw * Name Service packet. 942*da6c28aaSamw * 943*da6c28aaSamw * ARCOUNT Unsigned 16 bit integer specifying the number of 944*da6c28aaSamw * resource records in the additional records 945*da6c28aaSamw * section of a Name Service packet. 946*da6c28aaSamw * 947*da6c28aaSamw * The OPCODE field is defined as: 948*da6c28aaSamw * 949*da6c28aaSamw * 0 1 2 3 4 950*da6c28aaSamw * +---+---+---+---+---+ 951*da6c28aaSamw * | R | OPCODE | 952*da6c28aaSamw * +---+---+---+---+---+ 953*da6c28aaSamw * 954*da6c28aaSamw * Symbol Bit(s) Description 955*da6c28aaSamw * 956*da6c28aaSamw * OPCODE 1-4 Operation specifier: 957*da6c28aaSamw * 0 = query 958*da6c28aaSamw * 5 = registration 959*da6c28aaSamw * 6 = release 960*da6c28aaSamw * 7 = WACK 961*da6c28aaSamw * 8 = refresh 962*da6c28aaSamw * 963*da6c28aaSamw * R 0 RESPONSE flag: 964*da6c28aaSamw * if bit == 0 then request packet 965*da6c28aaSamw * if bit == 1 then response packet. 966*da6c28aaSamw */ 967*da6c28aaSamw 968*da6c28aaSamw 969*da6c28aaSamw /* 970*da6c28aaSamw * The NM_FLAGS field is defined as: 971*da6c28aaSamw * 972*da6c28aaSamw * 973*da6c28aaSamw * 0 1 2 3 4 5 6 974*da6c28aaSamw * +---+---+---+---+---+---+---+ 975*da6c28aaSamw * |AA |TC |RD |RA | 0 | 0 | B | 976*da6c28aaSamw * +---+---+---+---+---+---+---+ 977*da6c28aaSamw * 978*da6c28aaSamw * Symbol Bit(s) Description 979*da6c28aaSamw * 980*da6c28aaSamw * B 6 Broadcast Flag. 981*da6c28aaSamw * = 1: packet was broadcast or multicast 982*da6c28aaSamw * = 0: unicast 983*da6c28aaSamw * 984*da6c28aaSamw * RA 3 Recursion Available Flag. 985*da6c28aaSamw * 986*da6c28aaSamw * Only valid in responses from a NetBIOS Name 987*da6c28aaSamw * Server -- must be zero in all other 988*da6c28aaSamw * responses. 989*da6c28aaSamw * 990*da6c28aaSamw * If one (1) then the NAME supports recursive 991*da6c28aaSamw * query, registration, and release. 992*da6c28aaSamw * 993*da6c28aaSamw * If zero (0) then the end-node must iterate 994*da6c28aaSamw * for query and challenge for registration. 995*da6c28aaSamw * 996*da6c28aaSamw * RD 2 Recursion Desired Flag. 997*da6c28aaSamw * 998*da6c28aaSamw * May only be set on a request to a NetBIOS 999*da6c28aaSamw * Name Server. 1000*da6c28aaSamw * 1001*da6c28aaSamw * The NAME will copy its state into the 1002*da6c28aaSamw * response packet. 1003*da6c28aaSamw * 1004*da6c28aaSamw * If one (1) the NAME will iterate on the 1005*da6c28aaSamw * query, registration, or release. 1006*da6c28aaSamw * 1007*da6c28aaSamw * TC 1 Truncation Flag. 1008*da6c28aaSamw * 1009*da6c28aaSamw * Set if this message was truncated because the 1010*da6c28aaSamw * datagram carrying it would be greater than 1011*da6c28aaSamw * 576 bytes in length. Use TCP to get the 1012*da6c28aaSamw * information from the NetBIOS Name Server. 1013*da6c28aaSamw * 1014*da6c28aaSamw * AA 0 Authoritative Answer flag. 1015*da6c28aaSamw * 1016*da6c28aaSamw * Must be zero (0) if R flag of OPCODE is zero 1017*da6c28aaSamw * (0). 1018*da6c28aaSamw * 1019*da6c28aaSamw * If R flag is one (1) then if AA is one (1) 1020*da6c28aaSamw * then the node responding is an authority for 1021*da6c28aaSamw * the domain name. 1022*da6c28aaSamw * 1023*da6c28aaSamw * End nodes responding to queries always set 1024*da6c28aaSamw * this bit in responses. 1025*da6c28aaSamw * 1026*da6c28aaSamw */ 1027*da6c28aaSamw 1028*da6c28aaSamw /* 1029*da6c28aaSamw * 4.2.1.2. QUESTION SECTION 1030*da6c28aaSamw * 1031*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1032*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1033*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1034*da6c28aaSamw * | | 1035*da6c28aaSamw * / QUESTION_NAME / 1036*da6c28aaSamw * / / 1037*da6c28aaSamw * | | 1038*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1039*da6c28aaSamw * | QUESTION_TYPE | QUESTION_CLASS | 1040*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1041*da6c28aaSamw * 1042*da6c28aaSamw * Field Description 1043*da6c28aaSamw * 1044*da6c28aaSamw * QUESTION_NAME The compressed name representation of the 1045*da6c28aaSamw * NetBIOS name for the request. 1046*da6c28aaSamw * 1047*da6c28aaSamw * QUESTION_TYPE The type of request. The values for this field 1048*da6c28aaSamw * are specified for each request. 1049*da6c28aaSamw * 1050*da6c28aaSamw * QUESTION_CLASS The class of the request. The values for this 1051*da6c28aaSamw * field are specified for each request. 1052*da6c28aaSamw * 1053*da6c28aaSamw * QUESTION_TYPE is defined as: 1054*da6c28aaSamw * 1055*da6c28aaSamw * Symbol Value Description: 1056*da6c28aaSamw * 1057*da6c28aaSamw * NB 0x0020 NetBIOS general Name Service Resource Record 1058*da6c28aaSamw * NBSTAT 0x0021 NetBIOS NODE STATUS Resource Record (See NODE 1059*da6c28aaSamw * STATUS REQUEST) 1060*da6c28aaSamw * 1061*da6c28aaSamw * QUESTION_CLASS is defined as: 1062*da6c28aaSamw * 1063*da6c28aaSamw * Symbol Value Description: 1064*da6c28aaSamw * 1065*da6c28aaSamw * IN 0x0001 Internet class 1066*da6c28aaSamw */ 1067*da6c28aaSamw 1068*da6c28aaSamw #define QUESTION_TYPE_NETBIOS_GENERAL 0x20 1069*da6c28aaSamw #define QUESTION_TYPE_NETBIOS_STATUS 0x21 1070*da6c28aaSamw 1071*da6c28aaSamw #define QUESTION_CLASS_INTERNET 0x0001 1072*da6c28aaSamw 1073*da6c28aaSamw /* 1074*da6c28aaSamw * 1075*da6c28aaSamw * 4.2.1.3. RESOURCE RECORD 1076*da6c28aaSamw * 1077*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1078*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1079*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1080*da6c28aaSamw * | | 1081*da6c28aaSamw * / RR_NAME / 1082*da6c28aaSamw * / / 1083*da6c28aaSamw * | | 1084*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1085*da6c28aaSamw * | RR_TYPE | RR_CLASS | 1086*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1087*da6c28aaSamw * | TTL | 1088*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1089*da6c28aaSamw * | RDLENGTH | | 1090*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 1091*da6c28aaSamw * / / 1092*da6c28aaSamw * / RDATA / 1093*da6c28aaSamw * | | 1094*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1095*da6c28aaSamw * 1096*da6c28aaSamw * Field Description 1097*da6c28aaSamw * 1098*da6c28aaSamw * RR_NAME The compressed name representation of the 1099*da6c28aaSamw * NetBIOS name corresponding to this resource 1100*da6c28aaSamw * record. 1101*da6c28aaSamw * 1102*da6c28aaSamw * RR_TYPE Resource record type code 1103*da6c28aaSamw * 1104*da6c28aaSamw * RR_CLASS Resource record class code 1105*da6c28aaSamw * 1106*da6c28aaSamw * TTL The Time To Live of a the resource record's 1107*da6c28aaSamw * name. 1108*da6c28aaSamw * 1109*da6c28aaSamw * RDLENGTH Unsigned 16 bit integer that specifies the 1110*da6c28aaSamw * number of bytes in the RDATA field. 1111*da6c28aaSamw * 1112*da6c28aaSamw * RDATA RR_CLASS and RR_TYPE dependent field. Contains 1113*da6c28aaSamw * the resource information for the NetBIOS name. 1114*da6c28aaSamw * 1115*da6c28aaSamw * RESOURCE RECORD RR_TYPE field definitions: 1116*da6c28aaSamw * 1117*da6c28aaSamw * Symbol Value Description: 1118*da6c28aaSamw * 1119*da6c28aaSamw * A 0x0001 IP address Resource Record (See REDIRECT NAME 1120*da6c28aaSamw * QUERY RESPONSE) 1121*da6c28aaSamw * NS 0x0002 Name Server Resource Record (See REDIRECT 1122*da6c28aaSamw * NAME QUERY RESPONSE) 1123*da6c28aaSamw * NULL 0x000A NULL Resource Record (See WAIT FOR 1124*da6c28aaSamw * ACKNOWLEDGEMENT RESPONSE) 1125*da6c28aaSamw * NB 0x0020 NetBIOS general Name Service Resource Record 1126*da6c28aaSamw * (See NB_FLAGS and NB_ADDRESS, below) 1127*da6c28aaSamw * NBSTAT 0x0021 NetBIOS NODE STATUS Resource Record (See NODE 1128*da6c28aaSamw * STATUS RESPONSE) 1129*da6c28aaSamw */ 1130*da6c28aaSamw 1131*da6c28aaSamw #define RR_TYPE_IP_ADDRESS_RESOURCE 0x0001 1132*da6c28aaSamw #define RR_TYPE_NAME_SERVER_RESOURCE 0x0002 1133*da6c28aaSamw #define RR_TYPE_NULL_RESOURCE 0x000A 1134*da6c28aaSamw #define RR_TYPE_NETBIOS_RESOURCE 0x0020 1135*da6c28aaSamw #define RR_TYPE_NETBIOS_STATUS 0x0021 1136*da6c28aaSamw 1137*da6c28aaSamw /* 1138*da6c28aaSamw * 1139*da6c28aaSamw * RESOURCE RECORD RR_CLASS field definitions: 1140*da6c28aaSamw * 1141*da6c28aaSamw * Symbol Value Description: 1142*da6c28aaSamw * 1143*da6c28aaSamw * IN 0x0001 Internet class 1144*da6c28aaSamw */ 1145*da6c28aaSamw #define RR_CLASS_INTERNET_CLASS 0x0001 1146*da6c28aaSamw 1147*da6c28aaSamw /* 1148*da6c28aaSamw * 1149*da6c28aaSamw * NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of 1150*da6c28aaSamw * "NB": 1151*da6c28aaSamw * 1152*da6c28aaSamw * 1 1 1 1 1 1 1153*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 1154*da6c28aaSamw * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 1155*da6c28aaSamw * | G | ONT | RESERVED | 1156*da6c28aaSamw * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 1157*da6c28aaSamw * 1158*da6c28aaSamw * Symbol Bit(s) Description: 1159*da6c28aaSamw * 1160*da6c28aaSamw * RESERVED 3-15 Reserved for future use. Must be zero (0). 1161*da6c28aaSamw * ONT 1,2 Owner Node Type: 1162*da6c28aaSamw * 00 = B node 1163*da6c28aaSamw * 01 = P node 1164*da6c28aaSamw * 10 = M node 1165*da6c28aaSamw * 11 = Reserved for future use 1166*da6c28aaSamw * For registration requests this is the 1167*da6c28aaSamw * claimant's type. 1168*da6c28aaSamw * For responses this is the actual owner's 1169*da6c28aaSamw * type. 1170*da6c28aaSamw * 1171*da6c28aaSamw * G 0 Group Name Flag. 1172*da6c28aaSamw * If one (1) then the RR_NAME is a GROUP 1173*da6c28aaSamw * NetBIOS name. 1174*da6c28aaSamw * If zero (0) then the RR_NAME is a UNIQUE 1175*da6c28aaSamw * NetBIOS name. 1176*da6c28aaSamw * 1177*da6c28aaSamw * The NB_ADDRESS field of the RESOURCE RECORD RDATA field for 1178*da6c28aaSamw * RR_TYPE of "NB" is the IP address of the name's owner. 1179*da6c28aaSamw * 1180*da6c28aaSamw */ 1181*da6c28aaSamw #define RR_FLAGS_NB_ONT_MASK 0x6000 1182*da6c28aaSamw #define RR_FLAGS_NB_ONT_B_NODE 0x0000 1183*da6c28aaSamw #define RR_FLAGS_NB_ONT_P_NODE 0x2000 1184*da6c28aaSamw #define RR_FLAGS_NB_ONT_M_NODE 0x4000 1185*da6c28aaSamw #define RR_FLAGS_NB_ONT_RESERVED 0x6000 1186*da6c28aaSamw 1187*da6c28aaSamw #define RR_FLAGS_NB_GROUP_NAME 0x8000 1188*da6c28aaSamw 1189*da6c28aaSamw /* 1190*da6c28aaSamw * smb_netbios_send_rcv 1191*da6c28aaSamw * 1192*da6c28aaSamw * This function sends the given NetBIOS packet to the given 1193*da6c28aaSamw * address and get back the response. If send operation is not 1194*da6c28aaSamw * successful, it's repeated 'retries' times. 1195*da6c28aaSamw * 1196*da6c28aaSamw * Returns: 1197*da6c28aaSamw * 0 Unsuccessful send operation; no reply 1198*da6c28aaSamw * 1 Got reply 1199*da6c28aaSamw */ 1200*da6c28aaSamw static int 1201*da6c28aaSamw smb_netbios_send_rcv(int bcast, struct addr_entry *destination, 1202*da6c28aaSamw struct name_packet *packet, 1203*da6c28aaSamw uint32_t retries, uint32_t timeout) 1204*da6c28aaSamw { 1205*da6c28aaSamw uint32_t retry; 1206*da6c28aaSamw unsigned short tid; 1207*da6c28aaSamw struct timespec st; 1208*da6c28aaSamw int rc; 1209*da6c28aaSamw 1210*da6c28aaSamw for (retry = 0; retry < retries; retry++) { 1211*da6c28aaSamw if ((destination->flags & ADDR_FLAG_VALID) == 0) 1212*da6c28aaSamw return (0); 1213*da6c28aaSamw 1214*da6c28aaSamw tid = netbios_name_transcation_id++; 1215*da6c28aaSamw packet->name_trn_id = tid; 1216*da6c28aaSamw if (smb_send_name_service_packet(destination, packet) >= 0) { 1217*da6c28aaSamw rc = smb_netbios_process_response(tid, destination, 1218*da6c28aaSamw packet, timeout); 1219*da6c28aaSamw 1220*da6c28aaSamw if ((rc > 0) || (bcast == BROADCAST)) 1221*da6c28aaSamw return (1); 1222*da6c28aaSamw 1223*da6c28aaSamw if (rc != 0) 1224*da6c28aaSamw return (0); 1225*da6c28aaSamw } 1226*da6c28aaSamw 1227*da6c28aaSamw st.tv_sec = 0; 1228*da6c28aaSamw st.tv_nsec = (timeout * 1000000); 1229*da6c28aaSamw (void) nanosleep(&st, 0); 1230*da6c28aaSamw } 1231*da6c28aaSamw 1232*da6c28aaSamw return (0); 1233*da6c28aaSamw } 1234*da6c28aaSamw 1235*da6c28aaSamw /* 1236*da6c28aaSamw * 4.2.2. NAME REGISTRATION REQUEST 1237*da6c28aaSamw * 1238*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1239*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1240*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1241*da6c28aaSamw * | NAME_TRN_ID |0| 0x5 |0|0|1|0|0 0|B| 0x0 | 1242*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1243*da6c28aaSamw * | 0x0001 | 0x0000 | 1244*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1245*da6c28aaSamw * | 0x0000 | 0x0001 | 1246*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1247*da6c28aaSamw * | | 1248*da6c28aaSamw * / QUESTION_NAME / 1249*da6c28aaSamw * / / 1250*da6c28aaSamw * | | 1251*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1252*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1253*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1254*da6c28aaSamw * | | 1255*da6c28aaSamw * / RR_NAME / 1256*da6c28aaSamw * / / 1257*da6c28aaSamw * | | 1258*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1259*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1260*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1261*da6c28aaSamw * | TTL | 1262*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1263*da6c28aaSamw * | 0x0006 | NB_FLAGS | 1264*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1265*da6c28aaSamw * | NB_ADDRESS | 1266*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1267*da6c28aaSamw * 1268*da6c28aaSamw * Since the RR_NAME is the same name as the QUESTION_NAME, the 1269*da6c28aaSamw * RR_NAME representation must use pointers to the QUESTION_NAME 1270*da6c28aaSamw * name's labels to guarantee the length of the datagram is less 1271*da6c28aaSamw * than the maximum 576 bytes. See section above on name formats 1272*da6c28aaSamw * and also page 31 and 32 of RFC 883, Domain Names - Implementation 1273*da6c28aaSamw * and Specification, for a complete description of compressed name 1274*da6c28aaSamw * label pointers. 1275*da6c28aaSamw */ 1276*da6c28aaSamw static int 1277*da6c28aaSamw smb_send_name_registration_request(int bcast, struct name_question *question, 1278*da6c28aaSamw struct resource_record *additional) 1279*da6c28aaSamw { 1280*da6c28aaSamw int gotreply = 0; 1281*da6c28aaSamw uint32_t retries; 1282*da6c28aaSamw uint32_t timeout; 1283*da6c28aaSamw struct addr_entry *destination; 1284*da6c28aaSamw struct name_packet packet; 1285*da6c28aaSamw unsigned char type; 1286*da6c28aaSamw int i, addr_num, rc; 1287*da6c28aaSamw 1288*da6c28aaSamw type = question->name->name[15]; 1289*da6c28aaSamw if ((type != 0x00) && (type != 0x20)) { 1290*da6c28aaSamw syslog(LOG_ERR, "netbios: error trying to register" 1291*da6c28aaSamw " non-local name"); 1292*da6c28aaSamw smb_netbios_name_logf(question->name); 1293*da6c28aaSamw question->name->attributes &= ~NAME_ATTR_LOCAL; 1294*da6c28aaSamw return (-1); 1295*da6c28aaSamw } 1296*da6c28aaSamw 1297*da6c28aaSamw if (bcast == BROADCAST) { 1298*da6c28aaSamw if (bcast_num == 0) 1299*da6c28aaSamw return (0); 1300*da6c28aaSamw destination = smb_bcast_list; 1301*da6c28aaSamw addr_num = bcast_num; 1302*da6c28aaSamw retries = BCAST_REQ_RETRY_COUNT; 1303*da6c28aaSamw timeout = BCAST_REQ_RETRY_TIMEOUT; 1304*da6c28aaSamw packet.info = NAME_REGISTRATION_REQUEST | NM_FLAGS_BROADCAST; 1305*da6c28aaSamw } else { 1306*da6c28aaSamw if (nbns_num == 0) 1307*da6c28aaSamw return (0); 1308*da6c28aaSamw destination = smb_nbns; 1309*da6c28aaSamw addr_num = nbns_num; 1310*da6c28aaSamw retries = UCAST_REQ_RETRY_COUNT; 1311*da6c28aaSamw timeout = UCAST_REQ_RETRY_TIMEOUT; 1312*da6c28aaSamw packet.info = NAME_REGISTRATION_REQUEST | NM_FLAGS_UNICAST; 1313*da6c28aaSamw } 1314*da6c28aaSamw 1315*da6c28aaSamw packet.qdcount = 1; /* question entries */ 1316*da6c28aaSamw packet.question = question; 1317*da6c28aaSamw packet.ancount = 0; /* answer recs */ 1318*da6c28aaSamw packet.answer = NULL; 1319*da6c28aaSamw packet.nscount = 0; /* authority recs */ 1320*da6c28aaSamw packet.authority = NULL; 1321*da6c28aaSamw packet.arcount = 1; /* additional recs */ 1322*da6c28aaSamw packet.additional = additional; 1323*da6c28aaSamw 1324*da6c28aaSamw if (IS_UNIQUE(question->name->attributes) && 1325*da6c28aaSamw (is_multihome((char *)(question->name->name)))) 1326*da6c28aaSamw packet.info |= NAME_MULTIHOME_REGISTRATION_REQUEST; 1327*da6c28aaSamw 1328*da6c28aaSamw for (i = 0; i < addr_num; i++) { 1329*da6c28aaSamw /* 1330*da6c28aaSamw * Only register with the Primary WINS server, 1331*da6c28aaSamw * unless we got no reply. 1332*da6c28aaSamw */ 1333*da6c28aaSamw if ((bcast == UNICAST) && gotreply) 1334*da6c28aaSamw break; 1335*da6c28aaSamw 1336*da6c28aaSamw rc = smb_netbios_send_rcv(bcast, &destination[i], &packet, 1337*da6c28aaSamw retries, timeout); 1338*da6c28aaSamw if (rc == 1) 1339*da6c28aaSamw gotreply = 1; 1340*da6c28aaSamw } 1341*da6c28aaSamw 1342*da6c28aaSamw return (gotreply); 1343*da6c28aaSamw } 1344*da6c28aaSamw 1345*da6c28aaSamw /* 1346*da6c28aaSamw * 1347*da6c28aaSamw * 4.2.4. NAME REFRESH REQUEST 1348*da6c28aaSamw * 1349*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1350*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1351*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1352*da6c28aaSamw * | NAME_TRN_ID |0| 0x8 |0|0|0|0|0 0|B| 0x0 | 1353*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1354*da6c28aaSamw * | 0x0001 | 0x0000 | 1355*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1356*da6c28aaSamw * | 0x0000 | 0x0001 | 1357*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1358*da6c28aaSamw * | | 1359*da6c28aaSamw * / QUESTION_NAME / 1360*da6c28aaSamw * / / 1361*da6c28aaSamw * | | 1362*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1363*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1364*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1365*da6c28aaSamw * | | 1366*da6c28aaSamw * / RR_NAME / 1367*da6c28aaSamw * / / 1368*da6c28aaSamw * | | 1369*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1370*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1371*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1372*da6c28aaSamw * | TTL | 1373*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1374*da6c28aaSamw * | 0x0006 | NB_FLAGS | 1375*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1376*da6c28aaSamw * | NB_ADDRESS | 1377*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1378*da6c28aaSamw */ 1379*da6c28aaSamw /*ARGSUSED*/ 1380*da6c28aaSamw static int 1381*da6c28aaSamw smb_send_name_refresh_request(int bcast, struct name_question *question, 1382*da6c28aaSamw struct resource_record *additional, int force) 1383*da6c28aaSamw { 1384*da6c28aaSamw int rc = 0; 1385*da6c28aaSamw int gotreply = 0; 1386*da6c28aaSamw uint32_t retries; 1387*da6c28aaSamw uint32_t timeout; 1388*da6c28aaSamw struct addr_entry *addr; 1389*da6c28aaSamw struct addr_entry *destination; 1390*da6c28aaSamw struct name_packet packet; 1391*da6c28aaSamw unsigned char type; 1392*da6c28aaSamw int i, addr_num, q_addrs = 0; 1393*da6c28aaSamw 1394*da6c28aaSamw type = question->name->name[15]; 1395*da6c28aaSamw if ((type != 0x00) && (type != 0x20)) { 1396*da6c28aaSamw syslog(LOG_ERR, "attempt to refresh non-local name"); 1397*da6c28aaSamw smb_netbios_name_logf(question->name); 1398*da6c28aaSamw question->name->attributes &= ~NAME_ATTR_LOCAL; 1399*da6c28aaSamw return (-1); 1400*da6c28aaSamw } 1401*da6c28aaSamw switch (bcast) { 1402*da6c28aaSamw case BROADCAST : 1403*da6c28aaSamw if (bcast_num == 0) 1404*da6c28aaSamw return (-1); 1405*da6c28aaSamw destination = smb_bcast_list; 1406*da6c28aaSamw addr_num = bcast_num; 1407*da6c28aaSamw retries = BCAST_REQ_RETRY_COUNT; 1408*da6c28aaSamw timeout = BCAST_REQ_RETRY_TIMEOUT; 1409*da6c28aaSamw packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_BROADCAST; 1410*da6c28aaSamw break; 1411*da6c28aaSamw 1412*da6c28aaSamw case UNICAST : 1413*da6c28aaSamw if (nbns_num == 0) 1414*da6c28aaSamw return (-1); 1415*da6c28aaSamw destination = smb_nbns; 1416*da6c28aaSamw addr_num = nbns_num; 1417*da6c28aaSamw retries = UCAST_REQ_RETRY_COUNT; 1418*da6c28aaSamw timeout = UCAST_REQ_RETRY_TIMEOUT; 1419*da6c28aaSamw packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_UNICAST; 1420*da6c28aaSamw break; 1421*da6c28aaSamw 1422*da6c28aaSamw default: 1423*da6c28aaSamw destination = &question->name->addr_list; 1424*da6c28aaSamw /* 1425*da6c28aaSamw * the value of addr_num is irrelvant here, because 1426*da6c28aaSamw * the code is going to do special_process so it doesn't 1427*da6c28aaSamw * need the addr_num. We set a value here just to avoid 1428*da6c28aaSamw * compiler warning. 1429*da6c28aaSamw */ 1430*da6c28aaSamw addr_num = 0; 1431*da6c28aaSamw retries = UCAST_REQ_RETRY_COUNT; 1432*da6c28aaSamw timeout = UCAST_REQ_RETRY_TIMEOUT; 1433*da6c28aaSamw packet.info = NAME_REFRESH_REQUEST | NM_FLAGS_UNICAST; 1434*da6c28aaSamw q_addrs = 1; 1435*da6c28aaSamw break; 1436*da6c28aaSamw } 1437*da6c28aaSamw 1438*da6c28aaSamw if (IS_UNIQUE(question->name->attributes) && 1439*da6c28aaSamw (is_multihome((char *)(question->name->name)))) 1440*da6c28aaSamw packet.info |= NAME_MULTIHOME_REGISTRATION_REQUEST; 1441*da6c28aaSamw 1442*da6c28aaSamw packet.qdcount = 1; /* question entries */ 1443*da6c28aaSamw packet.question = question; 1444*da6c28aaSamw packet.ancount = 0; /* answer recs */ 1445*da6c28aaSamw packet.answer = NULL; 1446*da6c28aaSamw packet.nscount = 0; /* authority recs */ 1447*da6c28aaSamw packet.authority = NULL; 1448*da6c28aaSamw packet.arcount = 1; /* additional recs */ 1449*da6c28aaSamw packet.additional = additional; 1450*da6c28aaSamw 1451*da6c28aaSamw if (q_addrs) 1452*da6c28aaSamw goto special_process; 1453*da6c28aaSamw 1454*da6c28aaSamw for (i = 0; i < addr_num; i++) { 1455*da6c28aaSamw rc = smb_netbios_send_rcv(bcast, &destination[i], &packet, 1456*da6c28aaSamw retries, timeout); 1457*da6c28aaSamw if (rc == 1) 1458*da6c28aaSamw gotreply = 1; 1459*da6c28aaSamw } 1460*da6c28aaSamw 1461*da6c28aaSamw return (gotreply); 1462*da6c28aaSamw 1463*da6c28aaSamw special_process: 1464*da6c28aaSamw addr = destination; 1465*da6c28aaSamw do { 1466*da6c28aaSamw rc = smb_netbios_send_rcv(bcast, addr, &packet, 1467*da6c28aaSamw retries, timeout); 1468*da6c28aaSamw if (rc == 1) 1469*da6c28aaSamw gotreply = 1; 1470*da6c28aaSamw addr = addr->forw; 1471*da6c28aaSamw } while (addr != destination); 1472*da6c28aaSamw 1473*da6c28aaSamw return (gotreply); 1474*da6c28aaSamw } 1475*da6c28aaSamw 1476*da6c28aaSamw /* 1477*da6c28aaSamw * 4.2.5. POSITIVE NAME REGISTRATION RESPONSE 1478*da6c28aaSamw * 1479*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1480*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1481*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1482*da6c28aaSamw * | NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| 0x0 | 1483*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1484*da6c28aaSamw * | 0x0000 | 0x0001 | 1485*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1486*da6c28aaSamw * | 0x0000 | 0x0000 | 1487*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1488*da6c28aaSamw * | | 1489*da6c28aaSamw * / RR_NAME / 1490*da6c28aaSamw * / / 1491*da6c28aaSamw * | | 1492*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1493*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1494*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1495*da6c28aaSamw * | TTL | 1496*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1497*da6c28aaSamw * | 0x0006 | NB_FLAGS | 1498*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1499*da6c28aaSamw * | NB_ADDRESS | 1500*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1501*da6c28aaSamw * 1502*da6c28aaSamw * 1503*da6c28aaSamw * 1504*da6c28aaSamw * 4.2.6. NEGATIVE NAME REGISTRATION RESPONSE 1505*da6c28aaSamw * 1506*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1507*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1508*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1509*da6c28aaSamw * | NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| RCODE | 1510*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1511*da6c28aaSamw * | 0x0000 | 0x0001 | 1512*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1513*da6c28aaSamw * | 0x0000 | 0x0000 | 1514*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1515*da6c28aaSamw * | | 1516*da6c28aaSamw * / RR_NAME / 1517*da6c28aaSamw * / / 1518*da6c28aaSamw * | | 1519*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1520*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1521*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1522*da6c28aaSamw * | TTL | 1523*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1524*da6c28aaSamw * | 0x0006 | NB_FLAGS | 1525*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1526*da6c28aaSamw * | NB_ADDRESS | 1527*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1528*da6c28aaSamw * 1529*da6c28aaSamw * RCODE field values: 1530*da6c28aaSamw * 1531*da6c28aaSamw * Symbol Value Description: 1532*da6c28aaSamw * 1533*da6c28aaSamw * FMT_ERR 0x1 Format Error. Request was invalidly 1534*da6c28aaSamw * formatted. 1535*da6c28aaSamw * SRV_ERR 0x2 Server failure. Problem with NAME, cannot 1536*da6c28aaSamw * process name. 1537*da6c28aaSamw * IMP_ERR 0x4 Unsupported request error. Allowable only 1538*da6c28aaSamw * for challenging NAME when gets an Update type 1539*da6c28aaSamw * registration request. 1540*da6c28aaSamw * RFS_ERR 0x5 Refused error. For policy reasons server 1541*da6c28aaSamw * will not register this name from this host. 1542*da6c28aaSamw * ACT_ERR 0x6 Active error. Name is owned by another node. 1543*da6c28aaSamw * CFT_ERR 0x7 Name in conflict error. A UNIQUE name is 1544*da6c28aaSamw * owned by more than one node. 1545*da6c28aaSamw */ 1546*da6c28aaSamw static int 1547*da6c28aaSamw smb_send_name_registration_response(struct addr_entry *addr, 1548*da6c28aaSamw struct name_packet *original_packet, unsigned short rcode) 1549*da6c28aaSamw { 1550*da6c28aaSamw struct name_packet packet; 1551*da6c28aaSamw struct resource_record answer; 1552*da6c28aaSamw 1553*da6c28aaSamw bzero(&packet, sizeof (struct name_packet)); 1554*da6c28aaSamw bzero(&answer, sizeof (struct resource_record)); 1555*da6c28aaSamw 1556*da6c28aaSamw packet.name_trn_id = original_packet->name_trn_id; 1557*da6c28aaSamw packet.info = NAME_REGISTRATION_RESPONSE | NAME_NM_FLAGS_RA | 1558*da6c28aaSamw (rcode & NAME_RCODE_MASK); 1559*da6c28aaSamw packet.qdcount = 0; /* question entries */ 1560*da6c28aaSamw packet.question = NULL; 1561*da6c28aaSamw packet.ancount = 1; /* answer recs */ 1562*da6c28aaSamw packet.answer = &answer; 1563*da6c28aaSamw packet.nscount = 0; /* authority recs */ 1564*da6c28aaSamw packet.authority = NULL; 1565*da6c28aaSamw packet.arcount = 0; /* additional recs */ 1566*da6c28aaSamw packet.additional = NULL; 1567*da6c28aaSamw 1568*da6c28aaSamw answer.name = original_packet->question->name; 1569*da6c28aaSamw answer.rr_type = NAME_QUESTION_TYPE_NB; 1570*da6c28aaSamw answer.rr_class = NAME_QUESTION_CLASS_IN; 1571*da6c28aaSamw answer.ttl = original_packet->additional->ttl; 1572*da6c28aaSamw answer.rdlength = original_packet->additional->rdlength; 1573*da6c28aaSamw answer.rdata = original_packet->additional->rdata; 1574*da6c28aaSamw 1575*da6c28aaSamw return (smb_send_name_service_packet(addr, &packet)); 1576*da6c28aaSamw } 1577*da6c28aaSamw 1578*da6c28aaSamw /* 1579*da6c28aaSamw * 4.2.9. NAME RELEASE REQUEST & DEMAND 1580*da6c28aaSamw * 1581*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1582*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1583*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1584*da6c28aaSamw * | NAME_TRN_ID |0| 0x6 |0|0|0|0|0 0|B| 0x0 | 1585*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1586*da6c28aaSamw * | 0x0001 | 0x0000 | 1587*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1588*da6c28aaSamw * | 0x0000 | 0x0001 | 1589*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1590*da6c28aaSamw * | | 1591*da6c28aaSamw * / QUESTION_NAME / 1592*da6c28aaSamw * / / 1593*da6c28aaSamw * | | 1594*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1595*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1596*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1597*da6c28aaSamw * | | 1598*da6c28aaSamw * / RR_NAME / 1599*da6c28aaSamw * / / 1600*da6c28aaSamw * | | 1601*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1602*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1603*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1604*da6c28aaSamw * | 0x00000000 | 1605*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1606*da6c28aaSamw * | 0x0006 | NB_FLAGS | 1607*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1608*da6c28aaSamw * | NB_ADDRESS | 1609*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1610*da6c28aaSamw * 1611*da6c28aaSamw * Since the RR_NAME is the same name as the QUESTION_NAME, the 1612*da6c28aaSamw * RR_NAME representation must use label string pointers to the 1613*da6c28aaSamw * QUESTION_NAME labels to guarantee the length of the datagram is 1614*da6c28aaSamw * less than the maximum 576 bytes. This is the same condition as 1615*da6c28aaSamw * with the NAME REGISTRATION REQUEST. 1616*da6c28aaSamw */ 1617*da6c28aaSamw static int 1618*da6c28aaSamw smb_send_name_release_request_and_demand(int bcast, 1619*da6c28aaSamw struct name_question *question, struct resource_record *additional) 1620*da6c28aaSamw { 1621*da6c28aaSamw int gotreply = 0; 1622*da6c28aaSamw int i, rc; 1623*da6c28aaSamw int addr_num; 1624*da6c28aaSamw uint32_t retries; 1625*da6c28aaSamw uint32_t timeout; 1626*da6c28aaSamw struct addr_entry *destination; 1627*da6c28aaSamw struct name_packet packet; 1628*da6c28aaSamw 1629*da6c28aaSamw if (bcast == BROADCAST) { 1630*da6c28aaSamw if (bcast_num == 0) 1631*da6c28aaSamw return (-1); 1632*da6c28aaSamw destination = smb_bcast_list; 1633*da6c28aaSamw addr_num = bcast_num; 1634*da6c28aaSamw retries = 1; /* BCAST_REQ_RETRY_COUNT */ 1635*da6c28aaSamw timeout = 100; /* BCAST_REQ_RETRY_TIMEOUT */ 1636*da6c28aaSamw packet.info = NAME_RELEASE_REQUEST | NM_FLAGS_BROADCAST; 1637*da6c28aaSamw } else { 1638*da6c28aaSamw if (nbns_num == 0) 1639*da6c28aaSamw return (-1); 1640*da6c28aaSamw destination = smb_nbns; 1641*da6c28aaSamw addr_num = nbns_num; 1642*da6c28aaSamw retries = 1; /* UCAST_REQ_RETRY_COUNT */ 1643*da6c28aaSamw timeout = 100; /* UCAST_REQ_RETRY_TIMEOUT */ 1644*da6c28aaSamw packet.info = NAME_RELEASE_REQUEST | NM_FLAGS_UNICAST; 1645*da6c28aaSamw } 1646*da6c28aaSamw 1647*da6c28aaSamw packet.qdcount = 1; /* question entries */ 1648*da6c28aaSamw packet.question = question; 1649*da6c28aaSamw packet.ancount = 0; /* answer recs */ 1650*da6c28aaSamw packet.answer = NULL; 1651*da6c28aaSamw packet.nscount = 0; /* authority recs */ 1652*da6c28aaSamw packet.authority = NULL; 1653*da6c28aaSamw packet.arcount = 1; /* additional recs */ 1654*da6c28aaSamw packet.additional = additional; 1655*da6c28aaSamw 1656*da6c28aaSamw for (i = 0; i < addr_num; i++) { 1657*da6c28aaSamw rc = smb_netbios_send_rcv(bcast, &destination[i], &packet, 1658*da6c28aaSamw retries, timeout); 1659*da6c28aaSamw if (rc == 1) 1660*da6c28aaSamw gotreply = 1; 1661*da6c28aaSamw } 1662*da6c28aaSamw 1663*da6c28aaSamw return (gotreply); 1664*da6c28aaSamw } 1665*da6c28aaSamw 1666*da6c28aaSamw /* 1667*da6c28aaSamw * 4.2.10. POSITIVE NAME RELEASE RESPONSE 1668*da6c28aaSamw * 1669*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1670*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1671*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1672*da6c28aaSamw * | NAME_TRN_ID |1| 0x6 |1|0|0|0|0 0|0| 0x0 | 1673*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1674*da6c28aaSamw * | 0x0000 | 0x0001 | 1675*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1676*da6c28aaSamw * | 0x0000 | 0x0000 | 1677*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1678*da6c28aaSamw * | | 1679*da6c28aaSamw * / RR_NAME / 1680*da6c28aaSamw * / / 1681*da6c28aaSamw * | | 1682*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1683*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1684*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1685*da6c28aaSamw * | TTL | 1686*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1687*da6c28aaSamw * | 0x0006 | NB_FLAGS | 1688*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1689*da6c28aaSamw * | NB_ADDRESS | 1690*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1691*da6c28aaSamw * 1692*da6c28aaSamw * 1693*da6c28aaSamw * 4.2.11. NEGATIVE NAME RELEASE RESPONSE 1694*da6c28aaSamw * 1695*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1696*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1697*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1698*da6c28aaSamw * | NAME_TRN_ID |1| 0x6 |1|0|0|0|0 0|0| RCODE | 1699*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1700*da6c28aaSamw * | 0x0000 | 0x0001 | 1701*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1702*da6c28aaSamw * | 0x0000 | 0x0000 | 1703*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1704*da6c28aaSamw * | | 1705*da6c28aaSamw * / RR_NAME / 1706*da6c28aaSamw * / / 1707*da6c28aaSamw * | | 1708*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1709*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1710*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1711*da6c28aaSamw * | TTL | 1712*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1713*da6c28aaSamw * | 0x0006 | NB_FLAGS | 1714*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1715*da6c28aaSamw * | NB_ADDRESS | 1716*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1717*da6c28aaSamw * 1718*da6c28aaSamw * RCODE field values: 1719*da6c28aaSamw * 1720*da6c28aaSamw * Symbol Value Description: 1721*da6c28aaSamw * 1722*da6c28aaSamw * FMT_ERR 0x1 Format Error. Request was invalidly 1723*da6c28aaSamw * formatted. 1724*da6c28aaSamw * 1725*da6c28aaSamw * SRV_ERR 0x2 Server failure. Problem with NAME, cannot 1726*da6c28aaSamw * process name. 1727*da6c28aaSamw * 1728*da6c28aaSamw * RFS_ERR 0x5 Refused error. For policy reasons server 1729*da6c28aaSamw * will not release this name from this host. 1730*da6c28aaSamw * 1731*da6c28aaSamw * ACT_ERR 0x6 Active error. Name is owned by another node. 1732*da6c28aaSamw * Only that node may release it. A NetBIOS 1733*da6c28aaSamw * Name Server can optionally allow a node to 1734*da6c28aaSamw * release a name it does not own. This would 1735*da6c28aaSamw * facilitate detection of inactive names for 1736*da6c28aaSamw * nodes that went down silently. 1737*da6c28aaSamw */ 1738*da6c28aaSamw static int 1739*da6c28aaSamw /* LINTED - E_STATIC_UNUSED */ 1740*da6c28aaSamw smb_send_name_release_response(struct addr_entry *addr, 1741*da6c28aaSamw struct name_packet *original_packet, unsigned short rcode) 1742*da6c28aaSamw { 1743*da6c28aaSamw struct name_packet packet; 1744*da6c28aaSamw struct resource_record answer; 1745*da6c28aaSamw 1746*da6c28aaSamw bzero(&packet, sizeof (struct name_packet)); 1747*da6c28aaSamw bzero(&answer, sizeof (struct resource_record)); 1748*da6c28aaSamw 1749*da6c28aaSamw packet.name_trn_id = original_packet->name_trn_id; 1750*da6c28aaSamw packet.info = NAME_RELEASE_RESPONSE | (rcode & NAME_RCODE_MASK); 1751*da6c28aaSamw packet.qdcount = 0; /* question entries */ 1752*da6c28aaSamw packet.question = NULL; 1753*da6c28aaSamw packet.ancount = 1; /* answer recs */ 1754*da6c28aaSamw packet.answer = &answer; 1755*da6c28aaSamw packet.nscount = 0; /* authority recs */ 1756*da6c28aaSamw packet.authority = NULL; 1757*da6c28aaSamw packet.arcount = 0; /* additional recs */ 1758*da6c28aaSamw packet.additional = NULL; 1759*da6c28aaSamw 1760*da6c28aaSamw answer.name = original_packet->question->name; 1761*da6c28aaSamw answer.rr_type = NAME_QUESTION_TYPE_NB; 1762*da6c28aaSamw answer.rr_class = NAME_QUESTION_CLASS_IN; 1763*da6c28aaSamw answer.ttl = original_packet->additional->ttl; 1764*da6c28aaSamw answer.rdlength = original_packet->additional->rdlength; 1765*da6c28aaSamw answer.rdata = original_packet->additional->rdata; 1766*da6c28aaSamw 1767*da6c28aaSamw return (smb_send_name_service_packet(addr, &packet)); 1768*da6c28aaSamw } 1769*da6c28aaSamw 1770*da6c28aaSamw /* 1771*da6c28aaSamw * 1772*da6c28aaSamw * 4.2.12. NAME QUERY REQUEST 1773*da6c28aaSamw * 1774*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1775*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1776*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1777*da6c28aaSamw * | NAME_TRN_ID |0| 0x0 |0|0|1|0|0 0|B| 0x0 | 1778*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1779*da6c28aaSamw * | 0x0001 | 0x0000 | 1780*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1781*da6c28aaSamw * | 0x0000 | 0x0000 | 1782*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1783*da6c28aaSamw * | | 1784*da6c28aaSamw * / QUESTION_NAME / 1785*da6c28aaSamw * / / 1786*da6c28aaSamw * | | 1787*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1788*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1789*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1790*da6c28aaSamw */ 1791*da6c28aaSamw static int 1792*da6c28aaSamw smb_send_name_query_request(int bcast, struct name_question *question) 1793*da6c28aaSamw { 1794*da6c28aaSamw int rc = 0; 1795*da6c28aaSamw uint32_t retry, retries; 1796*da6c28aaSamw uint32_t timeout; 1797*da6c28aaSamw unsigned short tid; 1798*da6c28aaSamw struct addr_entry *destination; 1799*da6c28aaSamw struct name_packet packet; 1800*da6c28aaSamw int i, addr_num; 1801*da6c28aaSamw struct timespec st; 1802*da6c28aaSamw 1803*da6c28aaSamw if (bcast == BROADCAST) { 1804*da6c28aaSamw if (bcast_num == 0) 1805*da6c28aaSamw return (-1); 1806*da6c28aaSamw destination = smb_bcast_list; 1807*da6c28aaSamw addr_num = bcast_num; 1808*da6c28aaSamw retries = BCAST_REQ_RETRY_COUNT; 1809*da6c28aaSamw timeout = BCAST_REQ_RETRY_TIMEOUT; 1810*da6c28aaSamw packet.info = NAME_QUERY_REQUEST | NM_FLAGS_BROADCAST; 1811*da6c28aaSamw } else { 1812*da6c28aaSamw if (nbns_num == 0) 1813*da6c28aaSamw return (-1); 1814*da6c28aaSamw destination = smb_nbns; 1815*da6c28aaSamw addr_num = nbns_num; 1816*da6c28aaSamw retries = UCAST_REQ_RETRY_COUNT; 1817*da6c28aaSamw timeout = UCAST_REQ_RETRY_TIMEOUT; 1818*da6c28aaSamw packet.info = NAME_QUERY_REQUEST | NM_FLAGS_UNICAST; 1819*da6c28aaSamw } 1820*da6c28aaSamw packet.qdcount = 1; /* question entries */ 1821*da6c28aaSamw packet.question = question; 1822*da6c28aaSamw packet.ancount = 0; /* answer recs */ 1823*da6c28aaSamw packet.answer = NULL; 1824*da6c28aaSamw packet.nscount = 0; /* authority recs */ 1825*da6c28aaSamw packet.authority = NULL; 1826*da6c28aaSamw packet.arcount = 0; /* additional recs */ 1827*da6c28aaSamw packet.additional = NULL; 1828*da6c28aaSamw 1829*da6c28aaSamw for (i = 0; i < addr_num; i++) { 1830*da6c28aaSamw for (retry = 0; retry < retries; retry++) { 1831*da6c28aaSamw if ((destination->flags & ADDR_FLAG_VALID) == 0) 1832*da6c28aaSamw break; 1833*da6c28aaSamw tid = netbios_name_transcation_id++; 1834*da6c28aaSamw packet.name_trn_id = tid; 1835*da6c28aaSamw 1836*da6c28aaSamw if (smb_send_name_service_packet(&destination[i], 1837*da6c28aaSamw &packet) >= 0) { 1838*da6c28aaSamw if ((rc = smb_netbios_process_response(tid, 1839*da6c28aaSamw &destination[i], 1840*da6c28aaSamw &packet, timeout)) != 0) 1841*da6c28aaSamw break; 1842*da6c28aaSamw } 1843*da6c28aaSamw st.tv_sec = 0; 1844*da6c28aaSamw st.tv_nsec = (timeout * 1000000); 1845*da6c28aaSamw (void) nanosleep(&st, 0); 1846*da6c28aaSamw } 1847*da6c28aaSamw } 1848*da6c28aaSamw 1849*da6c28aaSamw return (rc); 1850*da6c28aaSamw } 1851*da6c28aaSamw 1852*da6c28aaSamw 1853*da6c28aaSamw /* 1854*da6c28aaSamw * 1855*da6c28aaSamw * 4.2.13. POSITIVE NAME QUERY RESPONSE 1856*da6c28aaSamw * 1857*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1858*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1859*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1860*da6c28aaSamw * | NAME_TRN_ID |1| 0x0 |1|T|1|?|0 0|0| 0x0 | 1861*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1862*da6c28aaSamw * | 0x0000 | 0x0001 | 1863*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1864*da6c28aaSamw * | 0x0000 | 0x0000 | 1865*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1866*da6c28aaSamw * | | 1867*da6c28aaSamw * / RR_NAME / 1868*da6c28aaSamw * / / 1869*da6c28aaSamw * | | 1870*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1871*da6c28aaSamw * | NB (0x0020) | IN (0x0001) | 1872*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1873*da6c28aaSamw * | TTL | 1874*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1875*da6c28aaSamw * | RDLENGTH | | 1876*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 1877*da6c28aaSamw * | | 1878*da6c28aaSamw * / ADDR_ENTRY ARRAY / 1879*da6c28aaSamw * / / 1880*da6c28aaSamw * | | 1881*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1882*da6c28aaSamw * 1883*da6c28aaSamw * The ADDR_ENTRY ARRAY a sequence of zero or more ADDR_ENTRY 1884*da6c28aaSamw * records. Each ADDR_ENTRY record represents an owner of a name. 1885*da6c28aaSamw * For group names there may be multiple entries. However, the list 1886*da6c28aaSamw * may be incomplete due to packet size limitations. Bit 22, "T", 1887*da6c28aaSamw * will be set to indicate truncated data. 1888*da6c28aaSamw * 1889*da6c28aaSamw * Each ADDR_ENTRY has the following format: 1890*da6c28aaSamw * 1891*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1892*da6c28aaSamw * | NB_FLAGS | NB_ADDRESS | 1893*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1894*da6c28aaSamw * | NB_ADDRESS (continued) | 1895*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1896*da6c28aaSamw * 1897*da6c28aaSamw * 1898*da6c28aaSamw * 1899*da6c28aaSamw * 4.2.14. NEGATIVE NAME QUERY RESPONSE 1900*da6c28aaSamw * 1901*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1902*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1903*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1904*da6c28aaSamw * | NAME_TRN_ID |1| 0x0 |1|0|1|?|0 0|0| RCODE | 1905*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1906*da6c28aaSamw * | 0x0000 | 0x0000 | 1907*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1908*da6c28aaSamw * | 0x0000 | 0x0000 | 1909*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1910*da6c28aaSamw * | | 1911*da6c28aaSamw * / RR_NAME / 1912*da6c28aaSamw * / / 1913*da6c28aaSamw * | | 1914*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1915*da6c28aaSamw * | NULL (0x000A) | IN (0x0001) | 1916*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1917*da6c28aaSamw * | 0x00000000 | 1918*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1919*da6c28aaSamw * | 0x0000 | 1920*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1921*da6c28aaSamw * 1922*da6c28aaSamw * RCODE field values: 1923*da6c28aaSamw * 1924*da6c28aaSamw * Symbol Value Description 1925*da6c28aaSamw * 1926*da6c28aaSamw * FMT_ERR 0x1 Format Error. Request was invalidly 1927*da6c28aaSamw * formatted. 1928*da6c28aaSamw * SRV_ERR 0x2 Server failure. Problem with NAME, cannot 1929*da6c28aaSamw * process name. 1930*da6c28aaSamw * NAM_ERR 0x3 Name Error. The name requested does not 1931*da6c28aaSamw * exist. 1932*da6c28aaSamw * IMP_ERR 0x4 Unsupported request error. Allowable only 1933*da6c28aaSamw * for challenging NAME when gets an Update type 1934*da6c28aaSamw * registration request. 1935*da6c28aaSamw * RFS_ERR 0x5 Refused error. For policy reasons server 1936*da6c28aaSamw * will not register this name from this host. 1937*da6c28aaSamw */ 1938*da6c28aaSamw static int 1939*da6c28aaSamw smb_send_name_query_response(struct addr_entry *addr, 1940*da6c28aaSamw struct name_packet *original_packet, struct name_entry *entry, 1941*da6c28aaSamw unsigned short rcode) 1942*da6c28aaSamw { 1943*da6c28aaSamw struct addr_entry *raddr; 1944*da6c28aaSamw struct name_packet packet; 1945*da6c28aaSamw struct resource_record answer; 1946*da6c28aaSamw unsigned short attr; 1947*da6c28aaSamw unsigned char data[MAX_DATAGRAM_LENGTH]; 1948*da6c28aaSamw unsigned char *scan = data; 1949*da6c28aaSamw 1950*da6c28aaSamw packet.name_trn_id = original_packet->name_trn_id; 1951*da6c28aaSamw packet.info = NAME_QUERY_RESPONSE | (rcode & NAME_RCODE_MASK); 1952*da6c28aaSamw packet.qdcount = 0; /* question entries */ 1953*da6c28aaSamw packet.question = NULL; 1954*da6c28aaSamw packet.ancount = 1; /* answer recs */ 1955*da6c28aaSamw packet.answer = &answer; 1956*da6c28aaSamw packet.nscount = 0; /* authority recs */ 1957*da6c28aaSamw packet.authority = NULL; 1958*da6c28aaSamw packet.arcount = 0; /* additional recs */ 1959*da6c28aaSamw packet.additional = NULL; 1960*da6c28aaSamw 1961*da6c28aaSamw answer.name = entry; 1962*da6c28aaSamw answer.rr_class = NAME_QUESTION_CLASS_IN; 1963*da6c28aaSamw answer.ttl = entry->addr_list.ttl; 1964*da6c28aaSamw answer.rdata = data; 1965*da6c28aaSamw if (rcode) { 1966*da6c28aaSamw answer.rr_type = NAME_RR_TYPE_NULL; 1967*da6c28aaSamw answer.rdlength = 0; 1968*da6c28aaSamw bzero(data, 6); 1969*da6c28aaSamw } else { 1970*da6c28aaSamw answer.rdlength = 0; 1971*da6c28aaSamw answer.rr_type = NAME_QUESTION_TYPE_NB; 1972*da6c28aaSamw raddr = &entry->addr_list; 1973*da6c28aaSamw scan = data; 1974*da6c28aaSamw do { 1975*da6c28aaSamw attr = entry->attributes & (NAME_ATTR_GROUP | 1976*da6c28aaSamw NAME_ATTR_OWNER_NODE_TYPE); 1977*da6c28aaSamw 1978*da6c28aaSamw BE_OUT16(scan, attr); scan += 2; 1979*da6c28aaSamw (void) memcpy(scan, &raddr->sin.sin_addr.s_addr, 1980*da6c28aaSamw sizeof (uint32_t)); 1981*da6c28aaSamw scan += 4; 1982*da6c28aaSamw 1983*da6c28aaSamw answer.rdlength += 6; 1984*da6c28aaSamw raddr = raddr->forw; 1985*da6c28aaSamw } while (raddr != &entry->addr_list); 1986*da6c28aaSamw } 1987*da6c28aaSamw 1988*da6c28aaSamw return (smb_send_name_service_packet(addr, &packet)); 1989*da6c28aaSamw } 1990*da6c28aaSamw 1991*da6c28aaSamw /* 1992*da6c28aaSamw * 4.2.18. NODE STATUS RESPONSE 1993*da6c28aaSamw * 1994*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 1995*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1996*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1997*da6c28aaSamw * | NAME_TRN_ID |1| 0x0 |1|0|0|0|0 0|0| 0x0 | 1998*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1999*da6c28aaSamw * | 0x0000 | 0x0001 | 2000*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2001*da6c28aaSamw * | 0x0000 | 0x0000 | 2002*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2003*da6c28aaSamw * | | 2004*da6c28aaSamw * / RR_NAME / 2005*da6c28aaSamw * | | 2006*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2007*da6c28aaSamw * | NBSTAT (0x0021) | IN (0x0001) | 2008*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2009*da6c28aaSamw * | 0x00000000 | 2010*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2011*da6c28aaSamw * | RDLENGTH | NUM_NAMES | | 2012*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 2013*da6c28aaSamw * | | 2014*da6c28aaSamw * + + 2015*da6c28aaSamw * / NODE_NAME ARRAY / 2016*da6c28aaSamw * + + 2017*da6c28aaSamw * | | 2018*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2019*da6c28aaSamw * | | 2020*da6c28aaSamw * + + 2021*da6c28aaSamw * / STATISTICS / 2022*da6c28aaSamw * + + 2023*da6c28aaSamw * | | 2024*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2025*da6c28aaSamw * 2026*da6c28aaSamw * The NODE_NAME ARRAY is an array of zero or more NUM_NAMES entries 2027*da6c28aaSamw * of NODE_NAME records. Each NODE_NAME entry represents an active 2028*da6c28aaSamw * name in the same NetBIOS scope as the requesting name in the 2029*da6c28aaSamw * local name table of the responder. RR_NAME is the requesting 2030*da6c28aaSamw * name. 2031*da6c28aaSamw * 2032*da6c28aaSamw * NODE_NAME Entry: 2033*da6c28aaSamw * 2034*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 2035*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2036*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2037*da6c28aaSamw * | | 2038*da6c28aaSamw * +--- ---+ 2039*da6c28aaSamw * | | 2040*da6c28aaSamw * +--- NETBIOS FORMAT NAME ---+ 2041*da6c28aaSamw * | | 2042*da6c28aaSamw * +--- ---+ 2043*da6c28aaSamw * | | 2044*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2045*da6c28aaSamw * | NAME_FLAGS | 2046*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2047*da6c28aaSamw * 2048*da6c28aaSamw * The NAME_FLAGS field: 2049*da6c28aaSamw * 2050*da6c28aaSamw * 1 1 1 1 1 1 2051*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 2052*da6c28aaSamw * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2053*da6c28aaSamw * | G | ONT |DRG|CNF|ACT|PRM| RESERVED | 2054*da6c28aaSamw * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 2055*da6c28aaSamw * 2056*da6c28aaSamw * The NAME_FLAGS field is defined as: 2057*da6c28aaSamw * 2058*da6c28aaSamw * Symbol Bit(s) Description: 2059*da6c28aaSamw * 2060*da6c28aaSamw * RESERVED 7-15 Reserved for future use. Must be zero (0). 2061*da6c28aaSamw * PRM 6 Permanent Name Flag. If one (1) then entry 2062*da6c28aaSamw * is for the permanent node name. Flag is zero 2063*da6c28aaSamw * (0) for all other names. 2064*da6c28aaSamw * ACT 5 Active Name Flag. All entries have this flag 2065*da6c28aaSamw * set to one (1). 2066*da6c28aaSamw * CNF 4 Conflict Flag. If one (1) then name on this 2067*da6c28aaSamw * node is in conflict. 2068*da6c28aaSamw * DRG 3 Deregister Flag. If one (1) then this name 2069*da6c28aaSamw * is in the process of being deleted. 2070*da6c28aaSamw * ONT 1,2 Owner Node Type: 2071*da6c28aaSamw * 00 = B node 2072*da6c28aaSamw * 01 = P node 2073*da6c28aaSamw * 10 = M node 2074*da6c28aaSamw * 11 = Reserved for future use 2075*da6c28aaSamw * G 0 Group Name Flag. 2076*da6c28aaSamw * If one (1) then the name is a GROUP NetBIOS 2077*da6c28aaSamw * name. 2078*da6c28aaSamw * If zero (0) then it is a UNIQUE NetBIOS name. 2079*da6c28aaSamw */ 2080*da6c28aaSamw #define NAME_FLAGS_PERMANENT_NAME 0x0200 2081*da6c28aaSamw #define NAME_FLAGS_ACTIVE_NAME 0x0400 2082*da6c28aaSamw #define NAME_FLAGS_CONFLICT 0x0800 2083*da6c28aaSamw #define NAME_FLAGS_DEREGISTER 0x1000 2084*da6c28aaSamw #define NAME_FLAGS_ONT_MASK 0x6000 2085*da6c28aaSamw #define NAME_FLAGS_ONT_B_NODE 0x0000 2086*da6c28aaSamw #define NAME_FLAGS_ONT_P_NODE 0x2000 2087*da6c28aaSamw #define NAME_FLAGS_ONT_M_NODE 0x4000 2088*da6c28aaSamw #define NAME_FLAGS_ONT_RESERVED 0x6000 2089*da6c28aaSamw #define NAME_FLAGS_GROUP_NAME 0x8000 2090*da6c28aaSamw 2091*da6c28aaSamw 2092*da6c28aaSamw /* 2093*da6c28aaSamw * STATISTICS Field of the NODE STATUS RESPONSE: 2094*da6c28aaSamw * 2095*da6c28aaSamw * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 2096*da6c28aaSamw * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2097*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2098*da6c28aaSamw * | UNIT_ID (Unique unit ID) | 2099*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2100*da6c28aaSamw * | UNIT_ID,continued | JUMPERS | TEST_RESULT | 2101*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2102*da6c28aaSamw * | VERSION_NUMBER | PERIOD_OF_STATISTICS | 2103*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2104*da6c28aaSamw * | NUMBER_OF_CRCs | NUMBER_ALIGNMENT_ERRORS | 2105*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2106*da6c28aaSamw * | NUMBER_OF_COLLISIONS | NUMBER_SEND_ABORTS | 2107*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2108*da6c28aaSamw * | NUMBER_GOOD_SENDS | 2109*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2110*da6c28aaSamw * | NUMBER_GOOD_RECEIVES | 2111*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2112*da6c28aaSamw * | NUMBER_RETRANSMITS | NUMBER_NO_RESOURCE_CONDITIONS | 2113*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2114*da6c28aaSamw * | NUMBER_FREE_COMMAND_BLOCKS | TOTAL_NUMBER_COMMAND_BLOCKS | 2115*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2116*da6c28aaSamw * |MAX_TOTAL_NUMBER_COMMAND_BLOCKS| NUMBER_PENDING_SESSIONS | 2117*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2118*da6c28aaSamw * | MAX_NUMBER_PENDING_SESSIONS | MAX_TOTAL_SESSIONS_POSSIBLE | 2119*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2120*da6c28aaSamw * | SESSION_DATA_PACKET_SIZE | 2121*da6c28aaSamw * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2122*da6c28aaSamw */ 2123*da6c28aaSamw #define MAX_NETBIOS_REPLY_DATA_SIZE 500 2124*da6c28aaSamw 2125*da6c28aaSamw static int 2126*da6c28aaSamw smb_send_node_status_response(struct addr_entry *addr, 2127*da6c28aaSamw struct name_packet *original_packet) 2128*da6c28aaSamw { 2129*da6c28aaSamw uint32_t net_ipaddr, max_connections; 2130*da6c28aaSamw struct arpreq arpreq; 2131*da6c28aaSamw struct name_packet packet; 2132*da6c28aaSamw struct resource_record answer; 2133*da6c28aaSamw unsigned char *scan; 2134*da6c28aaSamw unsigned char *scan_end; 2135*da6c28aaSamw unsigned char data[MAX_NETBIOS_REPLY_DATA_SIZE]; 2136*da6c28aaSamw net_cfg_t cfg; 2137*da6c28aaSamw 2138*da6c28aaSamw bzero(&packet, sizeof (struct name_packet)); 2139*da6c28aaSamw bzero(&answer, sizeof (struct resource_record)); 2140*da6c28aaSamw 2141*da6c28aaSamw packet.name_trn_id = original_packet->name_trn_id; 2142*da6c28aaSamw packet.info = NODE_STATUS_RESPONSE; 2143*da6c28aaSamw packet.qdcount = 0; /* question entries */ 2144*da6c28aaSamw packet.question = NULL; 2145*da6c28aaSamw packet.ancount = 1; /* answer recs */ 2146*da6c28aaSamw packet.answer = &answer; 2147*da6c28aaSamw packet.nscount = 0; /* authority recs */ 2148*da6c28aaSamw packet.authority = NULL; 2149*da6c28aaSamw packet.arcount = 0; /* additional recs */ 2150*da6c28aaSamw packet.additional = NULL; 2151*da6c28aaSamw 2152*da6c28aaSamw answer.name = original_packet->question->name; 2153*da6c28aaSamw answer.rr_type = NAME_RR_TYPE_NBSTAT; 2154*da6c28aaSamw answer.rr_class = NAME_QUESTION_CLASS_IN; 2155*da6c28aaSamw answer.ttl = 0; 2156*da6c28aaSamw answer.rdata = data; 2157*da6c28aaSamw 2158*da6c28aaSamw scan = smb_netbios_cache_status(data, MAX_NETBIOS_REPLY_DATA_SIZE, 2159*da6c28aaSamw original_packet->question->name->scope); 2160*da6c28aaSamw 2161*da6c28aaSamw scan_end = data + MAX_NETBIOS_REPLY_DATA_SIZE; 2162*da6c28aaSamw 2163*da6c28aaSamw if (smb_nic_get_bysubnet(addr->sin.sin_addr.s_addr, &cfg) == NULL) 2164*da6c28aaSamw net_ipaddr = 0; 2165*da6c28aaSamw else 2166*da6c28aaSamw net_ipaddr = cfg.ip; 2167*da6c28aaSamw 2168*da6c28aaSamw smb_config_rdlock(); 2169*da6c28aaSamw max_connections = smb_config_getnum(SMB_CI_MAX_CONNECTIONS); 2170*da6c28aaSamw smb_config_unlock(); 2171*da6c28aaSamw for (;;) { 2172*da6c28aaSamw if ((scan + 6) >= scan_end) { 2173*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2174*da6c28aaSamw break; 2175*da6c28aaSamw } 2176*da6c28aaSamw 2177*da6c28aaSamw if (net_ipaddr != 0) { 2178*da6c28aaSamw struct sockaddr_in *s_in; 2179*da6c28aaSamw int s; 2180*da6c28aaSamw 2181*da6c28aaSamw s = socket(AF_INET, SOCK_DGRAM, 0); 2182*da6c28aaSamw /* LINTED - E_BAD_PTR_CAST_ALIGN */ 2183*da6c28aaSamw s_in = (struct sockaddr_in *)&arpreq.arp_pa; 2184*da6c28aaSamw s_in->sin_family = AF_INET; 2185*da6c28aaSamw s_in->sin_addr.s_addr = net_ipaddr; 2186*da6c28aaSamw if (ioctl(s, SIOCGARP, (caddr_t)&arpreq) < 0) { 2187*da6c28aaSamw bzero(scan, 6); 2188*da6c28aaSamw } else { 2189*da6c28aaSamw bcopy(&arpreq.arp_ha.sa_data, scan, 6); 2190*da6c28aaSamw } 2191*da6c28aaSamw (void) close(s); 2192*da6c28aaSamw } else { 2193*da6c28aaSamw bzero(scan, 6); 2194*da6c28aaSamw } 2195*da6c28aaSamw scan += 6; 2196*da6c28aaSamw 2197*da6c28aaSamw if ((scan + 26) >= scan_end) { 2198*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2199*da6c28aaSamw break; 2200*da6c28aaSamw } 2201*da6c28aaSamw bzero(scan, 26); 2202*da6c28aaSamw scan += 26; 2203*da6c28aaSamw 2204*da6c28aaSamw if ((scan + 2) >= scan_end) { 2205*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2206*da6c28aaSamw break; 2207*da6c28aaSamw } 2208*da6c28aaSamw BE_OUT16(scan, 0); scan += 2; 2209*da6c28aaSamw 2210*da6c28aaSamw if ((scan + 2) >= scan_end) { 2211*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2212*da6c28aaSamw break; 2213*da6c28aaSamw } 2214*da6c28aaSamw BE_OUT16(scan, 0); scan += 2; 2215*da6c28aaSamw 2216*da6c28aaSamw if ((scan + 2) >= scan_end) { 2217*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2218*da6c28aaSamw break; 2219*da6c28aaSamw } 2220*da6c28aaSamw BE_OUT16(scan, 0); scan += 2; 2221*da6c28aaSamw 2222*da6c28aaSamw if ((scan + 2) >= scan_end) { 2223*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2224*da6c28aaSamw break; 2225*da6c28aaSamw } 2226*da6c28aaSamw BE_OUT16(scan, 0); scan += 2; 2227*da6c28aaSamw 2228*da6c28aaSamw if ((scan + 2) >= scan_end) { 2229*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2230*da6c28aaSamw break; 2231*da6c28aaSamw } 2232*da6c28aaSamw BE_OUT16(scan, 0); scan += 2; 2233*da6c28aaSamw 2234*da6c28aaSamw if ((scan + 2) >= scan_end) { 2235*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2236*da6c28aaSamw break; 2237*da6c28aaSamw } 2238*da6c28aaSamw BE_OUT16(scan, 0); scan += 2; 2239*da6c28aaSamw 2240*da6c28aaSamw if ((scan + 2) >= scan_end) { 2241*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2242*da6c28aaSamw break; 2243*da6c28aaSamw } 2244*da6c28aaSamw BE_OUT16(scan, 0); scan += 2; 2245*da6c28aaSamw 2246*da6c28aaSamw if ((scan + 2) >= scan_end) { 2247*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2248*da6c28aaSamw break; 2249*da6c28aaSamw } 2250*da6c28aaSamw BE_OUT16(scan, max_connections); scan += 2; 2251*da6c28aaSamw 2252*da6c28aaSamw if ((scan + 2) >= scan_end) { 2253*da6c28aaSamw packet.info |= NAME_NM_FLAGS_TC; 2254*da6c28aaSamw break; 2255*da6c28aaSamw } 2256*da6c28aaSamw 2257*da6c28aaSamw BE_OUT16(scan, 0); scan += 2; 2258*da6c28aaSamw 2259*da6c28aaSamw break; 2260*da6c28aaSamw /*NOTREACHED*/ 2261*da6c28aaSamw } 2262*da6c28aaSamw answer.rdlength = scan - data; 2263*da6c28aaSamw return (smb_send_name_service_packet(addr, &packet)); 2264*da6c28aaSamw } 2265*da6c28aaSamw 2266*da6c28aaSamw /* 2267*da6c28aaSamw * 2268*da6c28aaSamw * 5.1. NAME SERVICE PROTOCOLS 2269*da6c28aaSamw * 2270*da6c28aaSamw * A REQUEST packet is always sent to the well known UDP port - 2271*da6c28aaSamw * NAME_SERVICE_UDP_PORT. The destination address is normally 2272*da6c28aaSamw * either the IP broadcast address or the address of the NAME - the 2273*da6c28aaSamw * address of the NAME server it set up at initialization time. In 2274*da6c28aaSamw * rare cases, a request packet will be sent to an end node, e.g. a 2275*da6c28aaSamw * NAME QUERY REQUEST sent to "challenge" a node. 2276*da6c28aaSamw * 2277*da6c28aaSamw * A RESPONSE packet is always sent to the source UDP port and 2278*da6c28aaSamw * source IP address of the request packet. 2279*da6c28aaSamw * 2280*da6c28aaSamw * A DEMAND packet must always be sent to the well known UDP port - 2281*da6c28aaSamw * NAME_SERVICE_UDP_PORT. There is no restriction on the target IP 2282*da6c28aaSamw * address. 2283*da6c28aaSamw * 2284*da6c28aaSamw * Terms used in this section: 2285*da6c28aaSamw * 2286*da6c28aaSamw * tid - Transaction ID. This is a value composed from 2287*da6c28aaSamw * the requestor's IP address and a unique 16 bit 2288*da6c28aaSamw * value generated by the originator of the 2289*da6c28aaSamw * transaction. 2290*da6c28aaSamw */ 2291*da6c28aaSamw 2292*da6c28aaSamw 2293*da6c28aaSamw /* 2294*da6c28aaSamw * 2295*da6c28aaSamw * 5.1.1. B-NODE ACTIVITY 2296*da6c28aaSamw * 2297*da6c28aaSamw * 5.1.1.1. B-NODE ADD NAME 2298*da6c28aaSamw * 2299*da6c28aaSamw * PROCEDURE add_name(name) 2300*da6c28aaSamw * 2301*da6c28aaSamw * (* 2302*da6c28aaSamw * * Host initiated processing for a B node 2303*da6c28aaSamw * *) 2304*da6c28aaSamw * BEGIN 2305*da6c28aaSamw * 2306*da6c28aaSamw * REPEAT 2307*da6c28aaSamw * 2308*da6c28aaSamw * (* build name service packet *) 2309*da6c28aaSamw * 2310*da6c28aaSamw * ONT = B_NODE; (* broadcast node *) 2311*da6c28aaSamw * G = UNIQUE; (* unique name *) 2312*da6c28aaSamw * TTL = 0; 2313*da6c28aaSamw * 2314*da6c28aaSamw * broadcast NAME REGISTRATION REQUEST packet; 2315*da6c28aaSamw * 2316*da6c28aaSamw * (* 2317*da6c28aaSamw * * remote node(s) will send response packet 2318*da6c28aaSamw * * if applicable 2319*da6c28aaSamw * *) 2320*da6c28aaSamw * pause(BCAST_REQ_RETRY_TIMEOUT); 2321*da6c28aaSamw * 2322*da6c28aaSamw * UNTIL response packet is received or 2323*da6c28aaSamw * retransmit count has been exceeded 2324*da6c28aaSamw * 2325*da6c28aaSamw * IF no response packet was received THEN 2326*da6c28aaSamw * BEGIN (* no response *) 2327*da6c28aaSamw * (* 2328*da6c28aaSamw * * Build packet 2329*da6c28aaSamw * *) 2330*da6c28aaSamw * 2331*da6c28aaSamw * ONT = B_NODE; (* broadcast node *) 2332*da6c28aaSamw * G = UNIQUE; (* unique name *) 2333*da6c28aaSamw * TTL = 0; 2334*da6c28aaSamw * 2335*da6c28aaSamw * (* 2336*da6c28aaSamw * * Let other nodes known you have the name 2337*da6c28aaSamw * *) 2338*da6c28aaSamw * 2339*da6c28aaSamw * broadcast NAME UPDATE REQUEST packet; 2340*da6c28aaSamw * (* name can be added to local name table *) 2341*da6c28aaSamw * return success; 2342*da6c28aaSamw * END (* no response *) 2343*da6c28aaSamw * ELSE 2344*da6c28aaSamw * BEGIN (* got response *) 2345*da6c28aaSamw * 2346*da6c28aaSamw * (* 2347*da6c28aaSamw * * Match return transaction id 2348*da6c28aaSamw * * against tid sent in request 2349*da6c28aaSamw * *) 2350*da6c28aaSamw * 2351*da6c28aaSamw * IF NOT response tid = request tid THEN 2352*da6c28aaSamw * BEGIN 2353*da6c28aaSamw * ignore response packet; 2354*da6c28aaSamw * END 2355*da6c28aaSamw * ELSE 2356*da6c28aaSamw * CASE packet type OF 2357*da6c28aaSamw * 2358*da6c28aaSamw * NEGATIVE NAME REGISTRATION RESPONSE: 2359*da6c28aaSamw * 2360*da6c28aaSamw * return failure; (* name cannot be added *) 2361*da6c28aaSamw * 2362*da6c28aaSamw * POSITIVE NAME REGISTRATION RESPONSE: 2363*da6c28aaSamw * END-NODE CHALLENGE NAME REGISTRATION RESPONSE: 2364*da6c28aaSamw * 2365*da6c28aaSamw * (* 2366*da6c28aaSamw * * B nodes should normally not get this 2367*da6c28aaSamw * * response. 2368*da6c28aaSamw * *) 2369*da6c28aaSamw * 2370*da6c28aaSamw * ignore packet; 2371*da6c28aaSamw * END (* case *); 2372*da6c28aaSamw * END (* got response *) 2373*da6c28aaSamw * END (* procedure *) 2374*da6c28aaSamw * 2375*da6c28aaSamw * 2376*da6c28aaSamw * 2377*da6c28aaSamw * 5.1.1.2. B-NODE ADD_GROUP NAME 2378*da6c28aaSamw * 2379*da6c28aaSamw * PROCEDURE add_group_name(name) 2380*da6c28aaSamw * 2381*da6c28aaSamw * (* 2382*da6c28aaSamw * * Host initiated processing for a B node 2383*da6c28aaSamw * *) 2384*da6c28aaSamw * 2385*da6c28aaSamw * BEGIN 2386*da6c28aaSamw * (* 2387*da6c28aaSamw * * same as for a unique name with the 2388*da6c28aaSamw * * exception that the group bit (G) must 2389*da6c28aaSamw * * be set in the request packets. 2390*da6c28aaSamw * *) 2391*da6c28aaSamw * 2392*da6c28aaSamw * ... 2393*da6c28aaSamw * G = GROUP; 2394*da6c28aaSamw * ... 2395*da6c28aaSamw * ... 2396*da6c28aaSamw * 2397*da6c28aaSamw * (* 2398*da6c28aaSamw * * broadcast request ... 2399*da6c28aaSamw * *) 2400*da6c28aaSamw * 2401*da6c28aaSamw * 2402*da6c28aaSamw * END 2403*da6c28aaSamw */ 2404*da6c28aaSamw static int 2405*da6c28aaSamw smb_name_Bnode_add_name(struct name_entry *name) 2406*da6c28aaSamw { 2407*da6c28aaSamw struct name_question question; 2408*da6c28aaSamw struct resource_record additional; 2409*da6c28aaSamw unsigned char data[8]; 2410*da6c28aaSamw unsigned short attr; 2411*da6c28aaSamw struct addr_entry *addr; 2412*da6c28aaSamw int rc = 0; 2413*da6c28aaSamw 2414*da6c28aaSamw addr = &name->addr_list; 2415*da6c28aaSamw 2416*da6c28aaSamw do { 2417*da6c28aaSamw /* build name service packet */ 2418*da6c28aaSamw question.name = name; 2419*da6c28aaSamw /* 2420*da6c28aaSamw * question.name->attributes |= NAME_NB_FLAGS_ONT_B; 2421*da6c28aaSamw * This is commented because NAME_NB_FLAGS_ONT_B is 0 2422*da6c28aaSamw */ 2423*da6c28aaSamw question.question_type = NAME_QUESTION_TYPE_NB; 2424*da6c28aaSamw question.question_class = NAME_QUESTION_CLASS_IN; 2425*da6c28aaSamw 2426*da6c28aaSamw additional.name = name; 2427*da6c28aaSamw additional.rr_class = NAME_QUESTION_CLASS_IN; 2428*da6c28aaSamw additional.ttl = 0; 2429*da6c28aaSamw additional.rdata = data; 2430*da6c28aaSamw additional.rdlength = 6; 2431*da6c28aaSamw additional.rr_type = NAME_QUESTION_TYPE_NB; 2432*da6c28aaSamw attr = name->attributes & (NAME_ATTR_GROUP | 2433*da6c28aaSamw NAME_ATTR_OWNER_NODE_TYPE); 2434*da6c28aaSamw 2435*da6c28aaSamw BE_OUT16(&data[0], attr); 2436*da6c28aaSamw (void) memcpy(&data[2], &addr->sin.sin_addr.s_addr, 2437*da6c28aaSamw sizeof (uint32_t)); 2438*da6c28aaSamw 2439*da6c28aaSamw rc |= smb_send_name_registration_request(BROADCAST, &question, 2440*da6c28aaSamw &additional); 2441*da6c28aaSamw addr = addr->forw; 2442*da6c28aaSamw 2443*da6c28aaSamw } while (addr != &name->addr_list); 2444*da6c28aaSamw 2445*da6c28aaSamw return (rc); 2446*da6c28aaSamw } 2447*da6c28aaSamw 2448*da6c28aaSamw /* 2449*da6c28aaSamw * 5.1.1.3. B-NODE FIND_NAME 2450*da6c28aaSamw * 2451*da6c28aaSamw * PROCEDURE find_name(name) 2452*da6c28aaSamw * 2453*da6c28aaSamw * (* 2454*da6c28aaSamw * * Host initiated processing for a B node 2455*da6c28aaSamw * *) 2456*da6c28aaSamw * 2457*da6c28aaSamw * BEGIN 2458*da6c28aaSamw * 2459*da6c28aaSamw * REPEAT 2460*da6c28aaSamw * (* 2461*da6c28aaSamw * * build packet 2462*da6c28aaSamw * *) 2463*da6c28aaSamw * ONT = B; 2464*da6c28aaSamw * TTL = 0; 2465*da6c28aaSamw * G = DONT CARE; 2466*da6c28aaSamw * raddr = raddr->forw; 2467*da6c28aaSamw * 2468*da6c28aaSamw * broadcast NAME QUERY REQUEST packet; 2469*da6c28aaSamw * (* 2470*da6c28aaSamw * * a node might send response packet 2471*da6c28aaSamw * *) 2472*da6c28aaSamw * 2473*da6c28aaSamw * pause(BCAST_REQ_RETRY_TIMEOUT); 2474*da6c28aaSamw * UNTIL response packet received OR 2475*da6c28aaSamw * max transmit threshold exceeded 2476*da6c28aaSamw * 2477*da6c28aaSamw * IF no response packet received THEN 2478*da6c28aaSamw * return failure; 2479*da6c28aaSamw * ELSE 2480*da6c28aaSamw * IF NOT response tid = request tid THEN 2481*da6c28aaSamw * ignore packet; 2482*da6c28aaSamw * ELSE 2483*da6c28aaSamw * CASE packet type OF 2484*da6c28aaSamw * POSITIVE NAME QUERY RESPONSE: 2485*da6c28aaSamw * (* 2486*da6c28aaSamw * * Start a timer to detect conflict. 2487*da6c28aaSamw * * 2488*da6c28aaSamw * * Be prepared to detect conflict if 2489*da6c28aaSamw * * any more response packets are received. 2490*da6c28aaSamw * * 2491*da6c28aaSamw * *) 2492*da6c28aaSamw * 2493*da6c28aaSamw * save response as authoritative response; 2494*da6c28aaSamw * start_timer(CONFLICT_TIMER); 2495*da6c28aaSamw * return success; 2496*da6c28aaSamw * 2497*da6c28aaSamw * NEGATIVE NAME QUERY RESPONSE: 2498*da6c28aaSamw * REDIRECT NAME QUERY RESPONSE: 2499*da6c28aaSamw * 2500*da6c28aaSamw * (* 2501*da6c28aaSamw * * B Node should normally not get either 2502*da6c28aaSamw * * response. 2503*da6c28aaSamw * *) 2504*da6c28aaSamw * 2505*da6c28aaSamw * ignore response packet; 2506*da6c28aaSamw * 2507*da6c28aaSamw * END (* case *) 2508*da6c28aaSamw * END (* procedure *) 2509*da6c28aaSamw */ 2510*da6c28aaSamw static int 2511*da6c28aaSamw smb_name_Bnode_find_name(struct name_entry *name) 2512*da6c28aaSamw { 2513*da6c28aaSamw struct name_question question; 2514*da6c28aaSamw 2515*da6c28aaSamw question.name = name; 2516*da6c28aaSamw question.question_type = NAME_QUESTION_TYPE_NB; 2517*da6c28aaSamw question.question_class = NAME_QUESTION_CLASS_IN; 2518*da6c28aaSamw 2519*da6c28aaSamw return (smb_send_name_query_request(BROADCAST, &question)); 2520*da6c28aaSamw } 2521*da6c28aaSamw 2522*da6c28aaSamw /* 2523*da6c28aaSamw * 5.1.1.4. B NODE NAME RELEASE 2524*da6c28aaSamw * 2525*da6c28aaSamw * PROCEDURE delete_name (name) 2526*da6c28aaSamw * BEGIN 2527*da6c28aaSamw * 2528*da6c28aaSamw * REPEAT 2529*da6c28aaSamw * 2530*da6c28aaSamw * (* 2531*da6c28aaSamw * * build packet 2532*da6c28aaSamw * *) 2533*da6c28aaSamw * ... 2534*da6c28aaSamw * 2535*da6c28aaSamw * (* 2536*da6c28aaSamw * * send request 2537*da6c28aaSamw * *) 2538*da6c28aaSamw * 2539*da6c28aaSamw * broadcast NAME RELEASE REQUEST packet; 2540*da6c28aaSamw * 2541*da6c28aaSamw * (* 2542*da6c28aaSamw * * no response packet expected 2543*da6c28aaSamw * *) 2544*da6c28aaSamw * 2545*da6c28aaSamw * pause(BCAST_REQ_RETRY_TIMEOUT); 2546*da6c28aaSamw * 2547*da6c28aaSamw * UNTIL retransmit count has been exceeded 2548*da6c28aaSamw * END (* procedure *) 2549*da6c28aaSamw */ 2550*da6c28aaSamw static int 2551*da6c28aaSamw smb_name_Bnode_delete_name(struct name_entry *name) 2552*da6c28aaSamw { 2553*da6c28aaSamw struct name_question question; 2554*da6c28aaSamw struct resource_record additional; 2555*da6c28aaSamw struct addr_entry *raddr; 2556*da6c28aaSamw unsigned char data[MAX_DATAGRAM_LENGTH]; 2557*da6c28aaSamw unsigned char *scan = data; 2558*da6c28aaSamw uint32_t attr; 2559*da6c28aaSamw 2560*da6c28aaSamw /* build packet */ 2561*da6c28aaSamw question.name = name; 2562*da6c28aaSamw question.question_type = NAME_QUESTION_TYPE_NB; 2563*da6c28aaSamw question.question_class = NAME_QUESTION_CLASS_IN; 2564*da6c28aaSamw 2565*da6c28aaSamw additional.name = name; 2566*da6c28aaSamw additional.rr_class = NAME_QUESTION_CLASS_IN; 2567*da6c28aaSamw additional.ttl = 0; 2568*da6c28aaSamw additional.rdata = data; 2569*da6c28aaSamw additional.rdlength = 0; 2570*da6c28aaSamw additional.rr_type = NAME_QUESTION_TYPE_NB; 2571*da6c28aaSamw raddr = &name->addr_list; 2572*da6c28aaSamw scan = data; 2573*da6c28aaSamw do { 2574*da6c28aaSamw attr = name->attributes & (NAME_ATTR_GROUP | 2575*da6c28aaSamw NAME_ATTR_OWNER_NODE_TYPE); 2576*da6c28aaSamw 2577*da6c28aaSamw BE_OUT16(scan, attr); scan += 2; 2578*da6c28aaSamw (void) memcpy(scan, &raddr->sin.sin_addr.s_addr, 2579*da6c28aaSamw sizeof (uint32_t)); 2580*da6c28aaSamw scan += 4; 2581*da6c28aaSamw 2582*da6c28aaSamw additional.rdlength += 6; 2583*da6c28aaSamw } while (raddr != &name->addr_list); 2584*da6c28aaSamw 2585*da6c28aaSamw return (smb_send_name_release_request_and_demand(BROADCAST, 2586*da6c28aaSamw &question, &additional)); 2587*da6c28aaSamw } 2588*da6c28aaSamw 2589*da6c28aaSamw /* 2590*da6c28aaSamw * 2591*da6c28aaSamw * 5.1.2. P-NODE ACTIVITY 2592*da6c28aaSamw * 2593*da6c28aaSamw * All packets sent or received by P nodes are unicast UDP packets. 2594*da6c28aaSamw * A P node sends name service requests to the NAME node that is 2595*da6c28aaSamw * specified in the P-node configuration. 2596*da6c28aaSamw * 2597*da6c28aaSamw * 5.1.2.1. P-NODE ADD_NAME 2598*da6c28aaSamw * 2599*da6c28aaSamw * PROCEDURE add_name(name) 2600*da6c28aaSamw * 2601*da6c28aaSamw * (* 2602*da6c28aaSamw * * Host initiated processing for a P node 2603*da6c28aaSamw * *) 2604*da6c28aaSamw * 2605*da6c28aaSamw * BEGIN 2606*da6c28aaSamw * 2607*da6c28aaSamw * REPEAT 2608*da6c28aaSamw * (* 2609*da6c28aaSamw * * build packet 2610*da6c28aaSamw * *) 2611*da6c28aaSamw * 2612*da6c28aaSamw * ONT = P; 2613*da6c28aaSamw * G = UNIQUE; 2614*da6c28aaSamw * ... 2615*da6c28aaSamw * 2616*da6c28aaSamw * (* 2617*da6c28aaSamw * * send request 2618*da6c28aaSamw * *) 2619*da6c28aaSamw * 2620*da6c28aaSamw * unicast NAME REGISTRATION REQUEST packet; 2621*da6c28aaSamw * 2622*da6c28aaSamw * (* 2623*da6c28aaSamw * * NAME will send response packet 2624*da6c28aaSamw * *) 2625*da6c28aaSamw * 2626*da6c28aaSamw * IF receive a WACK RESPONSE THEN 2627*da6c28aaSamw * pause(time from TTL field of response); 2628*da6c28aaSamw * ELSE 2629*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 2630*da6c28aaSamw * UNTIL response packet is received OR 2631*da6c28aaSamw * retransmit count has been exceeded 2632*da6c28aaSamw * 2633*da6c28aaSamw * IF no response packet was received THEN 2634*da6c28aaSamw * BEGIN (* no response *) 2635*da6c28aaSamw * (* 2636*da6c28aaSamw * * NAME is down. Cannot claim name. 2637*da6c28aaSamw * *) 2638*da6c28aaSamw * 2639*da6c28aaSamw * return failure; (* name cannot be claimed *) 2640*da6c28aaSamw * END (* no response *) 2641*da6c28aaSamw * ELSE 2642*da6c28aaSamw * BEGIN (* response *) 2643*da6c28aaSamw * IF NOT response tid = request tid THEN 2644*da6c28aaSamw * BEGIN 2645*da6c28aaSamw * (* Packet may belong to another transaction *) 2646*da6c28aaSamw * ignore response packet; 2647*da6c28aaSamw * END 2648*da6c28aaSamw * ELSE 2649*da6c28aaSamw * CASE packet type OF 2650*da6c28aaSamw * 2651*da6c28aaSamw * POSITIVE NAME REGISTRATION RESPONSE: 2652*da6c28aaSamw * 2653*da6c28aaSamw * (* 2654*da6c28aaSamw * * name can be added 2655*da6c28aaSamw * *) 2656*da6c28aaSamw * 2657*da6c28aaSamw * adjust refresh timeout value, TTL, for this name; 2658*da6c28aaSamw * return success; (* name can be added *) 2659*da6c28aaSamw * 2660*da6c28aaSamw * NEGATIVE NAME REGISTRATION RESPONSE: 2661*da6c28aaSamw * return failure; (* name cannot be added *) 2662*da6c28aaSamw * 2663*da6c28aaSamw * END-NODE CHALLENGE REGISTRATION REQUEST: 2664*da6c28aaSamw * BEGIN (* end node challenge *) 2665*da6c28aaSamw * 2666*da6c28aaSamw * (* 2667*da6c28aaSamw * * The response packet has in it the 2668*da6c28aaSamw * * address of the presumed owner of the 2669*da6c28aaSamw * * name. Challenge that owner. 2670*da6c28aaSamw * * If owner either does not 2671*da6c28aaSamw * * respond or indicates that he no longer 2672*da6c28aaSamw * * owns the name, claim the name. 2673*da6c28aaSamw * * Otherwise, the name cannot be claimed. 2674*da6c28aaSamw * * 2675*da6c28aaSamw * *) 2676*da6c28aaSamw * 2677*da6c28aaSamw * REPEAT 2678*da6c28aaSamw * (* 2679*da6c28aaSamw * * build packet 2680*da6c28aaSamw * *) 2681*da6c28aaSamw * ... 2682*da6c28aaSamw * 2683*da6c28aaSamw * unicast NAME QUERY REQUEST packet to the 2684*da6c28aaSamw * address contained in the END NODE 2685*da6c28aaSamw * CHALLENGE RESPONSE packet; 2686*da6c28aaSamw * 2687*da6c28aaSamw * (* 2688*da6c28aaSamw * * remote node may send response packet 2689*da6c28aaSamw * *) 2690*da6c28aaSamw * 2691*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 2692*da6c28aaSamw * 2693*da6c28aaSamw * UNTIL response packet is received or 2694*da6c28aaSamw * retransmit count has been exceeded 2695*da6c28aaSamw * IF no response packet is received OR 2696*da6c28aaSamw * NEGATIVE NAME QUERY RESPONSE packet 2697*da6c28aaSamw * received THEN 2698*da6c28aaSamw * BEGIN (* update *) 2699*da6c28aaSamw * 2700*da6c28aaSamw * (* 2701*da6c28aaSamw * * name can be claimed 2702*da6c28aaSamw * *) 2703*da6c28aaSamw * 2704*da6c28aaSamw * REPEAT 2705*da6c28aaSamw * 2706*da6c28aaSamw * (* 2707*da6c28aaSamw * * build packet 2708*da6c28aaSamw * *) 2709*da6c28aaSamw * ... 2710*da6c28aaSamw * 2711*da6c28aaSamw * unicast NAME UPDATE REQUEST to NAME; 2712*da6c28aaSamw * 2713*da6c28aaSamw * (* 2714*da6c28aaSamw * * NAME node will send response packet 2715*da6c28aaSamw * *) 2716*da6c28aaSamw * 2717*da6c28aaSamw * IF receive a WACK RESPONSE THEN 2718*da6c28aaSamw * pause(time from TTL field of response); 2719*da6c28aaSamw * ELSE 2720*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 2721*da6c28aaSamw * UNTIL response packet is received or 2722*da6c28aaSamw * retransmit count has been exceeded 2723*da6c28aaSamw * IF no response packet received THEN 2724*da6c28aaSamw * BEGIN (* no response *) 2725*da6c28aaSamw * 2726*da6c28aaSamw * (* 2727*da6c28aaSamw * * name could not be claimed 2728*da6c28aaSamw * *) 2729*da6c28aaSamw * 2730*da6c28aaSamw * return failure; 2731*da6c28aaSamw * END (* no response *) 2732*da6c28aaSamw * ELSE 2733*da6c28aaSamw * CASE packet type OF 2734*da6c28aaSamw * POSITIVE NAME REGISTRATION RESPONSE: 2735*da6c28aaSamw * (* 2736*da6c28aaSamw * * add name 2737*da6c28aaSamw * *) 2738*da6c28aaSamw * return success; 2739*da6c28aaSamw * NEGATIVE NAME REGISTRATION RESPONSE: 2740*da6c28aaSamw * 2741*da6c28aaSamw * (* 2742*da6c28aaSamw * * you lose ... 2743*da6c28aaSamw * *) 2744*da6c28aaSamw * return failure; 2745*da6c28aaSamw * END (* case *) 2746*da6c28aaSamw * END (* update *) 2747*da6c28aaSamw * ELSE 2748*da6c28aaSamw * 2749*da6c28aaSamw * (* 2750*da6c28aaSamw * * received a positive response to the "challenge" 2751*da6c28aaSamw * * Remote node still has name 2752*da6c28aaSamw * *) 2753*da6c28aaSamw * 2754*da6c28aaSamw * return failure; 2755*da6c28aaSamw * END (* end node challenge *) 2756*da6c28aaSamw * END (* response *) 2757*da6c28aaSamw * END (* procedure *) 2758*da6c28aaSamw * 2759*da6c28aaSamw * 2760*da6c28aaSamw * 5.1.2.2. P-NODE ADD GROUP NAME 2761*da6c28aaSamw * 2762*da6c28aaSamw * PROCEDURE add_group_name(name) 2763*da6c28aaSamw * 2764*da6c28aaSamw * (* 2765*da6c28aaSamw * * Host initiated processing for a P node 2766*da6c28aaSamw * *) 2767*da6c28aaSamw * 2768*da6c28aaSamw * BEGIN 2769*da6c28aaSamw * (* 2770*da6c28aaSamw * * same as for a unique name, except that the 2771*da6c28aaSamw * * request packet must indicate that a 2772*da6c28aaSamw * * group name claim is being made. 2773*da6c28aaSamw * *) 2774*da6c28aaSamw * 2775*da6c28aaSamw * ... 2776*da6c28aaSamw * G = GROUP; 2777*da6c28aaSamw * ... 2778*da6c28aaSamw * 2779*da6c28aaSamw * (* 2780*da6c28aaSamw * * send packet 2781*da6c28aaSamw * *) 2782*da6c28aaSamw * ... 2783*da6c28aaSamw * 2784*da6c28aaSamw * 2785*da6c28aaSamw * END 2786*da6c28aaSamw */ 2787*da6c28aaSamw static int 2788*da6c28aaSamw smb_name_Pnode_add_name(struct name_entry *name) 2789*da6c28aaSamw { 2790*da6c28aaSamw struct name_question question; 2791*da6c28aaSamw struct resource_record additional; 2792*da6c28aaSamw unsigned char data[8]; 2793*da6c28aaSamw unsigned short attr; 2794*da6c28aaSamw struct addr_entry *addr; 2795*da6c28aaSamw int rc = 0; 2796*da6c28aaSamw 2797*da6c28aaSamw /* build packet */ 2798*da6c28aaSamw addr = &name->addr_list; 2799*da6c28aaSamw do { 2800*da6c28aaSamw question.name = name; 2801*da6c28aaSamw question.question_type = NAME_QUESTION_TYPE_NB; 2802*da6c28aaSamw question.question_class = NAME_QUESTION_CLASS_IN; 2803*da6c28aaSamw 2804*da6c28aaSamw additional.name = name; 2805*da6c28aaSamw additional.rr_class = NAME_QUESTION_CLASS_IN; 2806*da6c28aaSamw additional.ttl = 0; 2807*da6c28aaSamw additional.rdata = data; 2808*da6c28aaSamw additional.rdlength = 6; 2809*da6c28aaSamw additional.rr_type = NAME_QUESTION_TYPE_NB; 2810*da6c28aaSamw attr = name->attributes & 2811*da6c28aaSamw (NAME_ATTR_GROUP | NAME_ATTR_OWNER_NODE_TYPE); 2812*da6c28aaSamw 2813*da6c28aaSamw BE_OUT16(&data[0], attr); 2814*da6c28aaSamw (void) memcpy(&data[2], &addr->sin.sin_addr.s_addr, 2815*da6c28aaSamw sizeof (uint32_t)); 2816*da6c28aaSamw 2817*da6c28aaSamw rc |= smb_send_name_registration_request(UNICAST, &question, 2818*da6c28aaSamw &additional); 2819*da6c28aaSamw 2820*da6c28aaSamw addr = addr->forw; 2821*da6c28aaSamw 2822*da6c28aaSamw } while (addr != &name->addr_list); 2823*da6c28aaSamw 2824*da6c28aaSamw return (rc); 2825*da6c28aaSamw } 2826*da6c28aaSamw 2827*da6c28aaSamw static int 2828*da6c28aaSamw smb_name_Pnode_refresh_name(struct name_entry *name) 2829*da6c28aaSamw { 2830*da6c28aaSamw struct name_question question; 2831*da6c28aaSamw struct resource_record additional; 2832*da6c28aaSamw unsigned char data[8]; 2833*da6c28aaSamw unsigned short attr; 2834*da6c28aaSamw struct addr_entry *addr; 2835*da6c28aaSamw int rc = 0; 2836*da6c28aaSamw 2837*da6c28aaSamw /* build packet */ 2838*da6c28aaSamw addr = &name->addr_list; 2839*da6c28aaSamw do { 2840*da6c28aaSamw question.name = name; 2841*da6c28aaSamw question.question_type = NAME_QUESTION_TYPE_NB; 2842*da6c28aaSamw question.question_class = NAME_QUESTION_CLASS_IN; 2843*da6c28aaSamw 2844*da6c28aaSamw additional.name = name; 2845*da6c28aaSamw additional.rr_class = NAME_QUESTION_CLASS_IN; 2846*da6c28aaSamw additional.ttl = 0; 2847*da6c28aaSamw additional.rdata = data; 2848*da6c28aaSamw additional.rdlength = 6; 2849*da6c28aaSamw additional.rr_type = NAME_QUESTION_TYPE_NB; 2850*da6c28aaSamw attr = name->attributes & 2851*da6c28aaSamw (NAME_ATTR_GROUP | NAME_ATTR_OWNER_NODE_TYPE); 2852*da6c28aaSamw 2853*da6c28aaSamw BE_OUT16(&data[0], attr); 2854*da6c28aaSamw (void) memcpy(&data[2], &addr->sin.sin_addr.s_addr, 2855*da6c28aaSamw sizeof (uint32_t)); 2856*da6c28aaSamw 2857*da6c28aaSamw rc |= smb_send_name_refresh_request(UNICAST, &question, 2858*da6c28aaSamw &additional, 1); 2859*da6c28aaSamw 2860*da6c28aaSamw addr = addr->forw; 2861*da6c28aaSamw } while (addr != &name->addr_list); 2862*da6c28aaSamw 2863*da6c28aaSamw return (rc); 2864*da6c28aaSamw } 2865*da6c28aaSamw 2866*da6c28aaSamw /* 2867*da6c28aaSamw * 5.1.2.3. P-NODE FIND NAME 2868*da6c28aaSamw * 2869*da6c28aaSamw * PROCEDURE find_name(name) 2870*da6c28aaSamw * 2871*da6c28aaSamw * (* 2872*da6c28aaSamw * * Host initiated processing for a P node 2873*da6c28aaSamw * *) 2874*da6c28aaSamw * 2875*da6c28aaSamw * BEGIN 2876*da6c28aaSamw * REPEAT 2877*da6c28aaSamw * (* 2878*da6c28aaSamw * * build packet 2879*da6c28aaSamw * *) 2880*da6c28aaSamw * 2881*da6c28aaSamw * ONT = P; 2882*da6c28aaSamw * G = DONT CARE; 2883*da6c28aaSamw * 2884*da6c28aaSamw * unicast NAME QUERY REQUEST packet; 2885*da6c28aaSamw * 2886*da6c28aaSamw * (* 2887*da6c28aaSamw * * a NAME node might send response packet 2888*da6c28aaSamw * *) 2889*da6c28aaSamw * 2890*da6c28aaSamw * IF receive a WACK RESPONSE THEN 2891*da6c28aaSamw * pause(time from TTL field of response); 2892*da6c28aaSamw * ELSE 2893*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 2894*da6c28aaSamw * UNTIL response packet received OR 2895*da6c28aaSamw * max transmit threshold exceeded 2896*da6c28aaSamw * 2897*da6c28aaSamw * IF no response packet received THEN 2898*da6c28aaSamw * return failure; 2899*da6c28aaSamw * ELSE 2900*da6c28aaSamw * IF NOT response tid = request tid THEN 2901*da6c28aaSamw * ignore packet; 2902*da6c28aaSamw * ELSE 2903*da6c28aaSamw * CASE packet type OF 2904*da6c28aaSamw * POSITIVE NAME QUERY RESPONSE: 2905*da6c28aaSamw * return success; 2906*da6c28aaSamw * 2907*da6c28aaSamw * REDIRECT NAME QUERY RESPONSE: 2908*da6c28aaSamw * 2909*da6c28aaSamw * (* 2910*da6c28aaSamw * * NAME node wants this end node 2911*da6c28aaSamw * * to use some other NAME node 2912*da6c28aaSamw * * to resolve the query. 2913*da6c28aaSamw * *) 2914*da6c28aaSamw * 2915*da6c28aaSamw * repeat query with NAME address 2916*da6c28aaSamw * in the response packet; 2917*da6c28aaSamw * NEGATIVE NAME QUERY RESPONSE: 2918*da6c28aaSamw * return failure; 2919*da6c28aaSamw * 2920*da6c28aaSamw * END (* case *) 2921*da6c28aaSamw * END (* procedure *) 2922*da6c28aaSamw */ 2923*da6c28aaSamw static int 2924*da6c28aaSamw smb_name_Pnode_find_name(struct name_entry *name) 2925*da6c28aaSamw { 2926*da6c28aaSamw struct name_question question; 2927*da6c28aaSamw 2928*da6c28aaSamw /* 2929*da6c28aaSamw * Host initiated processing for a P node 2930*da6c28aaSamw */ 2931*da6c28aaSamw question.name = name; 2932*da6c28aaSamw question.name->attributes |= NAME_NB_FLAGS_ONT_P; 2933*da6c28aaSamw question.question_type = NAME_QUESTION_TYPE_NB; 2934*da6c28aaSamw question.question_class = NAME_QUESTION_CLASS_IN; 2935*da6c28aaSamw 2936*da6c28aaSamw return (smb_send_name_query_request(UNICAST, &question)); 2937*da6c28aaSamw } 2938*da6c28aaSamw 2939*da6c28aaSamw /* 2940*da6c28aaSamw * 5.1.2.4. P-NODE DELETE_NAME 2941*da6c28aaSamw * 2942*da6c28aaSamw * PROCEDURE delete_name (name) 2943*da6c28aaSamw * 2944*da6c28aaSamw * (* 2945*da6c28aaSamw * * Host initiated processing for a P node 2946*da6c28aaSamw * *) 2947*da6c28aaSamw * 2948*da6c28aaSamw * BEGIN 2949*da6c28aaSamw * 2950*da6c28aaSamw * REPEAT 2951*da6c28aaSamw * 2952*da6c28aaSamw * (* 2953*da6c28aaSamw * * build packet 2954*da6c28aaSamw * *) 2955*da6c28aaSamw * ... 2956*da6c28aaSamw * 2957*da6c28aaSamw * (* 2958*da6c28aaSamw * * send request 2959*da6c28aaSamw * *) 2960*da6c28aaSamw * 2961*da6c28aaSamw * unicast NAME RELEASE REQUEST packet; 2962*da6c28aaSamw * IF receive a WACK RESPONSE THEN 2963*da6c28aaSamw * pause(time from TTL field of response); 2964*da6c28aaSamw * ELSE 2965*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 2966*da6c28aaSamw * UNTIL retransmit count has been exceeded 2967*da6c28aaSamw * or response been received 2968*da6c28aaSamw * 2969*da6c28aaSamw * IF response has been received THEN 2970*da6c28aaSamw * CASE packet type OF 2971*da6c28aaSamw * POSITIVE NAME RELEASE RESPONSE: 2972*da6c28aaSamw * return success; 2973*da6c28aaSamw * NEGATIVE NAME RELEASE RESPONSE: 2974*da6c28aaSamw * 2975*da6c28aaSamw * (* 2976*da6c28aaSamw * * NAME does want node to delete this 2977*da6c28aaSamw * * name !!! 2978*da6c28aaSamw * *) 2979*da6c28aaSamw * 2980*da6c28aaSamw * return failure; 2981*da6c28aaSamw * END (* case *) 2982*da6c28aaSamw * END (* procedure *) 2983*da6c28aaSamw */ 2984*da6c28aaSamw static int 2985*da6c28aaSamw smb_name_Pnode_delete_name(struct name_entry *name) 2986*da6c28aaSamw { 2987*da6c28aaSamw struct name_question question; 2988*da6c28aaSamw struct resource_record additional; 2989*da6c28aaSamw struct addr_entry *raddr; 2990*da6c28aaSamw unsigned char data[MAX_DATAGRAM_LENGTH]; 2991*da6c28aaSamw unsigned char *scan = data; 2992*da6c28aaSamw uint32_t attr; 2993*da6c28aaSamw 2994*da6c28aaSamw /* build packet */ 2995*da6c28aaSamw question.name = name; 2996*da6c28aaSamw question.name->attributes |= NAME_NB_FLAGS_ONT_P; 2997*da6c28aaSamw question.question_type = NAME_QUESTION_TYPE_NB; 2998*da6c28aaSamw question.question_class = NAME_QUESTION_CLASS_IN; 2999*da6c28aaSamw 3000*da6c28aaSamw additional.name = name; 3001*da6c28aaSamw additional.rr_class = NAME_QUESTION_CLASS_IN; 3002*da6c28aaSamw additional.ttl = 0; 3003*da6c28aaSamw additional.rdata = data; 3004*da6c28aaSamw additional.rdlength = 0; 3005*da6c28aaSamw additional.rr_type = NAME_QUESTION_TYPE_NB; 3006*da6c28aaSamw raddr = &name->addr_list; 3007*da6c28aaSamw do { 3008*da6c28aaSamw scan = data; 3009*da6c28aaSamw attr = name->attributes & (NAME_ATTR_GROUP | 3010*da6c28aaSamw NAME_ATTR_OWNER_NODE_TYPE); 3011*da6c28aaSamw 3012*da6c28aaSamw BE_OUT16(scan, attr); scan += 2; 3013*da6c28aaSamw BE_OUT32(scan, raddr->sin.sin_addr.s_addr); scan += 4; 3014*da6c28aaSamw (void) memcpy(scan, &raddr->sin.sin_addr.s_addr, 3015*da6c28aaSamw sizeof (uint32_t)); 3016*da6c28aaSamw scan += 4; 3017*da6c28aaSamw 3018*da6c28aaSamw additional.rdlength = 6; 3019*da6c28aaSamw raddr = raddr->forw; 3020*da6c28aaSamw (void) smb_send_name_release_request_and_demand(UNICAST, 3021*da6c28aaSamw &question, &additional); 3022*da6c28aaSamw } while (raddr != &name->addr_list); 3023*da6c28aaSamw 3024*da6c28aaSamw return (1); 3025*da6c28aaSamw } 3026*da6c28aaSamw 3027*da6c28aaSamw /* 3028*da6c28aaSamw * 5.1.3. M-NODE ACTIVITY 3029*da6c28aaSamw * 3030*da6c28aaSamw * M nodes behavior is similar to that of P nodes with the addition 3031*da6c28aaSamw * of some B node-like broadcast actions. M node name service 3032*da6c28aaSamw * proceeds in two steps: 3033*da6c28aaSamw * 3034*da6c28aaSamw * 1.Use broadcast UDP based name service. Depending on the 3035*da6c28aaSamw * operation, goto step 2. 3036*da6c28aaSamw * 3037*da6c28aaSamw * 2.Use directed UDP name service. 3038*da6c28aaSamw * 3039*da6c28aaSamw * The following code for M nodes is exactly the same as for a P 3040*da6c28aaSamw * node, with the exception that broadcast operations are done 3041*da6c28aaSamw * before P type operation is attempted. 3042*da6c28aaSamw * 3043*da6c28aaSamw * 5.1.3.1. M-NODE ADD NAME 3044*da6c28aaSamw * 3045*da6c28aaSamw * PROCEDURE add_name(name) 3046*da6c28aaSamw * 3047*da6c28aaSamw * (* 3048*da6c28aaSamw * * Host initiated processing for a M node 3049*da6c28aaSamw * *) 3050*da6c28aaSamw * 3051*da6c28aaSamw * BEGIN 3052*da6c28aaSamw * 3053*da6c28aaSamw * (* 3054*da6c28aaSamw * * check if name exists on the 3055*da6c28aaSamw * * broadcast area 3056*da6c28aaSamw * *) 3057*da6c28aaSamw * REPEAT 3058*da6c28aaSamw * (* build packet *) 3059*da6c28aaSamw * 3060*da6c28aaSamw * .... 3061*da6c28aaSamw * broadcast NAME REGISTRATION REQUEST packet; 3062*da6c28aaSamw * pause(BCAST_REQ_RETRY_TIMEOUT); 3063*da6c28aaSamw * 3064*da6c28aaSamw * UNTIL response packet is received or 3065*da6c28aaSamw * retransmit count has been exceeded 3066*da6c28aaSamw * 3067*da6c28aaSamw * IF valid response received THEN 3068*da6c28aaSamw * BEGIN 3069*da6c28aaSamw * (* cannot claim name *) 3070*da6c28aaSamw * 3071*da6c28aaSamw * return failure; 3072*da6c28aaSamw * END 3073*da6c28aaSamw * 3074*da6c28aaSamw * (* 3075*da6c28aaSamw * * No objections received within the 3076*da6c28aaSamw * * broadcast area. 3077*da6c28aaSamw * * Send request to name server. 3078*da6c28aaSamw * *) 3079*da6c28aaSamw * 3080*da6c28aaSamw * REPEAT 3081*da6c28aaSamw * (* 3082*da6c28aaSamw * * build packet 3083*da6c28aaSamw * *) 3084*da6c28aaSamw * 3085*da6c28aaSamw * ONT = M; 3086*da6c28aaSamw * ... 3087*da6c28aaSamw * 3088*da6c28aaSamw * unicast NAME REGISTRATION REQUEST packet; 3089*da6c28aaSamw * 3090*da6c28aaSamw * (* 3091*da6c28aaSamw * * remote NAME will send response packet 3092*da6c28aaSamw * *) 3093*da6c28aaSamw * 3094*da6c28aaSamw * IF receive a WACK RESPONSE THEN 3095*da6c28aaSamw * pause(time from TTL field of response); 3096*da6c28aaSamw * ELSE 3097*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 3098*da6c28aaSamw * 3099*da6c28aaSamw * UNTIL response packet is received or 3100*da6c28aaSamw * retransmit count has been exceeded 3101*da6c28aaSamw * 3102*da6c28aaSamw * IF no response packet was received THEN 3103*da6c28aaSamw * BEGIN (* no response *) 3104*da6c28aaSamw * (* 3105*da6c28aaSamw * * NAME is down. Cannot claim name. 3106*da6c28aaSamw * *) 3107*da6c28aaSamw * return failure; (* name cannot be claimed *) 3108*da6c28aaSamw * END (* no response *) 3109*da6c28aaSamw * ELSE 3110*da6c28aaSamw * BEGIN (* response *) 3111*da6c28aaSamw * IF NOT response tid = request tid THEN 3112*da6c28aaSamw * BEGIN 3113*da6c28aaSamw * ignore response packet; 3114*da6c28aaSamw * END 3115*da6c28aaSamw * ELSE 3116*da6c28aaSamw * CASE packet type OF 3117*da6c28aaSamw * POSITIVE NAME REGISTRATION RESPONSE: 3118*da6c28aaSamw * 3119*da6c28aaSamw * (* 3120*da6c28aaSamw * * name can be added 3121*da6c28aaSamw * *) 3122*da6c28aaSamw * 3123*da6c28aaSamw * adjust refresh timeout value, TTL; 3124*da6c28aaSamw * return success; (* name can be added *) 3125*da6c28aaSamw * 3126*da6c28aaSamw * NEGATIVE NAME REGISTRATION RESPONSE: 3127*da6c28aaSamw * return failure; (* name cannot be added *) 3128*da6c28aaSamw * 3129*da6c28aaSamw * END-NODE CHALLENGE REGISTRATION REQUEST: 3130*da6c28aaSamw * BEGIN (* end node challenge *) 3131*da6c28aaSamw * 3132*da6c28aaSamw * (* 3133*da6c28aaSamw * * The response packet has in it the 3134*da6c28aaSamw * * address of the presumed owner of the 3135*da6c28aaSamw * * name. Challenge that owner. 3136*da6c28aaSamw * * If owner either does not 3137*da6c28aaSamw * * respond or indicates that he no longer 3138*da6c28aaSamw * * owns the name, claim the name. 3139*da6c28aaSamw * * Otherwise, the name cannot be claimed. 3140*da6c28aaSamw * * 3141*da6c28aaSamw * *) 3142*da6c28aaSamw * 3143*da6c28aaSamw * REPEAT 3144*da6c28aaSamw * (* 3145*da6c28aaSamw * * build packet 3146*da6c28aaSamw * *) 3147*da6c28aaSamw * ... 3148*da6c28aaSamw * 3149*da6c28aaSamw * (* 3150*da6c28aaSamw * * send packet to address contained in the 3151*da6c28aaSamw * * response packet 3152*da6c28aaSamw * *) 3153*da6c28aaSamw * 3154*da6c28aaSamw * unicast NAME QUERY REQUEST packet; 3155*da6c28aaSamw * 3156*da6c28aaSamw * (* 3157*da6c28aaSamw * * remote node may send response packet 3158*da6c28aaSamw * *) 3159*da6c28aaSamw * 3160*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 3161*da6c28aaSamw * 3162*da6c28aaSamw * UNTIL response packet is received or 3163*da6c28aaSamw * retransmit count has been exceeded 3164*da6c28aaSamw * IF no response packet is received THEN 3165*da6c28aaSamw * BEGIN (* no response *) 3166*da6c28aaSamw * 3167*da6c28aaSamw * (* 3168*da6c28aaSamw * * name can be claimed 3169*da6c28aaSamw * *) 3170*da6c28aaSamw * REPEAT 3171*da6c28aaSamw * 3172*da6c28aaSamw * (* 3173*da6c28aaSamw * * build packet 3174*da6c28aaSamw * *) 3175*da6c28aaSamw * ... 3176*da6c28aaSamw * 3177*da6c28aaSamw * unicast NAME UPDATE REQUEST to NAME; 3178*da6c28aaSamw * 3179*da6c28aaSamw * (* 3180*da6c28aaSamw * * NAME node will send response packet 3181*da6c28aaSamw * *) 3182*da6c28aaSamw * 3183*da6c28aaSamw * IF receive a WACK RESPONSE THEN 3184*da6c28aaSamw * pause(time from TTL field of response); 3185*da6c28aaSamw * ELSE 3186*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 3187*da6c28aaSamw * 3188*da6c28aaSamw * UNTIL response packet is received or 3189*da6c28aaSamw * retransmit count has been exceeded 3190*da6c28aaSamw * IF no response packet received THEN 3191*da6c28aaSamw * BEGIN (* no response *) 3192*da6c28aaSamw * 3193*da6c28aaSamw * (* 3194*da6c28aaSamw * * name could not be claimed 3195*da6c28aaSamw * *) 3196*da6c28aaSamw * 3197*da6c28aaSamw * return failure; 3198*da6c28aaSamw * END (* no response *) 3199*da6c28aaSamw * ELSE 3200*da6c28aaSamw * CASE packet type OF 3201*da6c28aaSamw * POSITIVE NAME REGISTRATION RESPONSE: 3202*da6c28aaSamw * (* 3203*da6c28aaSamw * * add name 3204*da6c28aaSamw * *) 3205*da6c28aaSamw * 3206*da6c28aaSamw * return success; 3207*da6c28aaSamw * NEGATIVE NAME REGISTRATION RESPONSE: 3208*da6c28aaSamw * (* 3209*da6c28aaSamw * * you lose ... 3210*da6c28aaSamw * *) 3211*da6c28aaSamw * 3212*da6c28aaSamw * return failure; 3213*da6c28aaSamw * END (* case *) 3214*da6c28aaSamw * END (* no response *) 3215*da6c28aaSamw * ELSE 3216*da6c28aaSamw * IF NOT response tid = request tid THEN 3217*da6c28aaSamw * BEGIN 3218*da6c28aaSamw * ignore response packet; 3219*da6c28aaSamw * END 3220*da6c28aaSamw * 3221*da6c28aaSamw * (* 3222*da6c28aaSamw * * received a response to the "challenge" 3223*da6c28aaSamw * * packet 3224*da6c28aaSamw * *) 3225*da6c28aaSamw * 3226*da6c28aaSamw * CASE packet type OF 3227*da6c28aaSamw * POSITIVE NAME QUERY: 3228*da6c28aaSamw * 3229*da6c28aaSamw * (* 3230*da6c28aaSamw * * remote node still has name. 3231*da6c28aaSamw * *) 3232*da6c28aaSamw * 3233*da6c28aaSamw * return failure; 3234*da6c28aaSamw * NEGATIVE NAME QUERY: 3235*da6c28aaSamw * 3236*da6c28aaSamw * (* 3237*da6c28aaSamw * * remote node no longer has name 3238*da6c28aaSamw * *) 3239*da6c28aaSamw * 3240*da6c28aaSamw * return success; 3241*da6c28aaSamw * END (* case *) 3242*da6c28aaSamw * END (* end node challenge *) 3243*da6c28aaSamw * END (* case *) 3244*da6c28aaSamw * END (* response *) 3245*da6c28aaSamw * END (* procedure *) 3246*da6c28aaSamw * 3247*da6c28aaSamw * 3248*da6c28aaSamw * 5.1.3.2. M-NODE ADD GROUP NAME 3249*da6c28aaSamw * 3250*da6c28aaSamw * PROCEDURE add_group_name(name) 3251*da6c28aaSamw * 3252*da6c28aaSamw * (* 3253*da6c28aaSamw * * Host initiated processing for a P node 3254*da6c28aaSamw * *) 3255*da6c28aaSamw * 3256*da6c28aaSamw * BEGIN 3257*da6c28aaSamw * (* 3258*da6c28aaSamw * * same as for a unique name, except that the 3259*da6c28aaSamw * * request packet must indicate that a 3260*da6c28aaSamw * * group name claim is being made. 3261*da6c28aaSamw * *) 3262*da6c28aaSamw * 3263*da6c28aaSamw * ... 3264*da6c28aaSamw * G = GROUP; 3265*da6c28aaSamw * ... 3266*da6c28aaSamw * 3267*da6c28aaSamw * (* 3268*da6c28aaSamw * * send packet 3269*da6c28aaSamw * *) 3270*da6c28aaSamw * ... 3271*da6c28aaSamw * 3272*da6c28aaSamw * 3273*da6c28aaSamw * END 3274*da6c28aaSamw */ 3275*da6c28aaSamw static int 3276*da6c28aaSamw smb_name_Mnode_add_name(struct name_entry *name) 3277*da6c28aaSamw { 3278*da6c28aaSamw if (smb_name_Bnode_add_name(name) > 0) { 3279*da6c28aaSamw if (nbns_num == 0) 3280*da6c28aaSamw return (1); /* No name server configured */ 3281*da6c28aaSamw 3282*da6c28aaSamw return (smb_name_Pnode_add_name(name)); 3283*da6c28aaSamw } 3284*da6c28aaSamw return (-1); 3285*da6c28aaSamw } 3286*da6c28aaSamw 3287*da6c28aaSamw static int 3288*da6c28aaSamw smb_name_Hnode_add_name(struct name_entry *name) 3289*da6c28aaSamw { 3290*da6c28aaSamw if (nbns_num > 0) { 3291*da6c28aaSamw if (smb_name_Pnode_add_name(name) == 1) 3292*da6c28aaSamw return (1); 3293*da6c28aaSamw } 3294*da6c28aaSamw 3295*da6c28aaSamw return (smb_name_Bnode_add_name(name)); 3296*da6c28aaSamw } 3297*da6c28aaSamw 3298*da6c28aaSamw /* 3299*da6c28aaSamw * 5.1.3.3. M-NODE FIND NAME 3300*da6c28aaSamw * 3301*da6c28aaSamw * PROCEDURE find_name(name) 3302*da6c28aaSamw * 3303*da6c28aaSamw * (* 3304*da6c28aaSamw * * Host initiated processing for a M node 3305*da6c28aaSamw * *) 3306*da6c28aaSamw * 3307*da6c28aaSamw * BEGIN 3308*da6c28aaSamw * (* 3309*da6c28aaSamw * * check if any node on the broadcast 3310*da6c28aaSamw * * area has the name 3311*da6c28aaSamw * *) 3312*da6c28aaSamw * 3313*da6c28aaSamw * REPEAT 3314*da6c28aaSamw * (* build packet *) 3315*da6c28aaSamw * ... 3316*da6c28aaSamw * 3317*da6c28aaSamw * broadcast NAME QUERY REQUEST packet; 3318*da6c28aaSamw * pause(BCAST_REQ_RETRY_TIMEOUT); 3319*da6c28aaSamw * UNTIL response packet received OR 3320*da6c28aaSamw * max transmit threshold exceeded 3321*da6c28aaSamw * 3322*da6c28aaSamw * IF valid response received THEN 3323*da6c28aaSamw * BEGIN 3324*da6c28aaSamw * save response as authoritative response; 3325*da6c28aaSamw * start_timer(CONFLICT_TIMER); 3326*da6c28aaSamw * return success; 3327*da6c28aaSamw * END 3328*da6c28aaSamw * 3329*da6c28aaSamw * (* 3330*da6c28aaSamw * * no valid response on the b'cast segment. 3331*da6c28aaSamw * * Try the name server. 3332*da6c28aaSamw * *) 3333*da6c28aaSamw * 3334*da6c28aaSamw * REPEAT 3335*da6c28aaSamw * (* 3336*da6c28aaSamw * * build packet 3337*da6c28aaSamw * *) 3338*da6c28aaSamw * 3339*da6c28aaSamw * ONT = M; 3340*da6c28aaSamw * G = DONT CARE; 3341*da6c28aaSamw * 3342*da6c28aaSamw * unicast NAME QUERY REQUEST packet to NAME; 3343*da6c28aaSamw * 3344*da6c28aaSamw * (* 3345*da6c28aaSamw * * a NAME node might send response packet 3346*da6c28aaSamw * *) 3347*da6c28aaSamw * 3348*da6c28aaSamw * IF receive a WACK RESPONSE THEN 3349*da6c28aaSamw * pause(time from TTL field of response); 3350*da6c28aaSamw * ELSE 3351*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 3352*da6c28aaSamw * UNTIL response packet received OR 3353*da6c28aaSamw * max transmit threshold exceeded 3354*da6c28aaSamw * 3355*da6c28aaSamw * IF no response packet received THEN 3356*da6c28aaSamw * return failure; 3357*da6c28aaSamw * ELSE 3358*da6c28aaSamw * IF NOT response tid = request tid THEN 3359*da6c28aaSamw * ignore packet; 3360*da6c28aaSamw * ELSE 3361*da6c28aaSamw * CASE packet type OF 3362*da6c28aaSamw * POSITIVE NAME QUERY RESPONSE: 3363*da6c28aaSamw * return success; 3364*da6c28aaSamw * 3365*da6c28aaSamw * REDIRECT NAME QUERY RESPONSE: 3366*da6c28aaSamw * 3367*da6c28aaSamw * (* 3368*da6c28aaSamw * * NAME node wants this end node 3369*da6c28aaSamw * * to use some other NAME node 3370*da6c28aaSamw * * to resolve the query. 3371*da6c28aaSamw * *) 3372*da6c28aaSamw * 3373*da6c28aaSamw * repeat query with NAME address 3374*da6c28aaSamw * in the response packet; 3375*da6c28aaSamw * NEGATIVE NAME QUERY RESPONSE: 3376*da6c28aaSamw * return failure; 3377*da6c28aaSamw * 3378*da6c28aaSamw * END (* case *) 3379*da6c28aaSamw * END (* procedure *) 3380*da6c28aaSamw */ 3381*da6c28aaSamw static int 3382*da6c28aaSamw smb_name_Mnode_find_name(struct name_entry *name) 3383*da6c28aaSamw { 3384*da6c28aaSamw if (smb_name_Bnode_find_name(name) == 1) 3385*da6c28aaSamw return (1); 3386*da6c28aaSamw 3387*da6c28aaSamw if (nbns_num == 0) 3388*da6c28aaSamw return (1); /* No name server configured */ 3389*da6c28aaSamw 3390*da6c28aaSamw return (smb_name_Pnode_find_name(name)); 3391*da6c28aaSamw } 3392*da6c28aaSamw 3393*da6c28aaSamw static int 3394*da6c28aaSamw smb_name_Hnode_find_name(struct name_entry *name) 3395*da6c28aaSamw { 3396*da6c28aaSamw if (nbns_num > 0) 3397*da6c28aaSamw if (smb_name_Pnode_find_name(name) == 1) 3398*da6c28aaSamw return (1); 3399*da6c28aaSamw 3400*da6c28aaSamw return (smb_name_Bnode_find_name(name)); 3401*da6c28aaSamw } 3402*da6c28aaSamw 3403*da6c28aaSamw /* 3404*da6c28aaSamw * 5.1.3.4. M-NODE DELETE NAME 3405*da6c28aaSamw * 3406*da6c28aaSamw * PROCEDURE delete_name (name) 3407*da6c28aaSamw * 3408*da6c28aaSamw * (* 3409*da6c28aaSamw * * Host initiated processing for a P node 3410*da6c28aaSamw * *) 3411*da6c28aaSamw * 3412*da6c28aaSamw * BEGIN 3413*da6c28aaSamw * (* 3414*da6c28aaSamw * * First, delete name on NAME 3415*da6c28aaSamw * *) 3416*da6c28aaSamw * 3417*da6c28aaSamw * REPEAT 3418*da6c28aaSamw * 3419*da6c28aaSamw * (* 3420*da6c28aaSamw * * build packet 3421*da6c28aaSamw * struct addr_entry *addr; 3422*da6c28aaSamw * *) 3423*da6c28aaSamw * ... 3424*da6c28aaSamw * 3425*da6c28aaSamw * (* 3426*da6c28aaSamw * * send request 3427*da6c28aaSamw * *) 3428*da6c28aaSamw * 3429*da6c28aaSamw * unicast NAME RELEASE REQUEST packet to NAME; 3430*da6c28aaSamw * 3431*da6c28aaSamw * IF receive a WACK RESPONSE THEN 3432*da6c28aaSamw * pause(time from TTL field of response); 3433*da6c28aaSamw * ELSE 3434*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 3435*da6c28aaSamw * UNTIL retransmit count has been exceeded 3436*da6c28aaSamw * or response been received 3437*da6c28aaSamw * 3438*da6c28aaSamw * IF response has been received THEN 3439*da6c28aaSamw * CASE packet type OF 3440*da6c28aaSamw * POSITIVE NAME RELEASE RESPONSE: 3441*da6c28aaSamw * (* 3442*da6c28aaSamw * * Deletion of name on b'cast segment is deferred 3443*da6c28aaSamw * * until after NAME has deleted the name 3444*da6c28aaSamw * *) 3445*da6c28aaSamw * 3446*da6c28aaSamw * REPEAT 3447*da6c28aaSamw * (* build packet *) 3448*da6c28aaSamw * 3449*da6c28aaSamw * ... 3450*da6c28aaSamw * broadcast NAME RELEASE REQUEST; 3451*da6c28aaSamw * pause(BCAST_REQ_RETRY_TIMEOUT); 3452*da6c28aaSamw * UNTIL rexmt threshold exceeded 3453*da6c28aaSamw * 3454*da6c28aaSamw * return success; 3455*da6c28aaSamw * NEGATIVE NAME RELEASE RESPONSE: 3456*da6c28aaSamw * 3457*da6c28aaSamw * (* 3458*da6c28aaSamw * * NAME does want node to delete this 3459*da6c28aaSamw * * name 3460*da6c28aaSamw * *) 3461*da6c28aaSamw * return failure; 3462*da6c28aaSamw * END (* case *) 3463*da6c28aaSamw * END (* procedure *) 3464*da6c28aaSamw */ 3465*da6c28aaSamw static int 3466*da6c28aaSamw smb_name_Mnode_delete_name(struct name_entry *name) 3467*da6c28aaSamw { 3468*da6c28aaSamw (void) smb_name_Bnode_delete_name(name); 3469*da6c28aaSamw 3470*da6c28aaSamw if (nbns_num == 0) 3471*da6c28aaSamw return (-1); /* No name server configured */ 3472*da6c28aaSamw 3473*da6c28aaSamw if (smb_name_Pnode_delete_name(name) > 0) 3474*da6c28aaSamw return (1); 3475*da6c28aaSamw 3476*da6c28aaSamw return (-1); 3477*da6c28aaSamw } 3478*da6c28aaSamw 3479*da6c28aaSamw static int 3480*da6c28aaSamw smb_name_Hnode_delete_name(struct name_entry *name) 3481*da6c28aaSamw { 3482*da6c28aaSamw if (nbns_num > 0) 3483*da6c28aaSamw if (smb_name_Pnode_delete_name(name) > 0) 3484*da6c28aaSamw return (1); 3485*da6c28aaSamw 3486*da6c28aaSamw return (smb_name_Bnode_delete_name(name)); 3487*da6c28aaSamw } 3488*da6c28aaSamw 3489*da6c28aaSamw /* 3490*da6c28aaSamw * 5.1.1.5. B-NODE INCOMING PACKET PROCESSING 3491*da6c28aaSamw * 3492*da6c28aaSamw * Following processing is done when broadcast or unicast packets 3493*da6c28aaSamw * are received at the NAME_SERVICE_UDP_PORT. 3494*da6c28aaSamw * 3495*da6c28aaSamw * PROCEDURE process_incoming_packet(packet) 3496*da6c28aaSamw * 3497*da6c28aaSamw * (* 3498*da6c28aaSamw * * Processing initiated by incoming packets for a B node 3499*da6c28aaSamw * *) 3500*da6c28aaSamw * 3501*da6c28aaSamw * BEGIN 3502*da6c28aaSamw * (* 3503*da6c28aaSamw * * Note: response packets are always sent 3504*da6c28aaSamw * * to: 3505*da6c28aaSamw * * source IP address of request packet 3506*da6c28aaSamw * * source UDP port of request packet 3507*da6c28aaSamw * *) 3508*da6c28aaSamw * 3509*da6c28aaSamw * CASE packet type OF 3510*da6c28aaSamw * 3511*da6c28aaSamw * NAME REGISTRATION REQUEST (UNIQUE): 3512*da6c28aaSamw * IF name exists in local name table THEN 3513*da6c28aaSamw * send NEGATIVE_NAME_REGISTRATION_RESPONSE ; 3514*da6c28aaSamw * NAME REGISTRATION REQUEST (GROUP): 3515*da6c28aaSamw * IF name exists in local name table THEN 3516*da6c28aaSamw * BEGIN 3517*da6c28aaSamw * IF local entry is a unique name THEN 3518*da6c28aaSamw * send NEGATIVE_NAME_REGISTRATION_RESPONSE ; 3519*da6c28aaSamw * END 3520*da6c28aaSamw * NAME QUERY REQUEST: 3521*da6c28aaSamw * IF name exists in local name table THEN 3522*da6c28aaSamw * BEGIN 3523*da6c28aaSamw * build response packet; 3524*da6c28aaSamw * send POSITIVE_NAME_QUERY_RESPONSE; 3525*da6c28aaSamw * POSITIVE NAME QUERY RESPONSE: 3526*da6c28aaSamw * IF name conflict timer is not active THEN 3527*da6c28aaSamw * BEGIN 3528*da6c28aaSamw * (* 3529*da6c28aaSamw * * timer has expired already... ignore this 3530*da6c28aaSamw * * packet 3531*da6c28aaSamw * *) 3532*da6c28aaSamw * 3533*da6c28aaSamw * return; 3534*da6c28aaSamw * END 3535*da6c28aaSamw * ELSE (* timer is active *) 3536*da6c28aaSamw * IF a response for this name has previously been 3537*da6c28aaSamw * received THEN 3538*da6c28aaSamw * BEGIN (* existing entry *) 3539*da6c28aaSamw * 3540*da6c28aaSamw * (* 3541*da6c28aaSamw * * we sent out a request packet, and 3542*da6c28aaSamw * * have already received (at least) 3543*da6c28aaSamw * * one response 3544*da6c28aaSamw * * 3545*da6c28aaSamw * * Check if conflict exists. 3546*da6c28aaSamw * * If so, send out a conflict packet. 3547*da6c28aaSamw * * 3548*da6c28aaSamw * * Note: detecting conflict does NOT 3549*da6c28aaSamw * * affect any existing sessions. 3550*da6c28aaSamw * * 3551*da6c28aaSamw * *) 3552*da6c28aaSamw * 3553*da6c28aaSamw * (* 3554*da6c28aaSamw * * Check for name conflict. 3555*da6c28aaSamw * * See "Name Conflict" in Concepts and Methods 3556*da6c28aaSamw * *) 3557*da6c28aaSamw * check saved authoritative response against 3558*da6c28aaSamw * information in this response packet; 3559*da6c28aaSamw * IF conflict detected THEN 3560*da6c28aaSamw * BEGIN 3561*da6c28aaSamw * unicast NAME CONFLICT DEMAND packet; 3562*da6c28aaSamw * IF entry exists in cache THEN 3563*da6c28aaSamw * BEGIN 3564*da6c28aaSamw * remove entry from cache; 3565*da6c28aaSamw * END 3566*da6c28aaSamw * END 3567*da6c28aaSamw * END (* existing entry *) 3568*da6c28aaSamw * ELSE 3569*da6c28aaSamw * BEGIN 3570*da6c28aaSamw * (* 3571*da6c28aaSamw * * Note: If this was the first response 3572*da6c28aaSamw * * to a name query, it would have been 3573*da6c28aaSamw * * handled in the 3574*da6c28aaSamw * * find_name() procedure. 3575*da6c28aaSamw * *) 3576*da6c28aaSamw * 3577*da6c28aaSamw * ignore packet; 3578*da6c28aaSamw * END 3579*da6c28aaSamw * NAME CONFLICT DEMAND: 3580*da6c28aaSamw * IF name exists in local name table THEN 3581*da6c28aaSamw * BEGIN 3582*da6c28aaSamw * mark name as conflict detected; 3583*da6c28aaSamw * 3584*da6c28aaSamw * (* 3585*da6c28aaSamw * * a name in the state "conflict detected" 3586*da6c28aaSamw * * does not "logically" exist on that node. 3587*da6c28aaSamw * * No further session will be accepted on 3588*da6c28aaSamw * * that name. 3589*da6c28aaSamw * * No datagrams can be sent against that name. 3590*da6c28aaSamw * * Such an entry will not be used for 3591*da6c28aaSamw * * purposes of processing incoming request 3592*da6c28aaSamw * * packets. 3593*da6c28aaSamw * * The only valid user NetBIOS operation 3594*da6c28aaSamw * * against such a name is DELETE NAME. 3595*da6c28aaSamw * *) 3596*da6c28aaSamw * END 3597*da6c28aaSamw * NAME RELEASE REQUEST: 3598*da6c28aaSamw * IF caching is being done THEN 3599*da6c28aaSamw * BEGIN 3600*da6c28aaSamw * remove entry from cache; 3601*da6c28aaSamw * END 3602*da6c28aaSamw * NAME UPDATE REQUEST: 3603*da6c28aaSamw * IF caching is being done THEN 3604*da6c28aaSamw * BEGIN 3605*da6c28aaSamw * IF entry exists in cache already, 3606*da6c28aaSamw * update cache; 3607*da6c28aaSamw * ELSE IF name is "interesting" THEN 3608*da6c28aaSamw * BEGIN 3609*da6c28aaSamw * add entry to cache; 3610*da6c28aaSamw * END 3611*da6c28aaSamw * END 3612*da6c28aaSamw * 3613*da6c28aaSamw * NODE STATUS REQUEST: 3614*da6c28aaSamw * IF name exists in local name table THEN 3615*da6c28aaSamw * BEGIN 3616*da6c28aaSamw * (* 3617*da6c28aaSamw * * send only those names that are 3618*da6c28aaSamw * * in the same scope as the scope 3619*da6c28aaSamw * * field in the request packet 3620*da6c28aaSamw * *) 3621*da6c28aaSamw * 3622*da6c28aaSamw * send NODE STATUS RESPONSE; 3623*da6c28aaSamw * END 3624*da6c28aaSamw * END 3625*da6c28aaSamw */ 3626*da6c28aaSamw static void 3627*da6c28aaSamw smb_name_process_Bnode_packet(struct name_packet *packet, 3628*da6c28aaSamw struct addr_entry *addr) 3629*da6c28aaSamw { 3630*da6c28aaSamw struct name_entry *name; 3631*da6c28aaSamw struct name_entry *entry; 3632*da6c28aaSamw struct name_question *question; 3633*da6c28aaSamw struct resource_record *additional; 3634*da6c28aaSamw 3635*da6c28aaSamw question = packet->question; 3636*da6c28aaSamw additional = packet->additional; 3637*da6c28aaSamw 3638*da6c28aaSamw switch (packet->info & NAME_OPCODE_OPCODE_MASK) { 3639*da6c28aaSamw case NAME_OPCODE_REFRESH: 3640*da6c28aaSamw /* Guard against malformed packets */ 3641*da6c28aaSamw if ((question == 0) || (additional == 0)) 3642*da6c28aaSamw break; 3643*da6c28aaSamw if (additional->name->addr_list.sin.sin_addr.s_addr == 0) 3644*da6c28aaSamw break; 3645*da6c28aaSamw 3646*da6c28aaSamw name = question->name; 3647*da6c28aaSamw name->addr_list.ttl = additional->ttl; 3648*da6c28aaSamw name->attributes = additional->name->attributes; 3649*da6c28aaSamw name->addr_list.sin = additional->name->addr_list.sin; 3650*da6c28aaSamw name->addr_list.forw = name->addr_list.back = &name->addr_list; 3651*da6c28aaSamw 3652*da6c28aaSamw if ((entry = smb_netbios_cache_lookup_addr(name)) != 0) { 3653*da6c28aaSamw smb_netbios_cache_update_entry(entry, question->name); 3654*da6c28aaSamw smb_netbios_cache_unlock_entry(entry); 3655*da6c28aaSamw } 3656*da6c28aaSamw else 3657*da6c28aaSamw (void) smb_netbios_cache_insert(question->name); 3658*da6c28aaSamw break; 3659*da6c28aaSamw 3660*da6c28aaSamw case NAME_OPCODE_QUERY: 3661*da6c28aaSamw /* 3662*da6c28aaSamw * This opcode covers both NAME_QUERY_REQUEST and 3663*da6c28aaSamw * NODE_STATUS_REQUEST. They can be distinguished 3664*da6c28aaSamw * based on the type of question entry. 3665*da6c28aaSamw */ 3666*da6c28aaSamw 3667*da6c28aaSamw /* All query requests have to have question entry */ 3668*da6c28aaSamw if (question == 0) 3669*da6c28aaSamw break; 3670*da6c28aaSamw 3671*da6c28aaSamw if (question->question_type == NAME_QUESTION_TYPE_NB) { 3672*da6c28aaSamw name = question->name; 3673*da6c28aaSamw if ((entry = smb_netbios_cache_lookup(name)) != 0) { 3674*da6c28aaSamw (void) smb_send_name_query_response(addr, 3675*da6c28aaSamw packet, entry, 0); 3676*da6c28aaSamw smb_netbios_cache_unlock_entry(entry); 3677*da6c28aaSamw } 3678*da6c28aaSamw } 3679*da6c28aaSamw else 3680*da6c28aaSamw if (question->question_type == NAME_QUESTION_TYPE_NBSTAT) { 3681*da6c28aaSamw /* 3682*da6c28aaSamw * Name of "*" may be used to force node to 3683*da6c28aaSamw * divulge status for administrative purposes 3684*da6c28aaSamw */ 3685*da6c28aaSamw name = question->name; 3686*da6c28aaSamw entry = 0; 3687*da6c28aaSamw if (NETBIOS_NAME_IS_STAR(name->name) || 3688*da6c28aaSamw ((entry = smb_netbios_cache_lookup(name)) != 0)) { 3689*da6c28aaSamw if (entry) 3690*da6c28aaSamw smb_netbios_cache_unlock_entry(entry); 3691*da6c28aaSamw /* 3692*da6c28aaSamw * send only those names that are 3693*da6c28aaSamw * in the same scope as the scope 3694*da6c28aaSamw * field in the request packet 3695*da6c28aaSamw */ 3696*da6c28aaSamw (void) smb_send_node_status_response(addr, 3697*da6c28aaSamw packet); 3698*da6c28aaSamw } 3699*da6c28aaSamw } 3700*da6c28aaSamw break; 3701*da6c28aaSamw 3702*da6c28aaSamw default: 3703*da6c28aaSamw break; 3704*da6c28aaSamw } 3705*da6c28aaSamw } 3706*da6c28aaSamw 3707*da6c28aaSamw /* 3708*da6c28aaSamw * 5.1.2.5. P-NODE INCOMING PACKET PROCESSING 3709*da6c28aaSamw * 3710*da6c28aaSamw * Processing initiated by reception of packets at a P node 3711*da6c28aaSamw * 3712*da6c28aaSamw * PROCEDURE process_incoming_packet(packet) 3713*da6c28aaSamw * 3714*da6c28aaSamw * (* 3715*da6c28aaSamw * * Processing initiated by incoming packets at a P node 3716*da6c28aaSamw * *) 3717*da6c28aaSamw * 3718*da6c28aaSamw * BEGIN 3719*da6c28aaSamw * (* 3720*da6c28aaSamw * * always ignore UDP broadcast packets 3721*da6c28aaSamw * *) 3722*da6c28aaSamw * 3723*da6c28aaSamw * IF packet was sent as a broadcast THEN 3724*da6c28aaSamw * BEGIN 3725*da6c28aaSamw * ignore packet; 3726*da6c28aaSamw * return; 3727*da6c28aaSamw * END 3728*da6c28aaSamw * CASE packet type of 3729*da6c28aaSamw * 3730*da6c28aaSamw * NAME CONFLICT DEMAND: 3731*da6c28aaSamw * IF name exists in local name table THEN 3732*da6c28aaSamw * mark name as in conflict; 3733*da6c28aaSamw * return; 3734*da6c28aaSamw * 3735*da6c28aaSamw * NAME QUERY REQUEST: 3736*da6c28aaSamw * IF name exists in local name table THEN 3737*da6c28aaSamw * BEGIN (* name exists *) 3738*da6c28aaSamw * 3739*da6c28aaSamw * (* 3740*da6c28aaSamw * * build packet 3741*da6c28aaSamw * *) 3742*da6c28aaSamw * ... 3743*da6c28aaSamw * 3744*da6c28aaSamw * (* 3745*da6c28aaSamw * * send response to the IP address and port 3746*da6c28aaSamw * * number from which the request was received. 3747*da6c28aaSamw * *) 3748*da6c28aaSamw * 3749*da6c28aaSamw * send POSITIVE_NAME_QUERY_RESPONSE ; 3750*da6c28aaSamw * return; 3751*da6c28aaSamw * END (* exists *) 3752*da6c28aaSamw * ELSE 3753*da6c28aaSamw * BEGIN (* does not exist *) 3754*da6c28aaSamw * 3755*da6c28aaSamw * (* 3756*da6c28aaSamw * * send response to the requestor 3757*da6c28aaSamw * *) 3758*da6c28aaSamw * 3759*da6c28aaSamw * send NEGATIVE_NAME_QUERY_RESPONSE ; 3760*da6c28aaSamw * return; 3761*da6c28aaSamw * END (* does not exist *) 3762*da6c28aaSamw * NODE STATUS REQUEST: 3763*da6c28aaSamw * (* 3764*da6c28aaSamw * * Name of "*" may be used for force node to 3765*da6c28aaSamw * * divulge status for administrative purposes 3766*da6c28aaSamw * *) 3767*da6c28aaSamw * IF name in local name table OR name = "*" THEN 3768*da6c28aaSamw * BEGIN 3769*da6c28aaSamw * (* 3770*da6c28aaSamw * * Build response packet and 3771*da6c28aaSamw * * send to requestor node 3772*da6c28aaSamw * * Send only those names that are 3773*da6c28aaSamw * * in the same scope as the scope 3774*da6c28aaSamw * * in the request packet. 3775*da6c28aaSamw * *) 3776*da6c28aaSamw * 3777*da6c28aaSamw * send NODE_STATUS_RESPONSE; 3778*da6c28aaSamw * END 3779*da6c28aaSamw * 3780*da6c28aaSamw * NAME RELEASE REQUEST: 3781*da6c28aaSamw * (* 3782*da6c28aaSamw * * This will be received if the NAME wants to flush the 3783*da6c28aaSamw * * name from the local name table, or from the local 3784*da6c28aaSamw * * cache. 3785*da6c28aaSamw * *) 3786*da6c28aaSamw * 3787*da6c28aaSamw * IF name exists in the local name table THEN 3788*da6c28aaSamw * BEGIN 3789*da6c28aaSamw * delete name from local name table; 3790*da6c28aaSamw * inform user that name has been deleted; 3791*da6c28aaSamw * END 3792*da6c28aaSamw * END (* case *) 3793*da6c28aaSamw * END (* procedure *) 3794*da6c28aaSamw * 3795*da6c28aaSamw * (* 3796*da6c28aaSamw * * Incoming packet processing on a NS node 3797*da6c28aaSamw * *) 3798*da6c28aaSamw * 3799*da6c28aaSamw * BEGIN 3800*da6c28aaSamw * IF packet was sent as a broadcast THEN 3801*da6c28aaSamw * BEGIN 3802*da6c28aaSamw * discard packet; 3803*da6c28aaSamw * return; 3804*da6c28aaSamw * END 3805*da6c28aaSamw * CASE packet type of 3806*da6c28aaSamw * 3807*da6c28aaSamw * NAME REGISTRATION REQUEST (UNIQUE): 3808*da6c28aaSamw * IF unique name exists in data base THEN 3809*da6c28aaSamw * BEGIN (* unique name exists *) 3810*da6c28aaSamw * (* 3811*da6c28aaSamw * * NAME node may be a "passive" 3812*da6c28aaSamw * * server in that it expects the 3813*da6c28aaSamw * * end node to do the challenge 3814*da6c28aaSamw * * server. Such a NAME node is 3815*da6c28aaSamw * * called a "non-secure" server. 3816*da6c28aaSamw * * A "secure" server will do the 3817*da6c28aaSamw * * challenging before it sends 3818*da6c28aaSamw * * back a response packet. 3819*da6c28aaSamw * *) 3820*da6c28aaSamw * 3821*da6c28aaSamw * IF non-secure THEN 3822*da6c28aaSamw * BEGIN 3823*da6c28aaSamw * (* 3824*da6c28aaSamw * * build response packet 3825*da6c28aaSamw * *) 3826*da6c28aaSamw * ... 3827*da6c28aaSamw * 3828*da6c28aaSamw * 3829*da6c28aaSamw * (* 3830*da6c28aaSamw * * let end node do the challenge 3831*da6c28aaSamw * *) 3832*da6c28aaSamw * 3833*da6c28aaSamw * send END-NODE CHALLENGE NAME REGISTRATION 3834*da6c28aaSamw * RESPONSE; 3835*da6c28aaSamw * return; 3836*da6c28aaSamw * END 3837*da6c28aaSamw * ELSE 3838*da6c28aaSamw * (* 3839*da6c28aaSamw * * secure server - do the name 3840*da6c28aaSamw * * challenge operation 3841*da6c28aaSamw * *) 3842*da6c28aaSamw * 3843*da6c28aaSamw * REPEAT 3844*da6c28aaSamw * send NAME QUERY REQUEST; 3845*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 3846*da6c28aaSamw * UNTIL response has been received or 3847*da6c28aaSamw * retransmit count has been exceeded 3848*da6c28aaSamw * IF no response was received THEN 3849*da6c28aaSamw * BEGIN 3850*da6c28aaSamw * 3851*da6c28aaSamw * (* node down *) 3852*da6c28aaSamw * 3853*da6c28aaSamw * update data base - remove entry; 3854*da6c28aaSamw * update data base - add new entry; 3855*da6c28aaSamw * send POSITIVE NAME REGISTRATION RESPONSE; 3856*da6c28aaSamw * return; 3857*da6c28aaSamw * END 3858*da6c28aaSamw * ELSE 3859*da6c28aaSamw * BEGIN (* challenged node replied *) 3860*da6c28aaSamw * (* 3861*da6c28aaSamw * * challenged node replied with 3862*da6c28aaSamw * * a response packet 3863*da6c28aaSamw * *) 3864*da6c28aaSamw * 3865*da6c28aaSamw * CASE packet type 3866*da6c28aaSamw * 3867*da6c28aaSamw * POSITIVE NAME QUERY RESPONSE: 3868*da6c28aaSamw * 3869*da6c28aaSamw * (* 3870*da6c28aaSamw * * name still owned by the 3871*da6c28aaSamw * * challenged node 3872*da6c28aaSamw * * 3873*da6c28aaSamw * * build packet and send response 3874*da6c28aaSamw * *) 3875*da6c28aaSamw * ... 3876*da6c28aaSamw * 3877*da6c28aaSamw * 3878*da6c28aaSamw * (* 3879*da6c28aaSamw * * Note: The NAME will need to 3880*da6c28aaSamw * * keep track (based on transaction id) of 3881*da6c28aaSamw * * the IP address and port number 3882*da6c28aaSamw * * of the original requestor. 3883*da6c28aaSamw * *) 3884*da6c28aaSamw * 3885*da6c28aaSamw * send NEGATIVE NAME REGISTRATION RESPONSE; 3886*da6c28aaSamw * return; 3887*da6c28aaSamw * NEGATIVE NAME QUERY RESPONSE: 3888*da6c28aaSamw * 3889*da6c28aaSamw * update data base - remove entry; 3890*da6c28aaSamw * update data base - add new entry; 3891*da6c28aaSamw * 3892*da6c28aaSamw * (* 3893*da6c28aaSamw * * build response packet and send 3894*da6c28aaSamw * * response 3895*da6c28aaSamw * *) 3896*da6c28aaSamw * send POSITIVE NAME REGISTRATION RESPONSE; 3897*da6c28aaSamw * return; 3898*da6c28aaSamw * END (* case *) 3899*da6c28aaSamw * END (* challenged node replied *) 3900*da6c28aaSamw * END (* unique name exists in data base *) 3901*da6c28aaSamw * ELSE 3902*da6c28aaSamw * IF group name exists in data base THEN 3903*da6c28aaSamw * BEGIN (* group names exists *) 3904*da6c28aaSamw * 3905*da6c28aaSamw * (* 3906*da6c28aaSamw * * Members of a group name are NOT 3907*da6c28aaSamw * * challenged. 3908*da6c28aaSamw * * Make the assumption that 3909*da6c28aaSamw * * at least some of the group members 3910*da6c28aaSamw * * are still alive. 3911*da6c28aaSamw * * Refresh mechanism will 3912*da6c28aaSamw * * allow the NAME to detect when all 3913*da6c28aaSamw * * members of a group no longer use that 3914*da6c28aaSamw * * name 3915*da6c28aaSamw * *) 3916*da6c28aaSamw * 3917*da6c28aaSamw * send NEGATIVE NAME REGISTRATION RESPONSE; 3918*da6c28aaSamw * END (* group name exists *) 3919*da6c28aaSamw * ELSE 3920*da6c28aaSamw * BEGIN (* name does not exist *) 3921*da6c28aaSamw * 3922*da6c28aaSamw * (* 3923*da6c28aaSamw * * Name does not exist in data base 3924*da6c28aaSamw * * 3925*da6c28aaSamw * * This code applies to both non-secure 3926*da6c28aaSamw * * and secure server. 3927*da6c28aaSamw * *) 3928*da6c28aaSamw * 3929*da6c28aaSamw * update data base - add new entry; 3930*da6c28aaSamw * send POSITIVE NAME REGISTRATION RESPONSE; 3931*da6c28aaSamw * return; 3932*da6c28aaSamw * END 3933*da6c28aaSamw * 3934*da6c28aaSamw * NAME QUERY REQUEST: 3935*da6c28aaSamw * IF name exists in data base THEN 3936*da6c28aaSamw * BEGIN 3937*da6c28aaSamw * (* 3938*da6c28aaSamw * * build response packet and send to 3939*da6c28aaSamw * * requestor 3940*da6c28aaSamw * *) 3941*da6c28aaSamw * ... 3942*da6c28aaSamw * 3943*da6c28aaSamw * send POSITIVE NAME QUERY RESPONSE; 3944*da6c28aaSamw * return; 3945*da6c28aaSamw * ELSE 3946*da6c28aaSamw * BEGIN 3947*da6c28aaSamw * (* 3948*da6c28aaSamw * * build response packet and send to 3949*da6c28aaSamw * * requestor 3950*da6c28aaSamw * *) 3951*da6c28aaSamw * ... 3952*da6c28aaSamw * 3953*da6c28aaSamw * send NEGATIVE NAME QUERY RESPONSE; 3954*da6c28aaSamw * return; 3955*da6c28aaSamw * END 3956*da6c28aaSamw * 3957*da6c28aaSamw * NAME REGISTRATION REQUEST (GROUP): 3958*da6c28aaSamw * IF name exists in data base THEN 3959*da6c28aaSamw * BEGIN 3960*da6c28aaSamw * IF local entry is a unique name THEN 3961*da6c28aaSamw * BEGIN (* local is unique *) 3962*da6c28aaSamw * 3963*da6c28aaSamw * IF non-secure THEN 3964*da6c28aaSamw * BEGIN 3965*da6c28aaSamw * send END-NODE CHALLENGE NAME 3966*da6c28aaSamw * REGISTRATION RESPONSE; 3967*da6c28aaSamw * return; 3968*da6c28aaSamw * END 3969*da6c28aaSamw * 3970*da6c28aaSamw * REPEAT 3971*da6c28aaSamw * send NAME QUERY REQUEST; 3972*da6c28aaSamw * pause(UCAST_REQ_RETRY_TIMEOUT); 3973*da6c28aaSamw * UNTIL response received or 3974*da6c28aaSamw * retransmit count exceeded 3975*da6c28aaSamw * IF no response received or 3976*da6c28aaSamw * NEGATIVE NAME QUERY RESPONSE 3977*da6c28aaSamw * received THEN 3978*da6c28aaSamw * BEGIN 3979*da6c28aaSamw * update data base - remove entry; 3980*da6c28aaSamw * update data base - add new entry; 3981*da6c28aaSamw * send POSITIVE NAME REGISTRATION RESPONSE; 3982*da6c28aaSamw * return; 3983*da6c28aaSamw * END 3984*da6c28aaSamw * ELSE 3985*da6c28aaSamw * BEGIN 3986*da6c28aaSamw * (* 3987*da6c28aaSamw * * name still being held 3988*da6c28aaSamw * * by challenged node 3989*da6c28aaSamw * *) 3990*da6c28aaSamw * 3991*da6c28aaSamw * send NEGATIVE NAME REGISTRATION RESPONSE; 3992*da6c28aaSamw * END 3993*da6c28aaSamw * END (* local is unique *) 3994*da6c28aaSamw * ELSE 3995*da6c28aaSamw * BEGIN (* local is group *) 3996*da6c28aaSamw * (* 3997*da6c28aaSamw * * existing entry is a group name 3998*da6c28aaSamw * *) 3999*da6c28aaSamw * 4000*da6c28aaSamw * update data base - remove entry; 4001*da6c28aaSamw * update data base - add new entry; 4002*da6c28aaSamw * send POSITIVE NAME REGISTRATION RESPONSE; 4003*da6c28aaSamw * return; 4004*da6c28aaSamw * END (* local is group *) 4005*da6c28aaSamw * END (* names exists *) 4006*da6c28aaSamw * ELSE 4007*da6c28aaSamw * BEGIN (* does not exist *) 4008*da6c28aaSamw * 4009*da6c28aaSamw * (* name does not exist in data base *) 4010*da6c28aaSamw * 4011*da6c28aaSamw * update data base - add new entry; 4012*da6c28aaSamw * send POSITIVE NAME REGISTRATION RESPONSE; 4013*da6c28aaSamw * return; 4014*da6c28aaSamw * END (* does not exist *) 4015*da6c28aaSamw * 4016*da6c28aaSamw * NAME RELEASE REQUEST: 4017*da6c28aaSamw * 4018*da6c28aaSamw * (* 4019*da6c28aaSamw * * secure server may choose to disallow 4020*da6c28aaSamw * * a node from deleting a name 4021*da6c28aaSamw * *) 4022*da6c28aaSamw * 4023*da6c28aaSamw * update data base - remove entry; 4024*da6c28aaSamw * send POSITIVE NAME RELEASE RESPONSE; 4025*da6c28aaSamw * return; 4026*da6c28aaSamw * 4027*da6c28aaSamw * NAME UPDATE REQUEST: 4028*da6c28aaSamw * 4029*da6c28aaSamw * (* 4030*da6c28aaSamw * * End-node completed a successful challenge, 4031*da6c28aaSamw * * no update database 4032*da6c28aaSamw * *) 4033*da6c28aaSamw * 4034*da6c28aaSamw * IF secure server THEN 4035*da6c28aaSamw * send NEGATIVE NAME REGISTRATION RESPONSE; 4036*da6c28aaSamw * ELSE 4037*da6c28aaSamw * BEGIN (* new entry *) 4038*da6c28aaSamw * IF entry already exists THEN 4039*da6c28aaSamw * update data base - remove entry; 4040*da6c28aaSamw * update data base - add new entry; 4041*da6c28aaSamw * send POSITIVE NAME REGISTRATION RESPONSE; 4042*da6c28aaSamw * start_timer(TTL); 4043*da6c28aaSamw * END 4044*da6c28aaSamw * 4045*da6c28aaSamw * NAME REFRESH REQUEST: 4046*da6c28aaSamw * check for consistency; 4047*da6c28aaSamw * 4048*da6c28aaSamw * IF node not allowed to have name THEN 4049*da6c28aaSamw * BEGIN 4050*da6c28aaSamw * 4051*da6c28aaSamw * (* 4052*da6c28aaSamw * * tell end node that it can't have name 4053*da6c28aaSamw * *) 4054*da6c28aaSamw * send NEGATIVE NAME REGISTRATION RESPONSE; 4055*da6c28aaSamw * END 4056*da6c28aaSamw * ELSE 4057*da6c28aaSamw * BEGIN 4058*da6c28aaSamw * 4059*da6c28aaSamw * (* 4060*da6c28aaSamw * * send confirmation response to the 4061*da6c28aaSamw * * end node. 4062*da6c28aaSamw * *) 4063*da6c28aaSamw * send POSITIVE NAME REGISTRATION; 4064*da6c28aaSamw * start_timer(TTL); 4065*da6c28aaSamw * END 4066*da6c28aaSamw * return; 4067*da6c28aaSamw * END (* case *) 4068*da6c28aaSamw * END (* procedure *) 4069*da6c28aaSamw */ 4070*da6c28aaSamw static void 4071*da6c28aaSamw smb_name_process_Pnode_packet(struct name_packet *packet, 4072*da6c28aaSamw struct addr_entry *addr) 4073*da6c28aaSamw { 4074*da6c28aaSamw struct name_entry *name; 4075*da6c28aaSamw struct name_entry *entry; 4076*da6c28aaSamw struct name_question *question; 4077*da6c28aaSamw struct resource_record *additional; 4078*da6c28aaSamw 4079*da6c28aaSamw question = packet->question; 4080*da6c28aaSamw additional = packet->additional; 4081*da6c28aaSamw 4082*da6c28aaSamw if (packet->info & NAME_NM_FLAGS_B) { 4083*da6c28aaSamw /* 4084*da6c28aaSamw * always ignore UDP broadcast packets 4085*da6c28aaSamw */ 4086*da6c28aaSamw return; 4087*da6c28aaSamw } 4088*da6c28aaSamw 4089*da6c28aaSamw switch (packet->info & NAME_OPCODE_OPCODE_MASK) { 4090*da6c28aaSamw case NAME_OPCODE_REFRESH: 4091*da6c28aaSamw /* Guard against malformed packets */ 4092*da6c28aaSamw if ((question == 0) || (additional == 0)) 4093*da6c28aaSamw break; 4094*da6c28aaSamw if (additional->name->addr_list.sin.sin_addr.s_addr == 0) 4095*da6c28aaSamw break; 4096*da6c28aaSamw 4097*da6c28aaSamw name = question->name; 4098*da6c28aaSamw name->addr_list.ttl = additional->ttl; 4099*da6c28aaSamw name->attributes = additional->name->attributes; 4100*da6c28aaSamw name->addr_list.sin = additional->name->addr_list.sin; 4101*da6c28aaSamw name->addr_list.forw = name->addr_list.back = &name->addr_list; 4102*da6c28aaSamw 4103*da6c28aaSamw if ((entry = smb_netbios_cache_lookup(name)) != 0) { 4104*da6c28aaSamw smb_netbios_cache_update_entry(entry, name); 4105*da6c28aaSamw smb_netbios_cache_unlock_entry(entry); 4106*da6c28aaSamw } 4107*da6c28aaSamw else 4108*da6c28aaSamw (void) smb_netbios_cache_insert(name); 4109*da6c28aaSamw 4110*da6c28aaSamw (void) smb_send_name_registration_response(addr, packet, 0); 4111*da6c28aaSamw break; 4112*da6c28aaSamw 4113*da6c28aaSamw case NAME_OPCODE_QUERY: 4114*da6c28aaSamw /* 4115*da6c28aaSamw * This opcode covers both NAME_QUERY_REQUEST and 4116*da6c28aaSamw * NODE_STATUS_REQUEST. They can be distinguished 4117*da6c28aaSamw * based on the type of question entry. 4118*da6c28aaSamw */ 4119*da6c28aaSamw 4120*da6c28aaSamw /* All query requests have to have question entry */ 4121*da6c28aaSamw if (question == 0) 4122*da6c28aaSamw break; 4123*da6c28aaSamw 4124*da6c28aaSamw if (question->question_type == NAME_QUESTION_TYPE_NB) { 4125*da6c28aaSamw name = question->name; 4126*da6c28aaSamw if ((entry = smb_netbios_cache_lookup(name)) != 0) { 4127*da6c28aaSamw /* 4128*da6c28aaSamw * send response to the IP address and port 4129*da6c28aaSamw * number from which the request was received. 4130*da6c28aaSamw */ 4131*da6c28aaSamw (void) smb_send_name_query_response(addr, 4132*da6c28aaSamw packet, entry, 0); 4133*da6c28aaSamw smb_netbios_cache_unlock_entry(entry); 4134*da6c28aaSamw } else { 4135*da6c28aaSamw /* 4136*da6c28aaSamw * send response to the requestor 4137*da6c28aaSamw */ 4138*da6c28aaSamw (void) smb_send_name_query_response(addr, 4139*da6c28aaSamw packet, name, RCODE_NAM_ERR); 4140*da6c28aaSamw } 4141*da6c28aaSamw } 4142*da6c28aaSamw else 4143*da6c28aaSamw if (question->question_type == NAME_QUESTION_TYPE_NBSTAT) { 4144*da6c28aaSamw /* 4145*da6c28aaSamw * Name of "*" may be used to force node to 4146*da6c28aaSamw * divulge status for administrative purposes 4147*da6c28aaSamw */ 4148*da6c28aaSamw name = question->name; 4149*da6c28aaSamw entry = 0; 4150*da6c28aaSamw if (NETBIOS_NAME_IS_STAR(name->name) || 4151*da6c28aaSamw ((entry = smb_netbios_cache_lookup(name)) != 0)) { 4152*da6c28aaSamw /* 4153*da6c28aaSamw * send only those names that are 4154*da6c28aaSamw * in the same scope as the scope 4155*da6c28aaSamw * field in the request packet 4156*da6c28aaSamw */ 4157*da6c28aaSamw if (entry) 4158*da6c28aaSamw smb_netbios_cache_unlock_entry(entry); 4159*da6c28aaSamw (void) smb_send_node_status_response(addr, 4160*da6c28aaSamw packet); 4161*da6c28aaSamw } 4162*da6c28aaSamw } 4163*da6c28aaSamw break; 4164*da6c28aaSamw 4165*da6c28aaSamw default: 4166*da6c28aaSamw break; 4167*da6c28aaSamw } 4168*da6c28aaSamw } 4169*da6c28aaSamw 4170*da6c28aaSamw /* 4171*da6c28aaSamw * 5.1.3.5. M-NODE INCOMING PACKET PROCESSING 4172*da6c28aaSamw * 4173*da6c28aaSamw * Processing initiated by reception of packets at a M node 4174*da6c28aaSamw * 4175*da6c28aaSamw * PROCEDURE process_incoming_packet(packet) 4176*da6c28aaSamw * 4177*da6c28aaSamw * (* 4178*da6c28aaSamw * * Processing initiated by incoming packets at a M node 4179*da6c28aaSamw * *) 4180*da6c28aaSamw * 4181*da6c28aaSamw * BEGIN 4182*da6c28aaSamw * CASE packet type of 4183*da6c28aaSamw * 4184*da6c28aaSamw * NAME CONFLICT DEMAND: 4185*da6c28aaSamw * IF name exists in local name table THEN 4186*da6c28aaSamw * mark name as in conflict; 4187*da6c28aaSamw * return; 4188*da6c28aaSamw * 4189*da6c28aaSamw * NAME QUERY REQUEST: 4190*da6c28aaSamw * IF name exists in local name table THEN 4191*da6c28aaSamw * BEGIN (* name exists *) 4192*da6c28aaSamw * 4193*da6c28aaSamw * (* 4194*da6c28aaSamw * * build packet 4195*da6c28aaSamw * *) 4196*da6c28aaSamw * ... 4197*da6c28aaSamw * 4198*da6c28aaSamw * (* 4199*da6c28aaSamw * * send response to the IP address and port 4200*da6c28aaSamw * * number from which the request was received. 4201*da6c28aaSamw * *) 4202*da6c28aaSamw * 4203*da6c28aaSamw * send POSITIVE NAME QUERY RESPONSE ; 4204*da6c28aaSamw * return; 4205*da6c28aaSamw * END (* exists *) 4206*da6c28aaSamw * ELSE 4207*da6c28aaSamw * BEGIN (* does not exist *) 4208*da6c28aaSamw * 4209*da6c28aaSamw * (* 4210*da6c28aaSamw * * send response to the requestor 4211*da6c28aaSamw * *) 4212*da6c28aaSamw * 4213*da6c28aaSamw * IF request NOT broadcast THEN 4214*da6c28aaSamw * (* 4215*da6c28aaSamw * * Don't send negative responses to 4216*da6c28aaSamw * * queries sent by B nodes 4217*da6c28aaSamw * *) 4218*da6c28aaSamw * send NEGATIVE NAME QUERY RESPONSE ; 4219*da6c28aaSamw * return; 4220*da6c28aaSamw * END (* does not exist *) 4221*da6c28aaSamw * NODE STATUS REQUEST: 4222*da6c28aaSamw * BEGIN 4223*da6c28aaSamw * (* 4224*da6c28aaSamw * * Name of "*" may be used to force node to 4225*da6c28aaSamw * * divulge status for administrative purposes 4226*da6c28aaSamw * *) 4227*da6c28aaSamw * IF name in local name table OR name = "*" THEN 4228*da6c28aaSamw * (* 4229*da6c28aaSamw * * Build response packet and 4230*da6c28aaSamw * * send to requestor node 4231*da6c28aaSamw * * Send only those names that are 4232*da6c28aaSamw * * in the same scope as the scope 4233*da6c28aaSamw * * in the request packet. 4234*da6c28aaSamw * *) 4235*da6c28aaSamw * 4236*da6c28aaSamw * send NODE STATUS RESPONSE; 4237*da6c28aaSamw * END 4238*da6c28aaSamw * 4239*da6c28aaSamw * NAME RELEASE REQUEST: 4240*da6c28aaSamw * (* 4241*da6c28aaSamw * * This will be received if the NAME wants to flush the 4242*da6c28aaSamw * * name from the local name table, or from the local 4243*da6c28aaSamw * * cache. 4244*da6c28aaSamw * *) 4245*da6c28aaSamw * 4246*da6c28aaSamw * IF name exists in the local name table THEN 4247*da6c28aaSamw * BEGIN 4248*da6c28aaSamw * delete name from local name table; 4249*da6c28aaSamw * inform user that name has been deleted; 4250*da6c28aaSamw * END 4251*da6c28aaSamw * NAME REGISTRATION REQUEST (UNIQUE): 4252*da6c28aaSamw * IF name exists in local name table THEN 4253*da6c28aaSamw * send NEGATIVE NAME REGISTRATION RESPONSE ; 4254*da6c28aaSamw * NAME REGISTRATION REQUEST (GROUP): 4255*da6c28aaSamw * IF name exists in local name table THEN 4256*da6c28aaSamw * BEGIN 4257*da6c28aaSamw * IF local entry is a unique name THEN 4258*da6c28aaSamw * send NEGATIVE NAME REGISTRATION RESPONSE ; 4259*da6c28aaSamw * END 4260*da6c28aaSamw * END (* case *) 4261*da6c28aaSamw * END (* procedure *) 4262*da6c28aaSamw */ 4263*da6c28aaSamw static void 4264*da6c28aaSamw smb_name_process_Mnode_packet(struct name_packet *packet, 4265*da6c28aaSamw struct addr_entry *addr) 4266*da6c28aaSamw { 4267*da6c28aaSamw if (packet->info & NAME_NM_FLAGS_B) 4268*da6c28aaSamw smb_name_process_Bnode_packet(packet, addr); 4269*da6c28aaSamw else 4270*da6c28aaSamw smb_name_process_Pnode_packet(packet, addr); 4271*da6c28aaSamw } 4272*da6c28aaSamw 4273*da6c28aaSamw static void 4274*da6c28aaSamw smb_name_process_Hnode_packet(struct name_packet *packet, 4275*da6c28aaSamw struct addr_entry *addr) 4276*da6c28aaSamw { 4277*da6c28aaSamw if (packet->info & NAME_NM_FLAGS_B) 4278*da6c28aaSamw smb_name_process_Bnode_packet(packet, addr); 4279*da6c28aaSamw else 4280*da6c28aaSamw smb_name_process_Pnode_packet(packet, addr); 4281*da6c28aaSamw } 4282*da6c28aaSamw 4283*da6c28aaSamw 4284*da6c28aaSamw /* 4285*da6c28aaSamw * smb_netbios_name_tick 4286*da6c28aaSamw * 4287*da6c28aaSamw * Called once a second to handle name server timeouts. 4288*da6c28aaSamw */ 4289*da6c28aaSamw void 4290*da6c28aaSamw smb_netbios_name_tick(void) 4291*da6c28aaSamw { 4292*da6c28aaSamw struct name_entry *name; 4293*da6c28aaSamw struct name_entry *entry; 4294*da6c28aaSamw 4295*da6c28aaSamw (void) mutex_lock(&refresh_queue.mtx); 4296*da6c28aaSamw smb_netbios_cache_refresh(&refresh_queue); 4297*da6c28aaSamw 4298*da6c28aaSamw while ((name = refresh_queue.head.forw) != &refresh_queue.head) { 4299*da6c28aaSamw QUEUE_CLIP(name); 4300*da6c28aaSamw if (IS_LOCAL(name->attributes)) { 4301*da6c28aaSamw if (IS_UNIQUE(name->attributes)) { 4302*da6c28aaSamw (void) smb_name_Pnode_refresh_name(name); 4303*da6c28aaSamw } 4304*da6c28aaSamw } else { 4305*da6c28aaSamw entry = smb_name_find_name(name); 4306*da6c28aaSamw smb_name_unlock_name(entry); 4307*da6c28aaSamw } 4308*da6c28aaSamw free(name); 4309*da6c28aaSamw } 4310*da6c28aaSamw (void) mutex_unlock(&refresh_queue.mtx); 4311*da6c28aaSamw 4312*da6c28aaSamw smb_netbios_cache_reset_ttl(); 4313*da6c28aaSamw } 4314*da6c28aaSamw 4315*da6c28aaSamw 4316*da6c28aaSamw /* 4317*da6c28aaSamw * smb_name_find_name 4318*da6c28aaSamw * 4319*da6c28aaSamw * Lookup name cache for the given name. 4320*da6c28aaSamw * If it's not in the cache it'll send a 4321*da6c28aaSamw * name query request and then lookup the 4322*da6c28aaSamw * cache again. Note that if a name is 4323*da6c28aaSamw * returned it's locked and called MUST 4324*da6c28aaSamw * unlock it by calling smb_name_unlock_name() 4325*da6c28aaSamw */ 4326*da6c28aaSamw struct name_entry * 4327*da6c28aaSamw smb_name_find_name(struct name_entry *name) 4328*da6c28aaSamw { 4329*da6c28aaSamw struct name_entry *result; 4330*da6c28aaSamw 4331*da6c28aaSamw if ((result = smb_netbios_cache_lookup(name)) == 0) { 4332*da6c28aaSamw switch (smb_node_type) { 4333*da6c28aaSamw case 'B': 4334*da6c28aaSamw (void) smb_name_Bnode_find_name(name); 4335*da6c28aaSamw break; 4336*da6c28aaSamw case 'P': 4337*da6c28aaSamw (void) smb_name_Pnode_find_name(name); 4338*da6c28aaSamw break; 4339*da6c28aaSamw case 'M': 4340*da6c28aaSamw (void) smb_name_Mnode_find_name(name); 4341*da6c28aaSamw break; 4342*da6c28aaSamw case 'H': 4343*da6c28aaSamw default: 4344*da6c28aaSamw (void) smb_name_Hnode_find_name(name); 4345*da6c28aaSamw break; 4346*da6c28aaSamw } 4347*da6c28aaSamw return (smb_netbios_cache_lookup(name)); 4348*da6c28aaSamw } 4349*da6c28aaSamw 4350*da6c28aaSamw return (result); 4351*da6c28aaSamw } 4352*da6c28aaSamw 4353*da6c28aaSamw void 4354*da6c28aaSamw smb_name_unlock_name(struct name_entry *name) 4355*da6c28aaSamw { 4356*da6c28aaSamw smb_netbios_cache_unlock_entry(name); 4357*da6c28aaSamw } 4358*da6c28aaSamw 4359*da6c28aaSamw int 4360*da6c28aaSamw smb_name_add_name(struct name_entry *name) 4361*da6c28aaSamw { 4362*da6c28aaSamw int rc = 1; 4363*da6c28aaSamw 4364*da6c28aaSamw smb_netbios_name_dump(name); 4365*da6c28aaSamw 4366*da6c28aaSamw switch (smb_node_type) { 4367*da6c28aaSamw case 'B': 4368*da6c28aaSamw rc = smb_name_Bnode_add_name(name); 4369*da6c28aaSamw break; 4370*da6c28aaSamw case 'P': 4371*da6c28aaSamw rc = smb_name_Pnode_add_name(name); 4372*da6c28aaSamw break; 4373*da6c28aaSamw case 'M': 4374*da6c28aaSamw rc = smb_name_Mnode_add_name(name); 4375*da6c28aaSamw break; 4376*da6c28aaSamw case 'H': 4377*da6c28aaSamw default: 4378*da6c28aaSamw rc = smb_name_Hnode_add_name(name); 4379*da6c28aaSamw break; 4380*da6c28aaSamw } 4381*da6c28aaSamw 4382*da6c28aaSamw if (rc >= 0) 4383*da6c28aaSamw (void) smb_netbios_cache_insert(name); 4384*da6c28aaSamw 4385*da6c28aaSamw return (rc); 4386*da6c28aaSamw } 4387*da6c28aaSamw 4388*da6c28aaSamw int 4389*da6c28aaSamw smb_name_delete_name(struct name_entry *name) 4390*da6c28aaSamw { 4391*da6c28aaSamw int rc; 4392*da6c28aaSamw unsigned char type; 4393*da6c28aaSamw 4394*da6c28aaSamw type = name->name[15]; 4395*da6c28aaSamw if ((type != 0x00) && (type != 0x20)) { 4396*da6c28aaSamw syslog(LOG_ERR, 4397*da6c28aaSamw "netbios: error trying to delete non-local name"); 4398*da6c28aaSamw smb_netbios_name_logf(name); 4399*da6c28aaSamw name->attributes &= ~NAME_ATTR_LOCAL; 4400*da6c28aaSamw return (-1); 4401*da6c28aaSamw } 4402*da6c28aaSamw 4403*da6c28aaSamw smb_netbios_cache_delete(name); 4404*da6c28aaSamw 4405*da6c28aaSamw switch (smb_node_type) { 4406*da6c28aaSamw case 'B': 4407*da6c28aaSamw rc = smb_name_Bnode_delete_name(name); 4408*da6c28aaSamw break; 4409*da6c28aaSamw case 'P': 4410*da6c28aaSamw rc = smb_name_Pnode_delete_name(name); 4411*da6c28aaSamw break; 4412*da6c28aaSamw case 'M': 4413*da6c28aaSamw rc = smb_name_Mnode_delete_name(name); 4414*da6c28aaSamw break; 4415*da6c28aaSamw case 'H': 4416*da6c28aaSamw default: 4417*da6c28aaSamw rc = smb_name_Hnode_delete_name(name); 4418*da6c28aaSamw break; 4419*da6c28aaSamw } 4420*da6c28aaSamw 4421*da6c28aaSamw if (rc > 0) 4422*da6c28aaSamw return (0); 4423*da6c28aaSamw 4424*da6c28aaSamw return (-1); 4425*da6c28aaSamw } 4426*da6c28aaSamw 4427*da6c28aaSamw typedef struct { 4428*da6c28aaSamw struct addr_entry *addr; 4429*da6c28aaSamw char *buf; 4430*da6c28aaSamw int length; 4431*da6c28aaSamw } worker_param_t; 4432*da6c28aaSamw 4433*da6c28aaSamw /* 4434*da6c28aaSamw * smb_netbios_worker 4435*da6c28aaSamw * 4436*da6c28aaSamw * Process incoming request/response packets for Netbios 4437*da6c28aaSamw * name service (on port 138). 4438*da6c28aaSamw */ 4439*da6c28aaSamw void * 4440*da6c28aaSamw smb_netbios_worker(void *arg) 4441*da6c28aaSamw { 4442*da6c28aaSamw worker_param_t *p = (worker_param_t *)arg; 4443*da6c28aaSamw struct addr_entry *addr = p->addr; 4444*da6c28aaSamw struct name_packet *packet; 4445*da6c28aaSamw 4446*da6c28aaSamw if ((packet = smb_name_buf_to_packet(p->buf, p->length)) != 0) { 4447*da6c28aaSamw if (packet->info & NAME_OPCODE_R) { 4448*da6c28aaSamw /* Reply packet */ 4449*da6c28aaSamw smb_reply_ready(packet, addr); 4450*da6c28aaSamw free(p->buf); 4451*da6c28aaSamw free(p); 4452*da6c28aaSamw return (0); 4453*da6c28aaSamw } 4454*da6c28aaSamw 4455*da6c28aaSamw /* Request packet */ 4456*da6c28aaSamw switch (smb_node_type) { 4457*da6c28aaSamw case 'B': 4458*da6c28aaSamw smb_name_process_Bnode_packet(packet, addr); 4459*da6c28aaSamw break; 4460*da6c28aaSamw case 'P': 4461*da6c28aaSamw smb_name_process_Pnode_packet(packet, addr); 4462*da6c28aaSamw break; 4463*da6c28aaSamw case 'M': 4464*da6c28aaSamw smb_name_process_Mnode_packet(packet, addr); 4465*da6c28aaSamw break; 4466*da6c28aaSamw case 'H': 4467*da6c28aaSamw default: 4468*da6c28aaSamw smb_name_process_Hnode_packet(packet, addr); 4469*da6c28aaSamw break; 4470*da6c28aaSamw } 4471*da6c28aaSamw 4472*da6c28aaSamw if (packet->answer) 4473*da6c28aaSamw smb_netbios_name_freeaddrs(packet->answer->name); 4474*da6c28aaSamw free(packet); 4475*da6c28aaSamw } 4476*da6c28aaSamw else 4477*da6c28aaSamw { 4478*da6c28aaSamw syslog(LOG_DEBUG, "SmbNBNS: error decoding received packet"); 4479*da6c28aaSamw } 4480*da6c28aaSamw 4481*da6c28aaSamw free(addr); 4482*da6c28aaSamw free(p->buf); 4483*da6c28aaSamw free(p); 4484*da6c28aaSamw return (0); 4485*da6c28aaSamw } 4486*da6c28aaSamw 4487*da6c28aaSamw static void 4488*da6c28aaSamw smb_netbios_wins_config(char *ip) 4489*da6c28aaSamw { 4490*da6c28aaSamw uint32_t ipaddr; 4491*da6c28aaSamw 4492*da6c28aaSamw ipaddr = inet_addr(ip); 4493*da6c28aaSamw if (ipaddr != INADDR_NONE) { 4494*da6c28aaSamw smb_nbns[nbns_num].flags = ADDR_FLAG_VALID; 4495*da6c28aaSamw smb_nbns[nbns_num].sinlen = sizeof (struct sockaddr_in); 4496*da6c28aaSamw smb_nbns[nbns_num].sin.sin_family = AF_INET; 4497*da6c28aaSamw smb_nbns[nbns_num].sin.sin_addr.s_addr = ipaddr; 4498*da6c28aaSamw smb_nbns[nbns_num++].sin.sin_port = 4499*da6c28aaSamw htons(NAME_SERVICE_UDP_PORT); 4500*da6c28aaSamw smb_node_type = 'H'; 4501*da6c28aaSamw } 4502*da6c28aaSamw } 4503*da6c28aaSamw 4504*da6c28aaSamw void 4505*da6c28aaSamw smb_netbios_name_config(void) 4506*da6c28aaSamw { 4507*da6c28aaSamw uint32_t ipaddr; 4508*da6c28aaSamw struct name_entry name; 4509*da6c28aaSamw char myname[MAXHOSTNAMELEN]; 4510*da6c28aaSamw int i; 4511*da6c28aaSamw int smb_nc_cnt; 4512*da6c28aaSamw net_cfg_t cfg; 4513*da6c28aaSamw 4514*da6c28aaSamw if (smb_getnetbiosname(myname, MAXHOSTNAMELEN) != 0) 4515*da6c28aaSamw return; 4516*da6c28aaSamw 4517*da6c28aaSamw /* Start with no broadcast addresses */ 4518*da6c28aaSamw bcast_num = 0; 4519*da6c28aaSamw bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS); 4520*da6c28aaSamw 4521*da6c28aaSamw smb_nc_cnt = smb_nic_get_num(); 4522*da6c28aaSamw /* Add all of my broadcast addresses */ 4523*da6c28aaSamw for (i = 0; i < smb_nc_cnt; i++) { 4524*da6c28aaSamw if (smb_nic_get_byind(i, &cfg) == NULL) { 4525*da6c28aaSamw break; 4526*da6c28aaSamw } 4527*da6c28aaSamw smb_bcast_list[bcast_num].flags = ADDR_FLAG_VALID; 4528*da6c28aaSamw smb_bcast_list[bcast_num].attributes = NAME_ATTR_LOCAL; 4529*da6c28aaSamw smb_bcast_list[bcast_num].sinlen = sizeof (struct sockaddr_in); 4530*da6c28aaSamw smb_bcast_list[bcast_num].sin.sin_family = AF_INET; 4531*da6c28aaSamw smb_bcast_list[bcast_num].sin.sin_port = 4532*da6c28aaSamw htons(NAME_SERVICE_UDP_PORT); 4533*da6c28aaSamw smb_bcast_list[bcast_num++].sin.sin_addr.s_addr = 4534*da6c28aaSamw cfg.broadcast; 4535*da6c28aaSamw } 4536*da6c28aaSamw 4537*da6c28aaSamw /* Start with no WINS */ 4538*da6c28aaSamw smb_node_type = 'B'; 4539*da6c28aaSamw nbns_num = 0; 4540*da6c28aaSamw bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS); 4541*da6c28aaSamw 4542*da6c28aaSamw /* add any configured WINS */ 4543*da6c28aaSamw smb_config_rdlock(); 4544*da6c28aaSamw smb_netbios_wins_config(smb_config_getstr(SMB_CI_WINS_SRV1)); 4545*da6c28aaSamw smb_netbios_wins_config(smb_config_getstr(SMB_CI_WINS_SRV2)); 4546*da6c28aaSamw smb_config_unlock(); 4547*da6c28aaSamw 4548*da6c28aaSamw for (i = 0; i < smb_nc_cnt; i++) { 4549*da6c28aaSamw if (smb_nic_get_byind(i, &cfg) == NULL) { 4550*da6c28aaSamw break; 4551*da6c28aaSamw } 4552*da6c28aaSamw if (cfg.exclude) 4553*da6c28aaSamw continue; 4554*da6c28aaSamw 4555*da6c28aaSamw ipaddr = cfg.ip; 4556*da6c28aaSamw smb_init_name_struct((unsigned char *)myname, 0x00, 0, ipaddr, 4557*da6c28aaSamw htons(DGM_SRVC_UDP_PORT), NAME_ATTR_UNIQUE, 4558*da6c28aaSamw NAME_ATTR_LOCAL, &name); 4559*da6c28aaSamw (void) smb_name_add_name(&name); 4560*da6c28aaSamw 4561*da6c28aaSamw smb_init_name_struct((unsigned char *)myname, 0x20, 0, 4562*da6c28aaSamw ipaddr, htons(DGM_SRVC_UDP_PORT), 4563*da6c28aaSamw NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name); 4564*da6c28aaSamw (void) smb_name_add_name(&name); 4565*da6c28aaSamw } 4566*da6c28aaSamw } 4567*da6c28aaSamw 4568*da6c28aaSamw void 4569*da6c28aaSamw smb_netbios_name_unconfig(void) 4570*da6c28aaSamw { 4571*da6c28aaSamw struct name_entry *name; 4572*da6c28aaSamw 4573*da6c28aaSamw (void) mutex_lock(&delete_queue.mtx); 4574*da6c28aaSamw smb_netbios_cache_delete_locals(&delete_queue); 4575*da6c28aaSamw 4576*da6c28aaSamw while ((name = delete_queue.head.forw) != &delete_queue.head) { 4577*da6c28aaSamw QUEUE_CLIP(name); 4578*da6c28aaSamw (void) smb_name_delete_name(name); 4579*da6c28aaSamw free(name); 4580*da6c28aaSamw } 4581*da6c28aaSamw (void) mutex_unlock(&delete_queue.mtx); 4582*da6c28aaSamw } 4583*da6c28aaSamw 4584*da6c28aaSamw void 4585*da6c28aaSamw smb_netbios_name_reconfig(void) 4586*da6c28aaSamw { 4587*da6c28aaSamw smb_netbios_name_unconfig(); 4588*da6c28aaSamw smb_netbios_name_config(); 4589*da6c28aaSamw } 4590*da6c28aaSamw 4591*da6c28aaSamw /* 4592*da6c28aaSamw * process_incoming Function: void smb_netbios_name_service_daemon(void) 4593*da6c28aaSamw * 4594*da6c28aaSamw * Description: 4595*da6c28aaSamw * 4596*da6c28aaSamw * Put test description here. 4597*da6c28aaSamw * 4598*da6c28aaSamw * Inputs: 4599*da6c28aaSamw * Nothing 4600*da6c28aaSamw * 4601*da6c28aaSamw * Returns: 4602*da6c28aaSamw * int -> Description 4603*da6c28aaSamw */ 4604*da6c28aaSamw /*ARGSUSED*/ 4605*da6c28aaSamw void * 4606*da6c28aaSamw smb_netbios_name_service_daemon(void *arg) 4607*da6c28aaSamw { 4608*da6c28aaSamw struct sockaddr_in sin; 4609*da6c28aaSamw struct addr_entry *addr; 4610*da6c28aaSamw int len; 4611*da6c28aaSamw int flag = 1; 4612*da6c28aaSamw char *buf; 4613*da6c28aaSamw worker_param_t *worker_param; 4614*da6c28aaSamw net_cfg_t cfg; 4615*da6c28aaSamw 4616*da6c28aaSamw /* 4617*da6c28aaSamw * Initialize reply_queue 4618*da6c28aaSamw */ 4619*da6c28aaSamw bzero(&reply_queue, sizeof (reply_queue)); 4620*da6c28aaSamw reply_queue.forw = reply_queue.back = &reply_queue; 4621*da6c28aaSamw 4622*da6c28aaSamw if (!smb_netbios_cache_init()) 4623*da6c28aaSamw return (0); 4624*da6c28aaSamw 4625*da6c28aaSamw bcast_num = 0; 4626*da6c28aaSamw bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS); 4627*da6c28aaSamw 4628*da6c28aaSamw if ((name_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 4629*da6c28aaSamw syslog(LOG_ERR, 4630*da6c28aaSamw "smbd: Could not create AF_INET, SOCK_DGRAM, socket"); 4631*da6c28aaSamw smb_netbios_cache_fini(); 4632*da6c28aaSamw smb_netbios_chg_status(NETBIOS_NAME_SVC_FAILED, 1); 4633*da6c28aaSamw return (0); 4634*da6c28aaSamw } 4635*da6c28aaSamw 4636*da6c28aaSamw (void) setsockopt(name_sock, SOL_SOCKET, SO_BROADCAST, &flag, 4637*da6c28aaSamw sizeof (flag)); 4638*da6c28aaSamw 4639*da6c28aaSamw bzero(&sin, sizeof (struct sockaddr_in)); 4640*da6c28aaSamw sin.sin_family = AF_INET; 4641*da6c28aaSamw sin.sin_port = htons(NAME_SERVICE_UDP_PORT); 4642*da6c28aaSamw if (bind(name_sock, (struct sockaddr *)&sin, sizeof (sin)) != 0) { 4643*da6c28aaSamw syslog(LOG_ERR, 4644*da6c28aaSamw "smbd: Bind to name service port %d failed (%d)", 4645*da6c28aaSamw NAME_SERVICE_UDP_PORT, errno); 4646*da6c28aaSamw smb_netbios_cache_fini(); 4647*da6c28aaSamw (void) close(name_sock); 4648*da6c28aaSamw smb_netbios_chg_status(NETBIOS_NAME_SVC_FAILED, 1); 4649*da6c28aaSamw return (0); 4650*da6c28aaSamw } 4651*da6c28aaSamw 4652*da6c28aaSamw smb_netbios_chg_status(NETBIOS_NAME_SVC_RUNNING, 1); 4653*da6c28aaSamw 4654*da6c28aaSamw while (((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) || 4655*da6c28aaSamw (nb_status.state & NETBIOS_BROWSER_RUNNING)) { 4656*da6c28aaSamw if ((buf = malloc(MAX_DATAGRAM_LENGTH)) == 0) { 4657*da6c28aaSamw /* Sleep for 10 sec and try again */ 4658*da6c28aaSamw (void) sleep(10); 4659*da6c28aaSamw continue; 4660*da6c28aaSamw } 4661*da6c28aaSamw if ((addr = (struct addr_entry *) 4662*da6c28aaSamw malloc(sizeof (struct addr_entry))) == 0) { 4663*da6c28aaSamw /* Sleep for 10 sec and try again */ 4664*da6c28aaSamw free(buf); 4665*da6c28aaSamw (void) sleep(10); 4666*da6c28aaSamw continue; 4667*da6c28aaSamw } 4668*da6c28aaSamw ignore: bzero(addr, sizeof (struct addr_entry)); 4669*da6c28aaSamw addr->sinlen = sizeof (addr->sin); 4670*da6c28aaSamw addr->forw = addr->back = addr; 4671*da6c28aaSamw 4672*da6c28aaSamw if ((len = recvfrom(name_sock, buf, MAX_DATAGRAM_LENGTH, 4673*da6c28aaSamw 0, (struct sockaddr *)&addr->sin, &addr->sinlen)) < 0) { 4674*da6c28aaSamw if (errno == ENOMEM || errno == ENFILE || 4675*da6c28aaSamw errno == EMFILE) { 4676*da6c28aaSamw /* Sleep for 10 sec and try again */ 4677*da6c28aaSamw free(buf); 4678*da6c28aaSamw free(addr); 4679*da6c28aaSamw (void) sleep(10); 4680*da6c28aaSamw continue; 4681*da6c28aaSamw } 4682*da6c28aaSamw syslog(LOG_ERR, 4683*da6c28aaSamw "smbd: NETBIOS name service - recvfrom failed"); 4684*da6c28aaSamw free(buf); 4685*da6c28aaSamw free(addr); 4686*da6c28aaSamw smb_netbios_chg_status(NETBIOS_NAME_SVC_FAILED, 1); 4687*da6c28aaSamw goto shutdown; 4688*da6c28aaSamw } 4689*da6c28aaSamw 4690*da6c28aaSamw /* Ignore any incoming packets from myself... */ 4691*da6c28aaSamw if (smb_nic_get_byip(addr->sin.sin_addr.s_addr, 4692*da6c28aaSamw &cfg) != NULL) { 4693*da6c28aaSamw goto ignore; 4694*da6c28aaSamw } 4695*da6c28aaSamw 4696*da6c28aaSamw /* 4697*da6c28aaSamw * Launch a netbios worker to process the received packet. 4698*da6c28aaSamw */ 4699*da6c28aaSamw worker_param = (worker_param_t *) 4700*da6c28aaSamw malloc(sizeof (worker_param_t)); 4701*da6c28aaSamw if (worker_param) { 4702*da6c28aaSamw pthread_t worker; 4703*da6c28aaSamw pthread_attr_t tattr; 4704*da6c28aaSamw 4705*da6c28aaSamw worker_param->addr = addr; 4706*da6c28aaSamw worker_param->buf = buf; 4707*da6c28aaSamw worker_param->length = len; 4708*da6c28aaSamw 4709*da6c28aaSamw (void) pthread_attr_init(&tattr); 4710*da6c28aaSamw (void) pthread_attr_setdetachstate(&tattr, 4711*da6c28aaSamw PTHREAD_CREATE_DETACHED); 4712*da6c28aaSamw (void) pthread_create(&worker, &tattr, 4713*da6c28aaSamw smb_netbios_worker, worker_param); 4714*da6c28aaSamw (void) pthread_attr_destroy(&tattr); 4715*da6c28aaSamw } 4716*da6c28aaSamw } 4717*da6c28aaSamw 4718*da6c28aaSamw shutdown: 4719*da6c28aaSamw smb_netbios_chg_status(NETBIOS_NAME_SVC_RUNNING, 0); 4720*da6c28aaSamw 4721*da6c28aaSamw (void) mutex_lock(&nb_status.mtx); 4722*da6c28aaSamw while (nb_status.state & NETBIOS_BROWSER_RUNNING) 4723*da6c28aaSamw (void) cond_wait(&nb_status.cv, &nb_status.mtx); 4724*da6c28aaSamw (void) mutex_unlock(&nb_status.mtx); 4725*da6c28aaSamw 4726*da6c28aaSamw if ((nb_status.state & NETBIOS_NAME_SVC_FAILED) == 0) { 4727*da6c28aaSamw /* this might delay shutdown, do we want to do this? */ 4728*da6c28aaSamw /* 4729*da6c28aaSamw * it'll send name release requests but nobody's waiting 4730*da6c28aaSamw * for response and it'll eventually timeout. 4731*da6c28aaSamw */ 4732*da6c28aaSamw smb_netbios_name_unconfig(); 4733*da6c28aaSamw } 4734*da6c28aaSamw (void) close(name_sock); 4735*da6c28aaSamw smb_netbios_cache_fini(); 4736*da6c28aaSamw syslog(LOG_DEBUG, "smbd: Netbios Name Service is down\n"); 4737*da6c28aaSamw return (0); 4738*da6c28aaSamw } 4739