78e6274f8ca8842abdd3455adbeadf0f7bf0a692
[samba.git] / source / nameresp.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios library routines
5    Copyright (C) Andrew Tridgell 1994-1995
6    
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.
11    
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.
16    
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.
20    
21 */
22
23 #include "includes.h"
24 #include "loadparm.h"
25
26 extern int ClientNMB;
27 extern int ClientDGRAM;
28
29 /* this is our initiated name query response database */
30 struct name_response_record *nameresponselist = NULL;
31
32 extern int DEBUGLEVEL;
33
34 static uint16 name_trn_id=0;
35 BOOL CanRecurse = True;
36 extern pstring scope;
37 extern pstring myname;
38 extern struct in_addr ipzero;
39
40
41 /***************************************************************************
42   add an initated name query  into the list
43   **************************************************************************/
44 extern void add_response_record(struct name_response_record *n)
45 {
46   struct name_response_record *n2;
47
48   if (!nameresponselist)
49     {
50       nameresponselist = n;
51       n->prev = NULL;
52       n->next = NULL;
53       return;
54     }
55   
56   for (n2 = nameresponselist; n2->next; n2 = n2->next) ;
57   
58   n2->next = n;
59   n->next = NULL;
60   n->prev = n2;
61 }
62
63
64 /*******************************************************************
65   remove old name response entries
66   ******************************************************************/
67 void expire_netbios_response_entries(time_t t)
68 {
69   struct name_response_record *n;
70   struct name_response_record *nextn;
71
72   for (n = nameresponselist; n; n = nextn)
73     {
74       if (n->start_time < t)
75         {
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));
78
79           if (n->cmd_type == CHECK_MASTER)
80             {
81               /* if no response received, the master browser must have gone */
82               if (n->num_msgs == 0)
83                 browser_gone(n->name.name, n->to_ip);
84             }
85           
86           nextn = n->next;
87           
88           if (n->prev) n->prev->next = n->next;
89           if (n->next) n->next->prev = n->prev;
90           
91           if (nameresponselist == n) nameresponselist = n->next; 
92           
93           free(n);
94         }
95       else
96         {
97           nextn = n->next;
98         }
99     }
100 }
101
102
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,
108                           char *data,int len)
109 {
110   struct packet_struct p;
111   struct nmb_packet *nmb = &p.packet.nmb;
112   struct res_rec answers;
113   char *packet_type = "unknown";
114   
115   p = *p1;
116
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";
121   
122   DEBUG(4,("replying netbios packet: %s %s\n",
123            packet_type, namestr(rr_name), inet_ntoa(p.ip)));
124
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;
133   
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;
139   
140   bzero((char*)&nmb->question,sizeof(nmb->question));
141   
142   nmb->answers = &answers;
143   bzero((char*)nmb->answers,sizeof(*nmb->answers));
144   
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;
149   
150   if (data && len)
151     {
152       nmb->answers->rdlength = len;
153       memcpy(nmb->answers->rdata, data, len);
154     }
155   
156   p.packet_type = NMB_PACKET;
157   
158   debug_nmb_packet(&p);
159   
160   send_packet(&p);
161 }
162
163
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)
170 {
171   struct packet_struct p;
172   struct nmb_packet *nmb = &p.packet.nmb;
173   struct res_rec additional_rec;
174   char *packet_type = "unknown";
175   int opcode = -1;
176
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; }
181   
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)));
184
185   if (opcode == -1) return False;
186
187   bzero((char *)&p,sizeof(p));
188
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;
192
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;
206   
207   make_nmb_name(&nmb->question.question_name,name,name_type,scope);
208   
209   nmb->question.question_type = quest_type;
210   nmb->question.question_class = 0x1;
211   
212   if (quest_type == NMB_REG || quest_type == NMB_REL)
213     {
214       nmb->additional = &additional_rec;
215       bzero((char *)nmb->additional,sizeof(*nmb->additional));
216       
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;
220       
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));
225     }
226   
227   p.ip = to_ip;
228   p.port = NMB_PORT;
229   p.fd = fd;
230   p.timestamp = time(NULL);
231   p.packet_type = NMB_PACKET;
232   
233   if (!send_packet(&p)) 
234     return(0);
235   
236   return(name_trn_id);
237 }
238
239
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)
248 {
249   if ((!lp_wins_support()) && (*lp_wins_server()))
250     {
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());
254
255       if (!zero_ip(wins_ip))
256         {
257           bcast = False;
258           to_ip = wins_ip;
259         }
260       else
261         {
262           /* oops. smb.conf's wins server parameter MUST be a host_name 
263              or an ip_address. */
264           DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
265         }
266     }
267
268   if (zero_ip(to_ip)) return;
269
270   queue_netbios_packet(fd, quest_type, cmd, 
271                        name, name_type, nb_flags,
272                        bcast, recurse, to_ip);
273 }
274
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,
280                                                            char *name,int type,
281                                                            BOOL bcast,BOOL recurse,
282                                                            struct in_addr ip)
283 {
284   struct name_response_record *n;
285         
286   if (!name || !name[0]) return NULL;
287         
288   if (!(n = (struct name_response_record *)malloc(sizeof(*n)))) 
289     return(NULL);
290
291   n->response_id = id;
292   n->cmd_type = cmd;
293   n->fd = fd;
294   make_nmb_name(&n->name, name, type, scope);
295   n->bcast = bcast;
296   n->recurse = recurse;
297   n->to_ip = ip;
298   n->start_time = time(NULL);
299   n->num_msgs = 0;
300
301   return n;
302 }
303
304
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)
314 {
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;
318
319   if (id == 0) return;
320   
321   if ((n = 
322        make_name_query_record(cmd,id,fd,name,name_type,bcast,recurse,to_ip)))
323     {
324       add_response_record(n);
325     }
326 }
327
328
329 /****************************************************************************
330   find a response in the name query response list
331   **************************************************************************/
332 struct name_response_record *find_name_query(uint16 id)
333 {   
334   struct name_response_record *n;
335
336   for (n = nameresponselist; n; n = n->next)
337     {
338       if (n->response_id == id) {
339         return n;
340       }
341     }
342
343   return NULL;
344 }
345
346
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;
353
354 /*******************************************************************
355   queue a packet into the packet queue
356   ******************************************************************/
357 void queue_packet(struct packet_struct *packet)
358 {
359   struct packet_struct *p;
360
361   if (!packet_queue) {
362     packet->prev = NULL;
363     packet->next = NULL;
364     packet_queue = packet;
365     return;
366   }
367   
368   /* find the bottom */
369   for (p=packet_queue;p->next;p=p->next) ;
370
371   p->next = packet;
372   packet->next = NULL;
373   packet->prev = p;
374 }
375
376 /*******************************************************************
377   run elements off the packet queue till its empty
378   ******************************************************************/
379 void run_packet_queue()
380 {
381   struct packet_struct *p;
382
383   while ((p=packet_queue))
384     {
385       switch (p->packet_type)
386         {
387         case NMB_PACKET:
388           process_nmb(p);
389           break;
390           
391         case DGRAM_PACKET:
392           process_dgram(p);
393           break;
394         }
395       
396       packet_queue = packet_queue->next;
397       if (packet_queue) packet_queue->prev = NULL;
398       free_packet(p);
399     }
400 }
401
402 /****************************************************************************
403   listens for NMB or DGRAM packets, and queues them
404   ***************************************************************************/
405 void listen_for_packets(BOOL run_election)
406 {
407   fd_set fds;
408   int selrtn;
409   struct timeval timeout;
410
411   FD_ZERO(&fds);
412   FD_SET(ClientNMB,&fds);
413   FD_SET(ClientDGRAM,&fds);
414
415   /* during elections we need to send election packets at one
416      second intervals */
417
418   timeout.tv_sec = run_election ? 1 : NMBD_SELECT_LOOP;
419   timeout.tv_usec = 0;
420
421   selrtn = sys_select(&fds,&timeout);
422
423   if (FD_ISSET(ClientNMB,&fds))
424     {
425       struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
426       if (packet) {
427 #if 1
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));          
432           free_packet(packet);
433         } else 
434 #endif
435           {
436             queue_packet(packet);
437           }
438       }
439     }
440
441   if (FD_ISSET(ClientDGRAM,&fds))
442     {
443       struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
444       if (packet) {
445 #if 1
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));          
450           free_packet(packet);
451         } else
452 #endif 
453           {
454             queue_packet(packet);
455           }
456       }
457     }
458 }
459
460
461
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)
469 {
470   int level = t==0x20 ? 4 : 0;
471   int numnames = CVAL(p,0);
472   BOOL found = False;
473
474   DEBUG(level,("received %d names\n",numnames));
475
476   p += 1;
477
478   if (serv_name) *serv_name = 0;
479
480   while (numnames--)
481     {
482       char qname[17];
483       int type;
484       fstring flags;
485       int nb_flags;
486       
487       BOOL group = False;
488       BOOL add   = False;
489       
490       *flags = 0;
491       
492       StrnCpy(qname,p,15);
493       type = CVAL(p,15);
494       nb_flags = p[16];
495       trim_string(qname,NULL," ");
496       
497       p += 18;
498       
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;}
508       
509       /* might as well update our namelist while we're at it */
510       if (add)
511         {
512           struct in_addr nameip;
513           enum name_source src;
514           
515           if (ismyip(ip)) {
516             nameip = ipzero;
517             src = SELF;
518           } else {
519             nameip = ip;
520             src = STATUS_QUERY;
521           }
522           add_netbios_entry(qname,type,nb_flags,2*60*60,src,nameip,True);
523         } 
524
525       /* we want the server name */
526       if (serv_name && !*serv_name && !group && t == 0)
527         {
528           StrnCpy(serv_name,qname,15);
529           serv_name[15] = 0;
530         }
531       
532       /* looking for a name and type? */
533       if (name && !found && (t == type))
534         {
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))
539             {
540               found = True;
541               make_nmb_name(name,qname,type,scope);
542             }
543         }
544       
545       DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
546     }
547   DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
548                IVAL(p,20),IVAL(p,24)));
549   return found;
550 }
551
552
553 /****************************************************************************
554   construct and send a netbios DGRAM
555
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)
562 {
563   struct packet_struct p;
564   struct dgram_packet *dgram = &p.packet.dgram;
565   char *ptr,*p2;
566   char tmp[4];
567
568   bzero((char *)&p,sizeof(p));
569
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;
579   
580   make_nmb_name(&dgram->source_name,srcname,src_type,scope);
581   make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
582
583   ptr = &dgram->data[0];
584
585   /* now setup the smb part */
586   ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
587   memcpy(tmp,ptr,4);
588   set_message(ptr,17,17 + len,True);
589   memcpy(ptr,tmp,4);
590
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);
599   p2 = smb_buf(ptr);
600   strcpy(p2,mailslot);
601   p2 = skip_string(p2,1);
602
603   memcpy(p2,buf,len);
604   p2 += len;
605
606   dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
607
608   p.ip = dest_ip;
609   p.port = DGRAM_PORT;
610   p.fd = ClientDGRAM;
611   p.timestamp = time(NULL);
612   p.packet_type = DGRAM_PACKET;
613
614   return(send_packet(&p));
615 }
616
617