2 Unix SMB/Netbios implementation.
4 NBT netbios library routines
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.
27 extern int ClientDGRAM;
29 /* this is our initiated name query response database */
30 struct name_response_record *nameresponselist = NULL;
32 extern int DEBUGLEVEL;
34 static uint16 name_trn_id=0;
35 BOOL CanRecurse = True;
37 extern pstring myname;
38 extern struct in_addr ipzero;
41 /***************************************************************************
42 add an initated name query into the list
43 **************************************************************************/
44 extern void add_response_record(struct name_response_record *n)
46 struct name_response_record *n2;
48 if (!nameresponselist)
56 for (n2 = nameresponselist; n2->next; n2 = n2->next) ;
64 /*******************************************************************
65 remove old name response entries
66 ******************************************************************/
67 void expire_netbios_response_entries(time_t t)
69 struct name_response_record *n;
70 struct name_response_record *nextn;
72 for (n = nameresponselist; n; n = nextn)
74 if (n->start_time < t)
76 DEBUG(3,("Removing dead name query for %s %s (num_msgs=%d)\n",
77 inet_ntoa(n->to_ip), namestr(&n->name), n->num_msgs));
79 if (n->cmd_type == CHECK_MASTER)
81 /* if no response received, the master browser must have gone */
83 browser_gone(n->name.name, n->to_ip);
88 if (n->prev) n->prev->next = n->next;
89 if (n->next) n->next->prev = n->prev;
91 if (nameresponselist == n) nameresponselist = n->next;
103 /****************************************************************************
104 reply to a netbios name packet
105 ****************************************************************************/
106 void reply_netbios_packet(struct packet_struct *p1,int trn_id,int rcode,int opcode,
107 struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
110 struct packet_struct p;
111 struct nmb_packet *nmb = &p.packet.nmb;
112 struct res_rec answers;
113 char *packet_type = "unknown";
117 if (rr_type == NMB_STATUS) packet_type = "nmb_status";
118 if (rr_type == NMB_QUERY ) packet_type = "nmb_query";
119 if (rr_type == NMB_REG ) packet_type = "nmb_reg";
120 if (rr_type == NMB_REL ) packet_type = "nmb_rel";
122 DEBUG(4,("replying netbios packet: %s %s\n",
123 packet_type, namestr(rr_name), inet_ntoa(p.ip)));
125 nmb->header.name_trn_id = trn_id;
126 nmb->header.opcode = opcode;
127 nmb->header.response = True;
128 nmb->header.nm_flags.bcast = False;
129 nmb->header.nm_flags.recursion_available = True;
130 nmb->header.nm_flags.recursion_desired = True;
131 nmb->header.nm_flags.trunc = False;
132 nmb->header.nm_flags.authoritative = True;
134 nmb->header.qdcount = 0;
135 nmb->header.ancount = 1;
136 nmb->header.nscount = 0;
137 nmb->header.arcount = 0;
138 nmb->header.rcode = 0;
140 bzero((char*)&nmb->question,sizeof(nmb->question));
142 nmb->answers = &answers;
143 bzero((char*)nmb->answers,sizeof(*nmb->answers));
145 nmb->answers->rr_name = *rr_name;
146 nmb->answers->rr_type = rr_type;
147 nmb->answers->rr_class = rr_class;
148 nmb->answers->ttl = ttl;
152 nmb->answers->rdlength = len;
153 memcpy(nmb->answers->rdata, data, len);
156 p.packet_type = NMB_PACKET;
158 debug_nmb_packet(&p);
164 /****************************************************************************
165 initiate a netbios packet
166 ****************************************************************************/
167 uint16 initiate_netbios_packet(int fd,int quest_type,char *name,int name_type,
168 int nb_flags,BOOL bcast,BOOL recurse,
169 struct in_addr to_ip)
171 struct packet_struct p;
172 struct nmb_packet *nmb = &p.packet.nmb;
173 struct res_rec additional_rec;
174 char *packet_type = "unknown";
177 if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; }
178 if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; }
179 if (quest_type == NMB_REG ) { packet_type = "nmb_reg"; opcode = 5; }
180 if (quest_type == NMB_REL ) { packet_type = "nmb_rel"; opcode = 6; }
182 DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
183 packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
185 if (opcode == -1) return False;
187 bzero((char *)&p,sizeof(p));
189 if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
190 (getpid()%(unsigned)100);
191 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
193 nmb->header.name_trn_id = name_trn_id;
194 nmb->header.opcode = opcode;
195 nmb->header.response = False;
196 nmb->header.nm_flags.bcast = bcast;
197 nmb->header.nm_flags.recursion_available = CanRecurse;
198 nmb->header.nm_flags.recursion_desired = recurse;
199 nmb->header.nm_flags.trunc = False;
200 nmb->header.nm_flags.authoritative = False;
201 nmb->header.rcode = 0;
202 nmb->header.qdcount = 1;
203 nmb->header.ancount = 0;
204 nmb->header.nscount = 0;
205 nmb->header.arcount = (quest_type==NMB_REG || quest_type==NMB_REL) ? 1 : 0;
207 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
209 nmb->question.question_type = quest_type;
210 nmb->question.question_class = 0x1;
212 if (quest_type == NMB_REG || quest_type == NMB_REL)
214 nmb->additional = &additional_rec;
215 bzero((char *)nmb->additional,sizeof(*nmb->additional));
217 nmb->additional->rr_name = nmb->question.question_name;
218 nmb->additional->rr_type = nmb->question.question_type;
219 nmb->additional->rr_class = nmb->question.question_class;
221 nmb->additional->ttl = quest_type == NMB_REG ? lp_max_ttl() : 0;
222 nmb->additional->rdlength = 6;
223 nmb->additional->rdata[0] = nb_flags;
224 putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
230 p.timestamp = time(NULL);
231 p.packet_type = NMB_PACKET;
233 if (!send_packet(&p))
240 /****************************************************************************
241 wrapper function to override a broadcast message and send it to the WINS
242 name server instead, if it exists. if wins is false, and there has been no
243 WINS server specified, the packet will NOT be sent.
244 ****************************************************************************/
245 void queue_netbios_pkt_wins(int fd,int quest_type,enum cmd_type cmd,
246 char *name,int name_type,int nb_flags,
247 BOOL bcast,BOOL recurse,struct in_addr to_ip)
249 if ((!lp_wins_support()) && (*lp_wins_server()))
251 /* samba is not a WINS server, and we are using a WINS server */
252 struct in_addr wins_ip;
253 wins_ip = *interpret_addr2(lp_wins_server());
255 if (!zero_ip(wins_ip))
262 /* oops. smb.conf's wins server parameter MUST be a host_name
264 DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
268 if (zero_ip(to_ip)) return;
270 queue_netbios_packet(fd, quest_type, cmd,
271 name, name_type, nb_flags,
272 bcast, recurse, to_ip);
275 /****************************************************************************
276 create a name query response record
277 **************************************************************************/
278 static struct name_response_record *make_name_query_record(
279 enum cmd_type cmd,int id,int fd,
281 BOOL bcast,BOOL recurse,
284 struct name_response_record *n;
286 if (!name || !name[0]) return NULL;
288 if (!(n = (struct name_response_record *)malloc(sizeof(*n))))
294 make_nmb_name(&n->name, name, type, scope);
296 n->recurse = recurse;
298 n->start_time = time(NULL);
305 /****************************************************************************
306 initiate a netbios name query to find someone's or someones' IP
307 this is intended to be used (not exclusively) for broadcasting to
308 master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
309 complete lists across a wide area network
310 ****************************************************************************/
311 void queue_netbios_packet(int fd,int quest_type,enum cmd_type cmd,char *name,
312 int name_type,int nb_flags,BOOL bcast,BOOL recurse,
313 struct in_addr to_ip)
315 uint16 id = initiate_netbios_packet(fd, quest_type, name, name_type,
316 nb_flags, bcast, recurse, to_ip);
317 struct name_response_record *n;
322 make_name_query_record(cmd,id,fd,name,name_type,bcast,recurse,to_ip)))
324 add_response_record(n);
329 /****************************************************************************
330 find a response in the name query response list
331 **************************************************************************/
332 struct name_response_record *find_name_query(uint16 id)
334 struct name_response_record *n;
336 for (n = nameresponselist; n; n = n->next)
338 if (n->response_id == id) {
347 /*******************************************************************
348 the global packet linked-list. incoming entries are added to the
349 end of this list. it is supposed to remain fairly short so we
350 won't bother with an end pointer.
351 ******************************************************************/
352 static struct packet_struct *packet_queue = NULL;
354 /*******************************************************************
355 queue a packet into the packet queue
356 ******************************************************************/
357 void queue_packet(struct packet_struct *packet)
359 struct packet_struct *p;
364 packet_queue = packet;
368 /* find the bottom */
369 for (p=packet_queue;p->next;p=p->next) ;
376 /*******************************************************************
377 run elements off the packet queue till its empty
378 ******************************************************************/
379 void run_packet_queue()
381 struct packet_struct *p;
383 while ((p=packet_queue))
385 switch (p->packet_type)
396 packet_queue = packet_queue->next;
397 if (packet_queue) packet_queue->prev = NULL;
402 /****************************************************************************
403 listens for NMB or DGRAM packets, and queues them
404 ***************************************************************************/
405 void listen_for_packets(BOOL run_election)
409 struct timeval timeout;
412 FD_SET(ClientNMB,&fds);
413 FD_SET(ClientDGRAM,&fds);
415 /* during elections we need to send election packets at one
418 timeout.tv_sec = run_election ? 1 : NMBD_SELECT_LOOP;
421 selrtn = sys_select(&fds,&timeout);
423 if (FD_ISSET(ClientNMB,&fds))
425 struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
428 if (ismyip(packet->ip) &&
429 (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
430 DEBUG(5,("discarding own packet from %s:%d\n",
431 inet_ntoa(packet->ip),packet->port));
436 queue_packet(packet);
441 if (FD_ISSET(ClientDGRAM,&fds))
443 struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
446 if (ismyip(packet->ip) &&
447 (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
448 DEBUG(5,("discarding own packet from %s:%d\n",
449 inet_ntoa(packet->ip),packet->port));
454 queue_packet(packet);
462 /****************************************************************************
463 interpret a node status response. this is pretty hacked: we need two bits of
464 info. a) the name of the workgroup b) the name of the server. it will also
465 add all the names it finds into the namelist.
466 ****************************************************************************/
467 BOOL interpret_node_status(char *p, struct nmb_name *name,int t,
468 char *serv_name, struct in_addr ip)
470 int level = t==0x20 ? 4 : 0;
471 int numnames = CVAL(p,0);
474 DEBUG(level,("received %d names\n",numnames));
478 if (serv_name) *serv_name = 0;
495 trim_string(qname,NULL," ");
499 if (NAME_GROUP (nb_flags)) { strcat(flags,"<GROUP> "); group=True;}
500 if (NAME_BFLAG (nb_flags)) { strcat(flags,"B "); }
501 if (NAME_PFLAG (nb_flags)) { strcat(flags,"P "); }
502 if (NAME_MFLAG (nb_flags)) { strcat(flags,"M "); }
503 if (NAME__FLAG (nb_flags)) { strcat(flags,"_ "); }
504 if (NAME_DEREG (nb_flags)) { strcat(flags,"<DEREGISTERING> "); }
505 if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); add=True;}
506 if (NAME_ACTIVE (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; }
507 if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;}
509 /* might as well update our namelist while we're at it */
512 struct in_addr nameip;
513 enum name_source src;
522 add_netbios_entry(qname,type,nb_flags,2*60*60,src,nameip,True);
525 /* we want the server name */
526 if (serv_name && !*serv_name && !group && t == 0)
528 StrnCpy(serv_name,qname,15);
532 /* looking for a name and type? */
533 if (name && !found && (t == type))
535 /* take a guess at some of the name types we're going to ask for.
536 evaluate whether they are group names or no... */
537 if (((t == 0x1b || t == 0x1d ) && !group) ||
538 ((t == 0x20 || t == 0x1c || t == 0x1e) && group))
541 make_nmb_name(name,qname,type,scope);
545 DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
547 DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
548 IVAL(p,20),IVAL(p,24)));
553 /****************************************************************************
554 construct and send a netbios DGRAM
556 Note that this currently sends all answers to port 138. thats the
557 wrong things to do! I should send to the requestors port. XXX
558 **************************************************************************/
559 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
560 char *dstname,int src_type,int dest_type,
561 struct in_addr dest_ip,struct in_addr src_ip)
563 struct packet_struct p;
564 struct dgram_packet *dgram = &p.packet.dgram;
568 bzero((char *)&p,sizeof(p));
570 dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
571 dgram->header.flags.node_type = M_NODE;
572 dgram->header.flags.first = True;
573 dgram->header.flags.more = False;
574 dgram->header.dgm_id = name_trn_id++;
575 dgram->header.source_ip = src_ip;
576 dgram->header.source_port = DGRAM_PORT;
577 dgram->header.dgm_length = 0; /* let build_dgram() handle this */
578 dgram->header.packet_offset = 0;
580 make_nmb_name(&dgram->source_name,srcname,src_type,scope);
581 make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
583 ptr = &dgram->data[0];
585 /* now setup the smb part */
586 ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
588 set_message(ptr,17,17 + len,True);
591 CVAL(ptr,smb_com) = SMBtrans;
592 SSVAL(ptr,smb_vwv1,len);
593 SSVAL(ptr,smb_vwv11,len);
594 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
595 SSVAL(ptr,smb_vwv13,3);
596 SSVAL(ptr,smb_vwv14,1);
597 SSVAL(ptr,smb_vwv15,1);
598 SSVAL(ptr,smb_vwv16,2);
601 p2 = skip_string(p2,1);
606 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
611 p.timestamp = time(NULL);
612 p.packet_type = DGRAM_PACKET;
614 return(send_packet(&p));