2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1997
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern int DEBUGLEVEL
;
29 /****************************************************************************
30 interpret a node status response
31 ****************************************************************************/
32 static void _interpret_node_status(char *p
, char *master
,char *rname
)
34 int numnames
= CVAL(p
,0);
35 DEBUG(1,("received %d names\n",numnames
));
37 if (rname
) *rname
= 0;
38 if (master
) *master
= 0;
52 strcat(flags
, (p
[0] & 0x80) ? "<GROUP> " : " ");
53 if ((p
[0] & 0x60) == 0x00) strcat(flags
,"B ");
54 if ((p
[0] & 0x60) == 0x20) strcat(flags
,"P ");
55 if ((p
[0] & 0x60) == 0x40) strcat(flags
,"M ");
56 if ((p
[0] & 0x60) == 0x60) strcat(flags
,"H ");
57 if (p
[0] & 0x10) strcat(flags
,"<DEREGISTERING> ");
58 if (p
[0] & 0x08) strcat(flags
,"<CONFLICT> ");
59 if (p
[0] & 0x04) strcat(flags
,"<ACTIVE> ");
60 if (p
[0] & 0x02) strcat(flags
,"<PERMANENT> ");
62 if (master
&& !*master
&& type
== 0x1d) {
63 StrnCpy(master
,qname
,15);
64 trim_string(master
,NULL
," ");
67 if (rname
&& !*rname
&& type
== 0x20 && !(p
[0]&0x80)) {
68 StrnCpy(rname
,qname
,15);
69 trim_string(rname
,NULL
," ");
72 for (i
= strlen( qname
) ; --i
>= 0 ; ) {
73 if (!isprint(qname
[i
])) qname
[i
] = '.';
75 DEBUG(1,("\t%-15s <%02x> - %s\n",qname
,type
,flags
));
78 DEBUG(1,("num_good_sends=%d num_good_receives=%d\n",
79 IVAL(p
,20),IVAL(p
,24)));
83 /****************************************************************************
84 do a netbios name status query on a host
86 the "master" parameter is a hack used for finding workgroups.
87 **************************************************************************/
88 BOOL
name_status(int fd
,char *name
,int name_type
,BOOL recurse
,
89 struct in_addr to_ip
,char *master
,char *rname
,
94 int retry_time
= 5000;
96 struct packet_struct p
;
97 struct packet_struct
*p2
;
98 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
99 static int name_trn_id
= 0;
101 bzero((char *)&p
,sizeof(p
));
103 if (!name_trn_id
) name_trn_id
= (time(NULL
)%(unsigned)0x7FFF) +
104 (getpid()%(unsigned)100);
105 name_trn_id
= (name_trn_id
+1) % (unsigned)0x7FFF;
107 nmb
->header
.name_trn_id
= name_trn_id
;
108 nmb
->header
.opcode
= 0;
109 nmb
->header
.response
= False
;
110 nmb
->header
.nm_flags
.bcast
= False
;
111 nmb
->header
.nm_flags
.recursion_available
= False
;
112 nmb
->header
.nm_flags
.recursion_desired
= False
;
113 nmb
->header
.nm_flags
.trunc
= False
;
114 nmb
->header
.nm_flags
.authoritative
= False
;
115 nmb
->header
.rcode
= 0;
116 nmb
->header
.qdcount
= 1;
117 nmb
->header
.ancount
= 0;
118 nmb
->header
.nscount
= 0;
119 nmb
->header
.arcount
= 0;
121 make_nmb_name(&nmb
->question
.question_name
,name
,name_type
,scope
);
123 nmb
->question
.question_type
= 0x21;
124 nmb
->question
.question_class
= 0x1;
129 p
.timestamp
= time(NULL
);
130 p
.packet_type
= NMB_PACKET
;
134 if (!send_packet(&p
))
141 struct timeval tval2
;
142 GetTimeOfDay(&tval2
);
143 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
145 if (!found
&& !send_packet(&p
))
151 if ((p2
=receive_packet(fd
,NMB_PACKET
,90)))
153 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
154 debug_nmb_packet(p2
);
156 if (nmb
->header
.name_trn_id
!= nmb2
->header
.name_trn_id
||
157 !nmb2
->header
.response
) {
158 /* its not for us - maybe deal with it later */
166 if (nmb2
->header
.opcode
!= 0 ||
167 nmb2
->header
.nm_flags
.bcast
||
168 nmb2
->header
.rcode
||
169 !nmb2
->header
.ancount
||
170 nmb2
->answers
->rr_type
!= 0x21) {
171 /* XXXX what do we do with this? could be a redirect, but
172 we'll discard it for the moment */
177 _interpret_node_status(&nmb2
->answers
->rdata
[0], master
,rname
);
184 DEBUG(0,("No status response (this is not unusual)\n"));
190 /****************************************************************************
191 do a netbios name query to find someones IP
192 ****************************************************************************/
193 BOOL
name_query(int fd
,char *name
,int name_type
,
194 BOOL bcast
,BOOL recurse
,
195 struct in_addr to_ip
, struct in_addr
*ip
,void (*fn
)())
199 int retry_time
= bcast
?250:2000;
201 struct packet_struct p
;
202 struct packet_struct
*p2
;
203 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
204 static int name_trn_id
= 0;
206 bzero((char *)&p
,sizeof(p
));
208 if (!name_trn_id
) name_trn_id
= (time(NULL
)%(unsigned)0x7FFF) +
209 (getpid()%(unsigned)100);
210 name_trn_id
= (name_trn_id
+1) % (unsigned)0x7FFF;
212 nmb
->header
.name_trn_id
= name_trn_id
;
213 nmb
->header
.opcode
= 0;
214 nmb
->header
.response
= False
;
215 nmb
->header
.nm_flags
.bcast
= bcast
;
216 nmb
->header
.nm_flags
.recursion_available
= False
;
217 nmb
->header
.nm_flags
.recursion_desired
= True
;
218 nmb
->header
.nm_flags
.trunc
= False
;
219 nmb
->header
.nm_flags
.authoritative
= False
;
220 nmb
->header
.rcode
= 0;
221 nmb
->header
.qdcount
= 1;
222 nmb
->header
.ancount
= 0;
223 nmb
->header
.nscount
= 0;
224 nmb
->header
.arcount
= 0;
226 make_nmb_name(&nmb
->question
.question_name
,name
,name_type
,scope
);
228 nmb
->question
.question_type
= 0x20;
229 nmb
->question
.question_class
= 0x1;
234 p
.timestamp
= time(NULL
);
235 p
.packet_type
= NMB_PACKET
;
239 if (!send_packet(&p
))
246 struct timeval tval2
;
247 GetTimeOfDay(&tval2
);
248 if (TvalDiff(&tval
,&tval2
) > retry_time
) {
250 if (!found
&& !send_packet(&p
))
256 if ((p2
=receive_packet(fd
,NMB_PACKET
,90)))
258 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
259 debug_nmb_packet(p2
);
261 if (nmb
->header
.name_trn_id
!= nmb2
->header
.name_trn_id
||
262 !nmb2
->header
.response
) {
263 /* its not for us - maybe deal with it later
264 (put it on the queue?) */
272 if (nmb2
->header
.opcode
!= 0 ||
273 nmb2
->header
.nm_flags
.bcast
||
274 nmb2
->header
.rcode
||
275 !nmb2
->header
.ancount
) {
276 /* XXXX what do we do with this? could be a redirect, but
277 we'll discard it for the moment */
283 putip((char *)ip
,&nmb2
->answers
->rdata
[2]);
284 DEBUG(fn
?3:2,("Got a positive name query response from %s",
286 DEBUG(fn
?3:2,(" (%s)\n",inet_ntoa(*ip
)));
288 found
=True
; retries
=0;