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 if (*id == 0xffff) *id = name_trn_id; /* allow resending with same id */
88 nmb->header.name_trn_id = *id;
89 nmb->header.opcode = opcode;
90 nmb->header.response = False;
92 nmb->header.nm_flags.bcast = bcast;
93 nmb->header.nm_flags.recursion_available = CanRecurse;
94 nmb->header.nm_flags.recursion_desired = recurse;
95 nmb->header.nm_flags.trunc = False;
96 nmb->header.nm_flags.authoritative = False;
98 nmb->header.rcode = 0;
99 nmb->header.qdcount = 1;
100 nmb->header.ancount = 0;
101 nmb->header.nscount = 0;
102 nmb->header.arcount = (quest_type==NMB_REG || quest_type==NMB_REL) ? 1 : 0;
104 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
106 nmb->question.question_type = quest_type;
107 nmb->question.question_class = 0x1;
109 if (quest_type == NMB_REG || quest_type == NMB_REL)
111 nmb->additional = &additional_rec;
112 bzero((char *)nmb->additional,sizeof(*nmb->additional));
114 nmb->additional->rr_name = nmb->question.question_name;
115 nmb->additional->rr_type = nmb->question.question_type;
116 nmb->additional->rr_class = nmb->question.question_class;
118 nmb->additional->ttl = quest_type == NMB_REG ? lp_max_ttl() : 0;
119 nmb->additional->rdlength = 6;
120 nmb->additional->rdata[0] = nb_flags;
121 putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
127 p.timestamp = time(NULL);
128 p.packet_type = NMB_PACKET;
130 if (!send_packet(&p)) *id = 0xffff;
136 /****************************************************************************
137 reply to a netbios name packet
138 ****************************************************************************/
139 void reply_netbios_packet(struct packet_struct *p1,int trn_id,
140 int rcode,int opcode, BOOL recurse,
141 struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
144 struct packet_struct p;
145 struct nmb_packet *nmb = &p.packet.nmb;
146 struct res_rec answers;
147 char *packet_type = "unknown";
148 BOOL recursion_desired = False;
156 packet_type = "nmb_status";
157 recursion_desired = True;
162 packet_type = "nmb_query";
163 recursion_desired = True;
168 packet_type = "nmb_reg";
169 recursion_desired = True;
174 packet_type = "nmb_rel";
175 recursion_desired = False;
180 packet_type = "nmb_wack";
181 recursion_desired = False;
186 DEBUG(1,("replying netbios packet: %s %s\n",
187 packet_type, namestr(rr_name), inet_ntoa(p.ip)));
193 DEBUG(4,("replying netbios packet: %s %s\n",
194 packet_type, namestr(rr_name), inet_ntoa(p.ip)));
196 nmb->header.name_trn_id = trn_id;
197 nmb->header.opcode = opcode;
198 nmb->header.response = True;
199 nmb->header.nm_flags.bcast = False;
200 nmb->header.nm_flags.recursion_available = recurse;
201 nmb->header.nm_flags.recursion_desired = recursion_desired;
202 nmb->header.nm_flags.trunc = False;
203 nmb->header.nm_flags.authoritative = True;
205 nmb->header.qdcount = 0;
206 nmb->header.ancount = 1;
207 nmb->header.nscount = 0;
208 nmb->header.arcount = 0;
209 nmb->header.rcode = 0;
211 bzero((char*)&nmb->question,sizeof(nmb->question));
213 nmb->answers = &answers;
214 bzero((char*)nmb->answers,sizeof(*nmb->answers));
216 nmb->answers->rr_name = *rr_name;
217 nmb->answers->rr_type = rr_type;
218 nmb->answers->rr_class = rr_class;
219 nmb->answers->ttl = ttl;
223 nmb->answers->rdlength = len;
224 memcpy(nmb->answers->rdata, data, len);
227 p.packet_type = NMB_PACKET;
229 debug_nmb_packet(&p);
235 /*******************************************************************
236 the global packet linked-list. incoming entries are added to the
237 end of this list. it is supposed to remain fairly short so we
238 won't bother with an end pointer.
239 ******************************************************************/
240 static struct packet_struct *packet_queue = NULL;
242 /*******************************************************************
243 queue a packet into the packet queue
244 ******************************************************************/
245 void queue_packet(struct packet_struct *packet)
247 struct packet_struct *p;
252 packet_queue = packet;
256 /* find the bottom */
257 for (p=packet_queue;p->next;p=p->next) ;
265 /****************************************************************************
266 process udp 138 datagrams
267 ****************************************************************************/
268 static void process_dgram(struct packet_struct *p)
273 struct dgram_packet *dgram = &p->packet.dgram;
275 if (dgram->header.msg_type != 0x10 &&
276 dgram->header.msg_type != 0x11 &&
277 dgram->header.msg_type != 0x12) {
278 /* don't process error packets etc yet */
282 buf = &dgram->data[0];
283 buf -= 4; /* XXXX for the pseudo tcp length -
284 someday I need to get rid of this */
286 if (CVAL(buf,smb_com) != SMBtrans) return;
288 len = SVAL(buf,smb_vwv11);
289 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
291 DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
292 namestr(&dgram->source_name),namestr(&dgram->dest_name),
293 smb_buf(buf),CVAL(buf2,0),len));
296 if (len <= 0) return;
298 /* datagram packet received for the browser mailslot */
299 if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) {
300 process_browse_packet(p,buf2,len);
304 /* datagram packet received for the domain log on mailslot */
305 if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) {
306 process_logon_packet(p,buf2,len);
311 /****************************************************************************
313 ****************************************************************************/
314 static void process_nmb(struct packet_struct *p)
316 struct nmb_packet *nmb = &p->packet.nmb;
320 switch (nmb->header.opcode)
322 case 8: /* what is this?? */
324 case NMB_REG_REFRESH:
326 if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
327 if (nmb->header.response)
328 response_netbios_packet(p); /* response to registration dealt with here */
336 if (nmb->header.response)
338 switch (nmb->question.question_type)
342 response_netbios_packet(p);
348 else if (nmb->header.qdcount>0)
350 switch (nmb->question.question_type)
359 reply_name_status(p);
370 if (nmb->header.qdcount==0 || nmb->header.arcount==0)
372 DEBUG(2,("netbios release packet rejected\n"));
376 if (nmb->header.response)
377 response_netbios_packet(p); /* response to reply dealt with in here */
379 reply_name_release(p);
386 /*******************************************************************
387 run elements off the packet queue till its empty
388 ******************************************************************/
389 void run_packet_queue()
391 struct packet_struct *p;
393 while ((p=packet_queue))
395 switch (p->packet_type)
406 packet_queue = packet_queue->next;
407 if (packet_queue) packet_queue->prev = NULL;
412 /****************************************************************************
413 listens for NMB or DGRAM packets, and queues them
414 ***************************************************************************/
415 void listen_for_packets(BOOL run_election)
419 struct timeval timeout;
422 FD_SET(ClientNMB,&fds);
423 FD_SET(ClientDGRAM,&fds);
425 /* during elections and when expecting a netbios response packet we need
426 to send election packets at one second intervals.
427 XXXX actually, it needs to be the interval (in ms) between time now and the
428 time we are expecting the next netbios packet */
430 timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
433 selrtn = sys_select(&fds,&timeout);
435 if (FD_ISSET(ClientNMB,&fds))
437 struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
440 if (ismyip(packet->ip) &&
441 (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
442 DEBUG(5,("discarding own packet from %s:%d\n",
443 inet_ntoa(packet->ip),packet->port));
448 queue_packet(packet);
453 if (FD_ISSET(ClientDGRAM,&fds))
455 struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
458 if (ismyip(packet->ip) &&
459 (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
460 DEBUG(5,("discarding own packet from %s:%d\n",
461 inet_ntoa(packet->ip),packet->port));
466 queue_packet(packet);
474 /****************************************************************************
475 construct and send a netbios DGRAM
477 Note that this currently sends all answers to port 138. thats the
478 wrong things to do! I should send to the requestors port. XXX
479 **************************************************************************/
480 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
481 char *dstname,int src_type,int dest_type,
482 struct in_addr dest_ip,struct in_addr src_ip)
484 struct packet_struct p;
485 struct dgram_packet *dgram = &p.packet.dgram;
486 struct in_addr wins_ip = ipgrp;
490 /* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */
491 if (ip_equal(wins_ip, dest_ip)) return False;
493 bzero((char *)&p,sizeof(p));
495 update_name_trn_id();
497 dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
498 dgram->header.flags.node_type = M_NODE;
499 dgram->header.flags.first = True;
500 dgram->header.flags.more = False;
501 dgram->header.dgm_id = name_trn_id;
502 dgram->header.source_ip = src_ip;
503 dgram->header.source_port = DGRAM_PORT;
504 dgram->header.dgm_length = 0; /* let build_dgram() handle this */
505 dgram->header.packet_offset = 0;
507 make_nmb_name(&dgram->source_name,srcname,src_type,scope);
508 make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
510 ptr = &dgram->data[0];
512 /* now setup the smb part */
513 ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
515 set_message(ptr,17,17 + len,True);
518 CVAL(ptr,smb_com) = SMBtrans;
519 SSVAL(ptr,smb_vwv1,len);
520 SSVAL(ptr,smb_vwv11,len);
521 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
522 SSVAL(ptr,smb_vwv13,3);
523 SSVAL(ptr,smb_vwv14,1);
524 SSVAL(ptr,smb_vwv15,1);
525 SSVAL(ptr,smb_vwv16,2);
528 p2 = skip_string(p2,1);
533 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
538 p.timestamp = time(NULL);
539 p.packet_type = DGRAM_PACKET;
541 return(send_packet(&p));