more changes from Luke
[samba.git] / source3 / 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,
107                           int opcode,BOOL recurse,struct nmb_name *rr_name,
108                           int rr_type,int rr_class,int ttl,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 = recurse;
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 *
279 make_name_query_record(enum cmd_type cmd,int id,int fd,char *name,int type,
280                        BOOL bcast,BOOL recurse,struct in_addr ip)
281 {
282   struct name_response_record *n;
283         
284   if (!name || !name[0]) return NULL;
285         
286   if (!(n = (struct name_response_record *)malloc(sizeof(*n)))) 
287     return(NULL);
288
289   n->response_id = id;
290   n->cmd_type = cmd;
291   n->fd = fd;
292   make_nmb_name(&n->name, name, type, scope);
293   n->bcast = bcast;
294   n->recurse = recurse;
295   n->to_ip = ip;
296   n->start_time = time(NULL);
297   n->num_msgs = 0;
298
299   return n;
300 }
301
302
303 /****************************************************************************
304   initiate a netbios name query to find someone's or someones' IP
305   this is intended to be used (not exclusively) for broadcasting to
306   master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
307   complete lists across a wide area network
308   ****************************************************************************/
309 void queue_netbios_packet(int fd,int quest_type,enum cmd_type cmd,char *name,
310                           int name_type,int nb_flags,BOOL bcast,BOOL recurse,
311                           struct in_addr to_ip)
312 {
313   uint16 id = initiate_netbios_packet(fd, quest_type, name, name_type,
314                                       nb_flags, bcast, recurse, to_ip);
315   struct name_response_record *n;
316
317   if (id == 0) return;
318   
319   if ((n = 
320        make_name_query_record(cmd,id,fd,name,name_type,bcast,recurse,to_ip)))
321     {
322       add_response_record(n);
323     }
324 }
325
326
327 /****************************************************************************
328   find a response in the name query response list
329   **************************************************************************/
330 struct name_response_record *find_name_query(uint16 id)
331 {   
332   struct name_response_record *n;
333
334   for (n = nameresponselist; n; n = n->next)
335     {
336       if (n->response_id == id) {
337         return n;
338       }
339     }
340
341   return NULL;
342 }
343
344
345 /*******************************************************************
346   the global packet linked-list. incoming entries are added to the
347   end of this list.  it is supposed to remain fairly short so we
348   won't bother with an end pointer.
349   ******************************************************************/
350 static struct packet_struct *packet_queue = NULL;
351
352 /*******************************************************************
353   queue a packet into the packet queue
354   ******************************************************************/
355 void queue_packet(struct packet_struct *packet)
356 {
357   struct packet_struct *p;
358
359   if (!packet_queue) {
360     packet->prev = NULL;
361     packet->next = NULL;
362     packet_queue = packet;
363     return;
364   }
365   
366   /* find the bottom */
367   for (p=packet_queue;p->next;p=p->next) ;
368
369   p->next = packet;
370   packet->next = NULL;
371   packet->prev = p;
372 }
373
374 /*******************************************************************
375   run elements off the packet queue till its empty
376   ******************************************************************/
377 void run_packet_queue()
378 {
379   struct packet_struct *p;
380
381   while ((p=packet_queue))
382     {
383       switch (p->packet_type)
384         {
385         case NMB_PACKET:
386           process_nmb(p);
387           break;
388           
389         case DGRAM_PACKET:
390           process_dgram(p);
391           break;
392         }
393       
394       packet_queue = packet_queue->next;
395       if (packet_queue) packet_queue->prev = NULL;
396       free_packet(p);
397     }
398 }
399
400 /****************************************************************************
401   listens for NMB or DGRAM packets, and queues them
402   ***************************************************************************/
403 void listen_for_packets(BOOL run_election)
404 {
405   fd_set fds;
406   int selrtn;
407   struct timeval timeout;
408
409   FD_ZERO(&fds);
410   FD_SET(ClientNMB,&fds);
411   FD_SET(ClientDGRAM,&fds);
412
413   /* during elections we need to send election packets at one
414      second intervals */
415
416   timeout.tv_sec = run_election ? 1 : NMBD_SELECT_LOOP;
417   timeout.tv_usec = 0;
418
419   selrtn = sys_select(&fds,&timeout);
420
421   if (FD_ISSET(ClientNMB,&fds))
422     {
423       struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
424       if (packet) {
425 #if 1
426         if (ismyip(packet->ip) &&
427             (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
428           DEBUG(5,("discarding own packet from %s:%d\n",
429                    inet_ntoa(packet->ip),packet->port));          
430           free_packet(packet);
431         } else 
432 #endif
433           {
434             queue_packet(packet);
435           }
436       }
437     }
438
439   if (FD_ISSET(ClientDGRAM,&fds))
440     {
441       struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
442       if (packet) {
443 #if 1
444         if (ismyip(packet->ip) &&
445               (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
446           DEBUG(5,("discarding own packet from %s:%d\n",
447                    inet_ntoa(packet->ip),packet->port));          
448           free_packet(packet);
449         } else
450 #endif 
451           {
452             queue_packet(packet);
453           }
454       }
455     }
456 }
457
458
459
460 /****************************************************************************
461 interpret a node status response. this is pretty hacked: we need two bits of
462 info. a) the name of the workgroup b) the name of the server. it will also
463 add all the names it finds into the namelist.
464 ****************************************************************************/
465 BOOL interpret_node_status(char *p, struct nmb_name *name,int t,
466                            char *serv_name, struct in_addr ip)
467 {
468   int level = t==0x20 ? 4 : 0;
469   int numnames = CVAL(p,0);
470   BOOL found = False;
471
472   DEBUG(level,("received %d names\n",numnames));
473
474   p += 1;
475
476   if (serv_name) *serv_name = 0;
477
478   while (numnames--)
479     {
480       char qname[17];
481       int type;
482       fstring flags;
483       int nb_flags;
484       
485       BOOL group = False;
486       BOOL add   = False;
487       
488       *flags = 0;
489       
490       StrnCpy(qname,p,15);
491       type = CVAL(p,15);
492       nb_flags = p[16];
493       trim_string(qname,NULL," ");
494       
495       p += 18;
496       
497       if (NAME_GROUP    (nb_flags)) { strcat(flags,"<GROUP> "); group=True;}
498       if (NAME_BFLAG    (nb_flags)) { strcat(flags,"B "); }
499       if (NAME_PFLAG    (nb_flags)) { strcat(flags,"P "); }
500       if (NAME_MFLAG    (nb_flags)) { strcat(flags,"M "); }
501       if (NAME__FLAG    (nb_flags)) { strcat(flags,"_ "); }
502       if (NAME_DEREG    (nb_flags)) { strcat(flags,"<DEREGISTERING> "); }
503       if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); add=True;}
504       if (NAME_ACTIVE   (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; }
505       if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;}
506       
507       /* might as well update our namelist while we're at it */
508       if (add)
509         {
510           struct in_addr nameip;
511           enum name_source src;
512           
513           if (ismyip(ip)) {
514             nameip = ipzero;
515             src = SELF;
516           } else {
517             nameip = ip;
518             src = STATUS_QUERY;
519           }
520           add_netbios_entry(qname,type,nb_flags,2*60*60,src,nameip,True);
521         } 
522
523       /* we want the server name */
524       if (serv_name && !*serv_name && !group && t == 0)
525         {
526           StrnCpy(serv_name,qname,15);
527           serv_name[15] = 0;
528         }
529       
530       /* looking for a name and type? */
531       if (name && !found && (t == type))
532         {
533           /* take a guess at some of the name types we're going to ask for.
534              evaluate whether they are group names or no... */
535           if (((t == 0x1b || t == 0x1d             ) && !group) ||
536               ((t == 0x20 || t == 0x1c || t == 0x1e) &&  group))
537             {
538               found = True;
539               make_nmb_name(name,qname,type,scope);
540             }
541         }
542       
543       DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
544     }
545   DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
546                IVAL(p,20),IVAL(p,24)));
547   return found;
548 }
549
550
551 /****************************************************************************
552   construct and send a netbios DGRAM
553
554   Note that this currently sends all answers to port 138. thats the
555   wrong things to do! I should send to the requestors port. XXX
556   **************************************************************************/
557 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
558                          char *dstname,int src_type,int dest_type,
559                          struct in_addr dest_ip,struct in_addr src_ip)
560 {
561   struct packet_struct p;
562   struct dgram_packet *dgram = &p.packet.dgram;
563   char *ptr,*p2;
564   char tmp[4];
565
566   bzero((char *)&p,sizeof(p));
567
568   dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
569   dgram->header.flags.node_type = M_NODE;
570   dgram->header.flags.first = True;
571   dgram->header.flags.more = False;
572   dgram->header.dgm_id = name_trn_id++;
573   dgram->header.source_ip = src_ip;
574   dgram->header.source_port = DGRAM_PORT;
575   dgram->header.dgm_length = 0; /* let build_dgram() handle this */
576   dgram->header.packet_offset = 0;
577   
578   make_nmb_name(&dgram->source_name,srcname,src_type,scope);
579   make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
580
581   ptr = &dgram->data[0];
582
583   /* now setup the smb part */
584   ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
585   memcpy(tmp,ptr,4);
586   set_message(ptr,17,17 + len,True);
587   memcpy(ptr,tmp,4);
588
589   CVAL(ptr,smb_com) = SMBtrans;
590   SSVAL(ptr,smb_vwv1,len);
591   SSVAL(ptr,smb_vwv11,len);
592   SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
593   SSVAL(ptr,smb_vwv13,3);
594   SSVAL(ptr,smb_vwv14,1);
595   SSVAL(ptr,smb_vwv15,1);
596   SSVAL(ptr,smb_vwv16,2);
597   p2 = smb_buf(ptr);
598   strcpy(p2,mailslot);
599   p2 = skip_string(p2,1);
600
601   memcpy(p2,buf,len);
602   p2 += len;
603
604   dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
605
606   p.ip = dest_ip;
607   p.port = DGRAM_PORT;
608   p.fd = ClientDGRAM;
609   p.timestamp = time(NULL);
610   p.packet_type = DGRAM_PACKET;
611
612   return(send_packet(&p));
613 }
614
615