2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1995
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.
23 14 jan 96: lkcl@pires.co.uk
24 added multiple workgroup domain master support
31 extern int ClientDGRAM
;
33 extern int DEBUGLEVEL
;
35 extern int num_response_packets
;
37 BOOL CanRecurse
= True
;
39 extern struct in_addr ipgrp
;
41 static uint16 name_trn_id
=0;
43 /***************************************************************************
44 updates the unique transaction identifier
45 **************************************************************************/
46 static void update_name_trn_id(void)
50 name_trn_id
= (time(NULL
)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
52 name_trn_id
= (name_trn_id
+1) % (unsigned)0x7FFF;
56 /****************************************************************************
57 initiate a netbios packet
58 ****************************************************************************/
59 void initiate_netbios_packet(uint16
*id
,
60 int fd
,int quest_type
,char *name
,int name_type
,
61 int nb_flags
,BOOL bcast
,BOOL recurse
,
64 struct packet_struct p
;
65 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
66 struct res_rec additional_rec
;
67 char *packet_type
= "unknown";
72 if (quest_type
== NMB_STATUS
) { packet_type
= "nmb_status"; opcode
= 0; }
73 if (quest_type
== NMB_QUERY
) { packet_type
= "nmb_query"; opcode
= 0; }
74 if (quest_type
== NMB_REG
) { packet_type
= "nmb_reg"; opcode
= 5; }
75 if (quest_type
== NMB_REL
) { packet_type
= "nmb_rel"; opcode
= 6; }
77 DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
78 packet_type
, name
, name_type
, BOOLSTR(bcast
), inet_ntoa(to_ip
)));
80 if (opcode
== -1) return;
82 bzero((char *)&p
,sizeof(p
));
86 *id
= name_trn_id
; /* allow resending with same id */
89 nmb
->header
.name_trn_id
= *id
;
90 nmb
->header
.opcode
= opcode
;
91 nmb
->header
.response
= False
;
93 nmb
->header
.nm_flags
.bcast
= bcast
;
94 nmb
->header
.nm_flags
.recursion_available
= CanRecurse
;
95 nmb
->header
.nm_flags
.recursion_desired
= recurse
;
96 nmb
->header
.nm_flags
.trunc
= False
;
97 nmb
->header
.nm_flags
.authoritative
= False
;
99 nmb
->header
.rcode
= 0;
100 nmb
->header
.qdcount
= 1;
101 nmb
->header
.ancount
= 0;
102 nmb
->header
.nscount
= 0;
103 nmb
->header
.arcount
= (quest_type
==NMB_REG
|| quest_type
==NMB_REL
) ? 1 : 0;
105 make_nmb_name(&nmb
->question
.question_name
,name
,name_type
,scope
);
107 nmb
->question
.question_type
= quest_type
;
108 nmb
->question
.question_class
= 0x1;
110 if (quest_type
== NMB_REG
|| quest_type
== NMB_REL
)
112 nmb
->additional
= &additional_rec
;
113 bzero((char *)nmb
->additional
,sizeof(*nmb
->additional
));
115 nmb
->additional
->rr_name
= nmb
->question
.question_name
;
116 nmb
->additional
->rr_type
= nmb
->question
.question_type
;
117 nmb
->additional
->rr_class
= nmb
->question
.question_class
;
119 nmb
->additional
->ttl
= quest_type
== NMB_REG
? lp_max_ttl() : 0;
120 nmb
->additional
->rdlength
= 6;
121 nmb
->additional
->rdata
[0] = nb_flags
;
122 putip(&nmb
->additional
->rdata
[2],(char *)iface_ip(to_ip
));
128 p
.timestamp
= time(NULL
);
129 p
.packet_type
= NMB_PACKET
;
131 if (!send_packet(&p
)) *id
= 0xffff;
137 /****************************************************************************
138 reply to a netbios name packet
139 ****************************************************************************/
140 void reply_netbios_packet(struct packet_struct
*p1
,int trn_id
,
141 int rcode
,int opcode
, BOOL recurse
,
142 struct nmb_name
*rr_name
,int rr_type
,int rr_class
,int ttl
,
145 struct packet_struct p
;
146 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
147 struct res_rec answers
;
148 char *packet_type
= "unknown";
149 BOOL recursion_desired
= False
;
157 packet_type
= "nmb_status";
158 recursion_desired
= True
;
163 packet_type
= "nmb_query";
164 recursion_desired
= True
;
169 packet_type
= "nmb_reg";
170 recursion_desired
= True
;
175 packet_type
= "nmb_rel";
176 recursion_desired
= False
;
181 packet_type
= "nmb_wack";
182 recursion_desired
= False
;
187 DEBUG(1,("replying netbios packet: %s %s\n",
188 packet_type
, namestr(rr_name
), inet_ntoa(p
.ip
)));
194 DEBUG(4,("replying netbios packet: %s %s\n",
195 packet_type
, namestr(rr_name
), inet_ntoa(p
.ip
)));
197 nmb
->header
.name_trn_id
= trn_id
;
198 nmb
->header
.opcode
= opcode
;
199 nmb
->header
.response
= True
;
200 nmb
->header
.nm_flags
.bcast
= False
;
201 nmb
->header
.nm_flags
.recursion_available
= recurse
;
202 nmb
->header
.nm_flags
.recursion_desired
= recursion_desired
;
203 nmb
->header
.nm_flags
.trunc
= False
;
204 nmb
->header
.nm_flags
.authoritative
= True
;
206 nmb
->header
.qdcount
= 0;
207 nmb
->header
.ancount
= 1;
208 nmb
->header
.nscount
= 0;
209 nmb
->header
.arcount
= 0;
210 nmb
->header
.rcode
= 0;
212 bzero((char*)&nmb
->question
,sizeof(nmb
->question
));
214 nmb
->answers
= &answers
;
215 bzero((char*)nmb
->answers
,sizeof(*nmb
->answers
));
217 nmb
->answers
->rr_name
= *rr_name
;
218 nmb
->answers
->rr_type
= rr_type
;
219 nmb
->answers
->rr_class
= rr_class
;
220 nmb
->answers
->ttl
= ttl
;
224 nmb
->answers
->rdlength
= len
;
225 memcpy(nmb
->answers
->rdata
, data
, len
);
228 p
.packet_type
= NMB_PACKET
;
230 debug_nmb_packet(&p
);
236 /*******************************************************************
237 the global packet linked-list. incoming entries are added to the
238 end of this list. it is supposed to remain fairly short so we
239 won't bother with an end pointer.
240 ******************************************************************/
241 static struct packet_struct
*packet_queue
= NULL
;
243 /*******************************************************************
244 queue a packet into the packet queue
245 ******************************************************************/
246 void queue_packet(struct packet_struct
*packet
)
248 struct packet_struct
*p
;
253 packet_queue
= packet
;
257 /* find the bottom */
258 for (p
=packet_queue
;p
->next
;p
=p
->next
) ;
266 /****************************************************************************
267 process udp 138 datagrams
268 ****************************************************************************/
269 static void process_dgram(struct packet_struct
*p
)
274 struct dgram_packet
*dgram
= &p
->packet
.dgram
;
276 if (dgram
->header
.msg_type
!= 0x10 &&
277 dgram
->header
.msg_type
!= 0x11 &&
278 dgram
->header
.msg_type
!= 0x12) {
279 /* don't process error packets etc yet */
283 buf
= &dgram
->data
[0];
284 buf
-= 4; /* XXXX for the pseudo tcp length -
285 someday I need to get rid of this */
287 if (CVAL(buf
,smb_com
) != SMBtrans
) return;
289 len
= SVAL(buf
,smb_vwv11
);
290 buf2
= smb_base(buf
) + SVAL(buf
,smb_vwv12
);
292 DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
293 namestr(&dgram
->source_name
),namestr(&dgram
->dest_name
),
294 smb_buf(buf
),CVAL(buf2
,0),len
));
297 if (len
<= 0) return;
299 /* datagram packet received for the browser mailslot */
300 if (strequal(smb_buf(buf
),BROWSE_MAILSLOT
)) {
301 process_browse_packet(p
,buf2
,len
);
305 /* datagram packet received for the domain log on mailslot */
306 if (strequal(smb_buf(buf
),NET_LOGON_MAILSLOT
)) {
307 process_logon_packet(p
,buf2
,len
);
312 /****************************************************************************
314 ****************************************************************************/
315 static void process_nmb(struct packet_struct
*p
)
317 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
321 switch (nmb
->header
.opcode
)
323 case 8: /* what is this?? */
325 case NMB_REG_REFRESH
:
327 if (nmb
->header
.qdcount
==0 || nmb
->header
.arcount
==0) break;
328 if (nmb
->header
.response
)
329 response_netbios_packet(p
); /* response to registration dealt with here */
337 if (nmb
->header
.response
)
339 switch (nmb
->question
.question_type
)
343 response_netbios_packet(p
);
349 else if (nmb
->header
.qdcount
>0)
351 switch (nmb
->question
.question_type
)
360 reply_name_status(p
);
371 if (nmb
->header
.qdcount
==0 || nmb
->header
.arcount
==0)
373 DEBUG(2,("netbios release packet rejected\n"));
377 if (nmb
->header
.response
)
378 response_netbios_packet(p
); /* response to reply dealt with in here */
380 reply_name_release(p
);
387 /*******************************************************************
388 run elements off the packet queue till its empty
389 ******************************************************************/
390 void run_packet_queue()
392 struct packet_struct
*p
;
394 while ((p
=packet_queue
))
396 switch (p
->packet_type
)
407 packet_queue
= packet_queue
->next
;
408 if (packet_queue
) packet_queue
->prev
= NULL
;
413 /****************************************************************************
414 listens for NMB or DGRAM packets, and queues them
415 ***************************************************************************/
416 void listen_for_packets(BOOL run_election
)
420 struct timeval timeout
;
423 FD_SET(ClientNMB
,&fds
);
424 FD_SET(ClientDGRAM
,&fds
);
426 /* during elections and when expecting a netbios response packet we need
427 to send election packets at one second intervals.
428 XXXX actually, it needs to be the interval (in ms) between time now and the
429 time we are expecting the next netbios packet */
431 timeout
.tv_sec
= (run_election
||num_response_packets
) ? 1 : NMBD_SELECT_LOOP
;
434 selrtn
= sys_select(&fds
,&timeout
);
436 if (FD_ISSET(ClientNMB
,&fds
))
438 struct packet_struct
*packet
= read_packet(ClientNMB
, NMB_PACKET
);
441 if (ismyip(packet
->ip
) &&
442 (packet
->port
== NMB_PORT
|| packet
->port
== DGRAM_PORT
)) {
443 DEBUG(5,("discarding own packet from %s:%d\n",
444 inet_ntoa(packet
->ip
),packet
->port
));
449 queue_packet(packet
);
454 if (FD_ISSET(ClientDGRAM
,&fds
))
456 struct packet_struct
*packet
= read_packet(ClientDGRAM
, DGRAM_PACKET
);
459 if (ismyip(packet
->ip
) &&
460 (packet
->port
== NMB_PORT
|| packet
->port
== DGRAM_PORT
)) {
461 DEBUG(5,("discarding own packet from %s:%d\n",
462 inet_ntoa(packet
->ip
),packet
->port
));
467 queue_packet(packet
);
475 /****************************************************************************
476 construct and send a netbios DGRAM
478 Note that this currently sends all answers to port 138. thats the
479 wrong things to do! I should send to the requestors port. XXX
480 **************************************************************************/
481 BOOL
send_mailslot_reply(char *mailslot
,int fd
,char *buf
,int len
,char *srcname
,
482 char *dstname
,int src_type
,int dest_type
,
483 struct in_addr dest_ip
,struct in_addr src_ip
)
485 struct packet_struct p
;
486 struct dgram_packet
*dgram
= &p
.packet
.dgram
;
487 struct in_addr wins_ip
= ipgrp
;
491 /* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */
492 if (ip_equal(wins_ip
, dest_ip
)) return False
;
494 bzero((char *)&p
,sizeof(p
));
496 update_name_trn_id();
498 dgram
->header
.msg_type
= 0x11; /* DIRECT GROUP DATAGRAM */
499 dgram
->header
.flags
.node_type
= M_NODE
;
500 dgram
->header
.flags
.first
= True
;
501 dgram
->header
.flags
.more
= False
;
502 dgram
->header
.dgm_id
= name_trn_id
;
503 dgram
->header
.source_ip
= src_ip
;
504 dgram
->header
.source_port
= DGRAM_PORT
;
505 dgram
->header
.dgm_length
= 0; /* let build_dgram() handle this */
506 dgram
->header
.packet_offset
= 0;
508 make_nmb_name(&dgram
->source_name
,srcname
,src_type
,scope
);
509 make_nmb_name(&dgram
->dest_name
,dstname
,dest_type
,scope
);
511 ptr
= &dgram
->data
[0];
513 /* now setup the smb part */
514 ptr
-= 4; /* XXX ugliness because of handling of tcp SMB length */
516 set_message(ptr
,17,17 + len
,True
);
519 CVAL(ptr
,smb_com
) = SMBtrans
;
520 SSVAL(ptr
,smb_vwv1
,len
);
521 SSVAL(ptr
,smb_vwv11
,len
);
522 SSVAL(ptr
,smb_vwv12
,70 + strlen(mailslot
));
523 SSVAL(ptr
,smb_vwv13
,3);
524 SSVAL(ptr
,smb_vwv14
,1);
525 SSVAL(ptr
,smb_vwv15
,1);
526 SSVAL(ptr
,smb_vwv16
,2);
529 p2
= skip_string(p2
,1);
534 dgram
->datasize
= PTR_DIFF(p2
,ptr
+4); /* +4 for tcp length */
539 p
.timestamp
= time(NULL
);
540 p
.packet_type
= DGRAM_PACKET
;
542 return(send_packet(&p
));