Basic doc changes to keep up to date.
[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
25 extern int ClientNMB;
26 extern int ClientDGRAM;
27
28 /* this is our initiated name query response database */
29 struct name_response_record *nameresponselist = NULL;
30
31 extern int DEBUGLEVEL;
32
33 static uint16 name_trn_id=0;
34 BOOL CanRecurse = True;
35 extern pstring scope;
36 extern pstring myname;
37 extern struct in_addr ipzero;
38
39
40 /***************************************************************************
41   add an initated name query  into the list
42   **************************************************************************/
43 extern void add_response_record(struct name_response_record *n)
44 {
45   struct name_response_record *n2;
46
47   if (!nameresponselist)
48     {
49       nameresponselist = n;
50       n->prev = NULL;
51       n->next = NULL;
52       return;
53     }
54   
55   for (n2 = nameresponselist; n2->next; n2 = n2->next) ;
56   
57   n2->next = n;
58   n->next = NULL;
59   n->prev = n2;
60 }
61
62
63 /*******************************************************************
64   remove old name response entries
65   ******************************************************************/
66 void expire_netbios_response_entries(time_t t)
67 {
68   struct name_response_record *n;
69   struct name_response_record *nextn;
70
71   for (n = nameresponselist; n; n = nextn)
72     {
73       if (n->start_time < t)
74         {
75           DEBUG(3,("Removing dead name query for %s %s (num_msgs=%d)\n",
76                    inet_ntoa(n->to_ip), namestr(&n->name), n->num_msgs));
77
78           if (n->cmd_type == CHECK_MASTER)
79             {
80               /* if no response received, the master browser must have gone */
81               if (n->num_msgs == 0)
82                 browser_gone(n->name.name, n->to_ip);
83             }
84           
85           nextn = n->next;
86           
87           if (n->prev) n->prev->next = n->next;
88           if (n->next) n->next->prev = n->prev;
89           
90           if (nameresponselist == n) nameresponselist = n->next; 
91           
92           free(n);
93         }
94       else
95         {
96           nextn = n->next;
97         }
98     }
99 }
100
101
102 /****************************************************************************
103   reply to a netbios name packet 
104   ****************************************************************************/
105 void reply_netbios_packet(struct packet_struct *p1,int trn_id,int rcode,
106                           int opcode,BOOL recurse,struct nmb_name *rr_name,
107                           int rr_type,int rr_class,int ttl,char *data,int len)
108 {
109   struct packet_struct p;
110   struct nmb_packet *nmb = &p.packet.nmb;
111   struct res_rec answers;
112   char *packet_type = "unknown";
113   
114   p = *p1;
115
116   if (rr_type == NMB_STATUS) packet_type = "nmb_status";
117   if (rr_type == NMB_QUERY ) packet_type = "nmb_query";
118   if (rr_type == NMB_REG   ) packet_type = "nmb_reg";
119   if (rr_type == NMB_REL   ) packet_type = "nmb_rel";
120   
121   DEBUG(4,("replying netbios packet: %s %s\n",
122            packet_type, namestr(rr_name), inet_ntoa(p.ip)));
123
124   nmb->header.name_trn_id = trn_id;
125   nmb->header.opcode = opcode;
126   nmb->header.response = True;
127   nmb->header.nm_flags.bcast = False;
128   nmb->header.nm_flags.recursion_available = recurse;
129   nmb->header.nm_flags.recursion_desired = True;
130   nmb->header.nm_flags.trunc = False;
131   nmb->header.nm_flags.authoritative = True;
132   
133   nmb->header.qdcount = 0;
134   nmb->header.ancount = 1;
135   nmb->header.nscount = 0;
136   nmb->header.arcount = 0;
137   nmb->header.rcode = 0;
138   
139   bzero((char*)&nmb->question,sizeof(nmb->question));
140   
141   nmb->answers = &answers;
142   bzero((char*)nmb->answers,sizeof(*nmb->answers));
143   
144   nmb->answers->rr_name  = *rr_name;
145   nmb->answers->rr_type  = rr_type;
146   nmb->answers->rr_class = rr_class;
147   nmb->answers->ttl      = ttl;
148   
149   if (data && len)
150     {
151       nmb->answers->rdlength = len;
152       memcpy(nmb->answers->rdata, data, len);
153     }
154   
155   p.packet_type = NMB_PACKET;
156   
157   debug_nmb_packet(&p);
158   
159   send_packet(&p);
160 }
161
162
163 /****************************************************************************
164   initiate a netbios packet
165   ****************************************************************************/
166 uint16 initiate_netbios_packet(int fd,int quest_type,char *name,int name_type,
167                                int nb_flags,BOOL bcast,BOOL recurse,
168                                struct in_addr to_ip)
169 {
170   struct packet_struct p;
171   struct nmb_packet *nmb = &p.packet.nmb;
172   struct res_rec additional_rec;
173   char *packet_type = "unknown";
174   int opcode = -1;
175
176   if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; }
177   if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; }
178   if (quest_type == NMB_REG   ) { packet_type = "nmb_reg"; opcode = 5; }
179   if (quest_type == NMB_REL   ) { packet_type = "nmb_rel"; opcode = 6; }
180   
181   DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
182            packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
183
184   if (opcode == -1) return False;
185
186   bzero((char *)&p,sizeof(p));
187
188   if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + 
189     (getpid()%(unsigned)100);
190   name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
191
192   nmb->header.name_trn_id = name_trn_id;
193   nmb->header.opcode = opcode;
194   nmb->header.response = False;
195   nmb->header.nm_flags.bcast = bcast;
196   nmb->header.nm_flags.recursion_available = CanRecurse;
197   nmb->header.nm_flags.recursion_desired = recurse;
198   nmb->header.nm_flags.trunc = False;
199   nmb->header.nm_flags.authoritative = False;
200   nmb->header.rcode = 0;
201   nmb->header.qdcount = 1;
202   nmb->header.ancount = 0;
203   nmb->header.nscount = 0;
204   nmb->header.arcount = (quest_type==NMB_REG || quest_type==NMB_REL) ? 1 : 0;
205   
206   make_nmb_name(&nmb->question.question_name,name,name_type,scope);
207   
208   nmb->question.question_type = quest_type;
209   nmb->question.question_class = 0x1;
210   
211   if (quest_type == NMB_REG || quest_type == NMB_REL)
212     {
213       nmb->additional = &additional_rec;
214       bzero((char *)nmb->additional,sizeof(*nmb->additional));
215       
216       nmb->additional->rr_name  = nmb->question.question_name;
217       nmb->additional->rr_type  = nmb->question.question_type;
218       nmb->additional->rr_class = nmb->question.question_class;
219       
220       nmb->additional->ttl = quest_type == NMB_REG ? lp_max_ttl() : 0;
221       nmb->additional->rdlength = 6;
222       nmb->additional->rdata[0] = nb_flags;
223       putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
224     }
225   
226   p.ip = to_ip;
227   p.port = NMB_PORT;
228   p.fd = fd;
229   p.timestamp = time(NULL);
230   p.packet_type = NMB_PACKET;
231   
232   if (!send_packet(&p)) 
233     return(0);
234   
235   return(name_trn_id);
236 }
237
238
239 /****************************************************************************
240   wrapper function to override a broadcast message and send it to the WINS
241   name server instead, if it exists. if wins is false, and there has been no
242   WINS server specified, the packet will NOT be sent.
243   ****************************************************************************/
244 void queue_netbios_pkt_wins(int fd,int quest_type,enum cmd_type cmd,
245                             char *name,int name_type,int nb_flags,
246                             BOOL bcast,BOOL recurse,struct in_addr to_ip)
247 {
248   if ((!lp_wins_support()) && (*lp_wins_server()))
249     {
250       /* samba is not a WINS server, and we are using a WINS server */
251       struct in_addr wins_ip;
252       wins_ip = *interpret_addr2(lp_wins_server());
253
254       if (!zero_ip(wins_ip))
255         {
256           bcast = False;
257           to_ip = wins_ip;
258         }
259       else
260         {
261           /* oops. smb.conf's wins server parameter MUST be a host_name 
262              or an ip_address. */
263           DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
264         }
265     }
266
267   if (zero_ip(to_ip)) return;
268
269   queue_netbios_packet(fd, quest_type, cmd, 
270                        name, name_type, nb_flags,
271                        bcast, recurse, to_ip);
272 }
273
274 /****************************************************************************
275   create a name query response record
276   **************************************************************************/
277 static struct name_response_record *
278 make_name_query_record(enum cmd_type cmd,int id,int fd,char *name,int type,
279                        BOOL bcast,BOOL recurse,struct in_addr ip)
280 {
281   struct name_response_record *n;
282         
283   if (!name || !name[0]) return NULL;
284         
285   if (!(n = (struct name_response_record *)malloc(sizeof(*n)))) 
286     return(NULL);
287
288   n->response_id = id;
289   n->cmd_type = cmd;
290   n->fd = fd;
291   make_nmb_name(&n->name, name, type, scope);
292   n->bcast = bcast;
293   n->recurse = recurse;
294   n->to_ip = ip;
295   n->start_time = time(NULL);
296   n->num_msgs = 0;
297
298   return n;
299 }
300
301
302 /****************************************************************************
303   initiate a netbios name query to find someone's or someones' IP
304   this is intended to be used (not exclusively) for broadcasting to
305   master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
306   complete lists across a wide area network
307   ****************************************************************************/
308 void queue_netbios_packet(int fd,int quest_type,enum cmd_type cmd,char *name,
309                           int name_type,int nb_flags,BOOL bcast,BOOL recurse,
310                           struct in_addr to_ip)
311 {
312   uint16 id = initiate_netbios_packet(fd, quest_type, name, name_type,
313                                       nb_flags, bcast, recurse, to_ip);
314   struct name_response_record *n;
315
316   if (id == 0) return;
317   
318   if ((n = 
319        make_name_query_record(cmd,id,fd,name,name_type,bcast,recurse,to_ip)))
320     {
321       add_response_record(n);
322     }
323 }
324
325
326 /****************************************************************************
327   find a response in the name query response list
328   **************************************************************************/
329 struct name_response_record *find_name_query(uint16 id)
330 {   
331   struct name_response_record *n;
332
333   for (n = nameresponselist; n; n = n->next)
334     {
335       if (n->response_id == id) {
336         return n;
337       }
338     }
339
340   return NULL;
341 }
342
343
344 /*******************************************************************
345   the global packet linked-list. incoming entries are added to the
346   end of this list.  it is supposed to remain fairly short so we
347   won't bother with an end pointer.
348   ******************************************************************/
349 static struct packet_struct *packet_queue = NULL;
350
351 /*******************************************************************
352   queue a packet into the packet queue
353   ******************************************************************/
354 void queue_packet(struct packet_struct *packet)
355 {
356   struct packet_struct *p;
357
358   if (!packet_queue) {
359     packet->prev = NULL;
360     packet->next = NULL;
361     packet_queue = packet;
362     return;
363   }
364   
365   /* find the bottom */
366   for (p=packet_queue;p->next;p=p->next) ;
367
368   p->next = packet;
369   packet->next = NULL;
370   packet->prev = p;
371 }
372
373 /*******************************************************************
374   run elements off the packet queue till its empty
375   ******************************************************************/
376 void run_packet_queue()
377 {
378   struct packet_struct *p;
379
380   while ((p=packet_queue))
381     {
382       switch (p->packet_type)
383         {
384         case NMB_PACKET:
385           process_nmb(p);
386           break;
387           
388         case DGRAM_PACKET:
389           process_dgram(p);
390           break;
391         }
392       
393       packet_queue = packet_queue->next;
394       if (packet_queue) packet_queue->prev = NULL;
395       free_packet(p);
396     }
397 }
398
399 /****************************************************************************
400   listens for NMB or DGRAM packets, and queues them
401   ***************************************************************************/
402 void listen_for_packets(BOOL run_election)
403 {
404   fd_set fds;
405   int selrtn;
406   struct timeval timeout;
407
408   FD_ZERO(&fds);
409   FD_SET(ClientNMB,&fds);
410   FD_SET(ClientDGRAM,&fds);
411
412   /* during elections we need to send election packets at one
413      second intervals */
414
415   timeout.tv_sec = run_election ? 1 : NMBD_SELECT_LOOP;
416   timeout.tv_usec = 0;
417
418   selrtn = sys_select(&fds,&timeout);
419
420   if (FD_ISSET(ClientNMB,&fds))
421     {
422       struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
423       if (packet) {
424 #if 1
425         if (ismyip(packet->ip) &&
426             (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
427           DEBUG(5,("discarding own packet from %s:%d\n",
428                    inet_ntoa(packet->ip),packet->port));          
429           free_packet(packet);
430         } else 
431 #endif
432           {
433             queue_packet(packet);
434           }
435       }
436     }
437
438   if (FD_ISSET(ClientDGRAM,&fds))
439     {
440       struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
441       if (packet) {
442 #if 1
443         if (ismyip(packet->ip) &&
444               (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
445           DEBUG(5,("discarding own packet from %s:%d\n",
446                    inet_ntoa(packet->ip),packet->port));          
447           free_packet(packet);
448         } else
449 #endif 
450           {
451             queue_packet(packet);
452           }
453       }
454     }
455 }
456
457
458
459 /****************************************************************************
460 interpret a node status response. this is pretty hacked: we need two bits of
461 info. a) the name of the workgroup b) the name of the server. it will also
462 add all the names it finds into the namelist.
463 ****************************************************************************/
464 BOOL interpret_node_status(char *p, struct nmb_name *name,int t,
465                            char *serv_name, struct in_addr ip)
466 {
467   int level = t==0x20 ? 4 : 0;
468   int numnames = CVAL(p,0);
469   BOOL found = False;
470
471   DEBUG(level,("received %d names\n",numnames));
472
473   p += 1;
474
475   if (serv_name) *serv_name = 0;
476
477   while (numnames--)
478     {
479       char qname[17];
480       int type;
481       fstring flags;
482       int nb_flags;
483       
484       BOOL group = False;
485       BOOL add   = False;
486       
487       *flags = 0;
488       
489       StrnCpy(qname,p,15);
490       type = CVAL(p,15);
491       nb_flags = p[16];
492       trim_string(qname,NULL," ");
493       
494       p += 18;
495       
496       if (NAME_GROUP    (nb_flags)) { strcat(flags,"<GROUP> "); group=True;}
497       if (NAME_BFLAG    (nb_flags)) { strcat(flags,"B "); }
498       if (NAME_PFLAG    (nb_flags)) { strcat(flags,"P "); }
499       if (NAME_MFLAG    (nb_flags)) { strcat(flags,"M "); }
500       if (NAME__FLAG    (nb_flags)) { strcat(flags,"_ "); }
501       if (NAME_DEREG    (nb_flags)) { strcat(flags,"<DEREGISTERING> "); }
502       if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); add=True;}
503       if (NAME_ACTIVE   (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; }
504       if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;}
505       
506       /* might as well update our namelist while we're at it */
507       if (add)
508         {
509           struct in_addr nameip;
510           enum name_source src;
511           
512           if (ismyip(ip)) {
513             nameip = ipzero;
514             src = SELF;
515           } else {
516             nameip = ip;
517             src = STATUS_QUERY;
518           }
519           add_netbios_entry(qname,type,nb_flags,2*60*60,src,nameip,True);
520         } 
521
522       /* we want the server name */
523       if (serv_name && !*serv_name && !group && t == 0)
524         {
525           StrnCpy(serv_name,qname,15);
526           serv_name[15] = 0;
527         }
528       
529       /* looking for a name and type? */
530       if (name && !found && (t == type))
531         {
532           /* take a guess at some of the name types we're going to ask for.
533              evaluate whether they are group names or no... */
534           if (((t == 0x1b || t == 0x1d             ) && !group) ||
535               ((t == 0x20 || t == 0x1c || t == 0x1e) &&  group))
536             {
537               found = True;
538               make_nmb_name(name,qname,type,scope);
539             }
540         }
541       
542       DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
543     }
544   DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
545                IVAL(p,20),IVAL(p,24)));
546   return found;
547 }
548
549
550 /****************************************************************************
551   construct and send a netbios DGRAM
552
553   Note that this currently sends all answers to port 138. thats the
554   wrong things to do! I should send to the requestors port. XXX
555   **************************************************************************/
556 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
557                          char *dstname,int src_type,int dest_type,
558                          struct in_addr dest_ip,struct in_addr src_ip)
559 {
560   struct packet_struct p;
561   struct dgram_packet *dgram = &p.packet.dgram;
562   char *ptr,*p2;
563   char tmp[4];
564
565   bzero((char *)&p,sizeof(p));
566
567   dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
568   dgram->header.flags.node_type = M_NODE;
569   dgram->header.flags.first = True;
570   dgram->header.flags.more = False;
571   dgram->header.dgm_id = name_trn_id++;
572   dgram->header.source_ip = src_ip;
573   dgram->header.source_port = DGRAM_PORT;
574   dgram->header.dgm_length = 0; /* let build_dgram() handle this */
575   dgram->header.packet_offset = 0;
576   
577   make_nmb_name(&dgram->source_name,srcname,src_type,scope);
578   make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
579
580   ptr = &dgram->data[0];
581
582   /* now setup the smb part */
583   ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
584   memcpy(tmp,ptr,4);
585   set_message(ptr,17,17 + len,True);
586   memcpy(ptr,tmp,4);
587
588   CVAL(ptr,smb_com) = SMBtrans;
589   SSVAL(ptr,smb_vwv1,len);
590   SSVAL(ptr,smb_vwv11,len);
591   SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
592   SSVAL(ptr,smb_vwv13,3);
593   SSVAL(ptr,smb_vwv14,1);
594   SSVAL(ptr,smb_vwv15,1);
595   SSVAL(ptr,smb_vwv16,2);
596   p2 = smb_buf(ptr);
597   strcpy(p2,mailslot);
598   p2 = skip_string(p2,1);
599
600   memcpy(p2,buf,len);
601   p2 += len;
602
603   dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
604
605   p.ip = dest_ip;
606   p.port = DGRAM_PORT;
607   p.fd = ClientDGRAM;
608   p.timestamp = time(NULL);
609   p.packet_type = DGRAM_PACKET;
610
611   return(send_packet(&p));
612 }
613
614