xref: /illumos-gate/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
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