- sequent-ptx support from bressler@iftccu.ca.boeing.com (Rick
[samba.git] / source / namepacket.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines and daemon - version 2
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    Revision History:
22
23    14 jan 96: lkcl@pires.co.uk
24    added multiple workgroup domain master support
25
26 */
27
28 #include "includes.h"
29
30 extern int ClientNMB;
31 extern int ClientDGRAM;
32
33 extern int DEBUGLEVEL;
34
35 extern int num_response_packets;
36
37 BOOL CanRecurse = True;
38 extern pstring scope;
39 extern struct in_addr ipgrp;
40
41 static uint16 name_trn_id=0;
42
43
44 /***************************************************************************
45   updates the unique transaction identifier
46   **************************************************************************/
47 void debug_browse_data(char *outbuf, int len)
48 {
49     int i,j;
50     for (i = 0; i < len; i+= 16)
51       {
52         DEBUG(4, ("%3x char ", i));
53         
54         for (j = 0; j < 16; j++)
55           {
56             unsigned char x = outbuf[i+j];
57             if (x < 32 || x > 127) x = '.';
58             
59             if (i+j >= len) break;
60             DEBUG(4, ("%c", x));
61           }
62         
63         DEBUG(4, (" hex ", i));
64         
65         for (j = 0; j < 16; j++)
66           {
67             if (i+j >= len) break;
68             DEBUG(4, (" %02x", outbuf[i+j]));
69           }
70         
71         DEBUG(4, ("\n"));
72       }
73     
74 }
75
76
77 /***************************************************************************
78   updates the unique transaction identifier
79   **************************************************************************/
80 static void update_name_trn_id(void)
81 {
82   if (!name_trn_id)
83   {
84     name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
85   }
86   name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
87 }
88
89
90 /****************************************************************************
91   initiate a netbios packet
92   ****************************************************************************/
93 void initiate_netbios_packet(uint16 *id,
94                                 int fd,int quest_type,char *name,int name_type,
95                             int nb_flags,BOOL bcast,BOOL recurse,
96                             struct in_addr to_ip)
97 {
98   struct packet_struct p;
99   struct nmb_packet *nmb = &p.packet.nmb;
100   struct res_rec additional_rec;
101   char *packet_type = "unknown";
102   int opcode = -1;
103
104   if (!id) return;
105
106   if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; }
107   if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; }
108   if (quest_type == NMB_REG   ) { packet_type = "nmb_reg"; opcode = 5; }
109   if (quest_type == NMB_REL   ) { packet_type = "nmb_rel"; opcode = 6; }
110   
111   DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
112            packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
113
114   if (opcode == -1) return;
115
116   bzero((char *)&p,sizeof(p));
117
118   if (*id == 0xffff) {
119     update_name_trn_id();
120     *id = name_trn_id; /* allow resending with same id */
121   }
122
123   nmb->header.name_trn_id = *id;
124   nmb->header.opcode = opcode;
125   nmb->header.response = False;
126
127   nmb->header.nm_flags.bcast = bcast;
128   nmb->header.nm_flags.recursion_available = False;
129   nmb->header.nm_flags.recursion_desired = recurse;
130   nmb->header.nm_flags.trunc = False;
131   nmb->header.nm_flags.authoritative = False;
132
133   nmb->header.rcode = 0;
134   nmb->header.qdcount = 1;
135   nmb->header.ancount = 0;
136   nmb->header.nscount = 0;
137   nmb->header.arcount = (quest_type==NMB_REG || quest_type==NMB_REL) ? 1 : 0;
138   
139   make_nmb_name(&nmb->question.question_name,name,name_type,scope);
140   
141   nmb->question.question_type = quest_type;
142   nmb->question.question_class = 0x1;
143   
144   if (quest_type == NMB_REG || quest_type == NMB_REL)
145     {
146       nmb->additional = &additional_rec;
147       bzero((char *)nmb->additional,sizeof(*nmb->additional));
148       
149       nmb->additional->rr_name  = nmb->question.question_name;
150       nmb->additional->rr_type  = nmb->question.question_type;
151       nmb->additional->rr_class = nmb->question.question_class;
152       
153       nmb->additional->ttl = quest_type == NMB_REG ? lp_max_ttl() : 0;
154       nmb->additional->rdlength = 6;
155       nmb->additional->rdata[0] = nb_flags;
156       putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
157     }
158   
159   p.ip = to_ip;
160   p.port = NMB_PORT;
161   p.fd = fd;
162   p.timestamp = time(NULL);
163   p.packet_type = NMB_PACKET;
164   
165   if (!send_packet(&p)) *id = 0xffff;
166   
167   return;
168 }
169
170
171 /****************************************************************************
172   reply to a netbios name packet 
173   ****************************************************************************/
174 void reply_netbios_packet(struct packet_struct *p1,int trn_id,
175                                 int rcode, int rcv_code, int opcode, BOOL recurse,
176                                 struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
177                                 char *data,int len)
178 {
179   struct packet_struct p;
180   struct nmb_packet *nmb = &p.packet.nmb;
181   struct res_rec answers;
182   char *packet_type = "unknown";
183   BOOL recursion_desired = False;
184   
185   p = *p1;
186
187   switch (rcv_code)
188   {
189     case NMB_STATUS:
190         {
191       packet_type = "nmb_status";
192       recursion_desired = True;
193       break;
194     }
195     case NMB_QUERY:
196         {
197       packet_type = "nmb_query";
198       recursion_desired = True;
199       break;
200     }
201     case NMB_REG:
202         {
203       packet_type = "nmb_reg";
204       recursion_desired = True;
205       break;
206     }
207     case NMB_REL:
208         {
209       packet_type = "nmb_rel";
210       recursion_desired = False;
211       break;
212     }
213     case NMB_WAIT_ACK:
214         {
215       packet_type = "nmb_wack";
216       recursion_desired = False;
217       break;
218     }
219     default:
220     {
221       DEBUG(1,("replying netbios packet: %s %s\n",
222                     packet_type, namestr(rr_name), inet_ntoa(p.ip)));
223
224       return;
225     }
226   }
227
228   DEBUG(4,("replying netbios packet: %s %s\n",
229            packet_type, namestr(rr_name), inet_ntoa(p.ip)));
230
231   nmb->header.name_trn_id = trn_id;
232   nmb->header.opcode = opcode;
233   nmb->header.response = True;
234   nmb->header.nm_flags.bcast = False;
235   nmb->header.nm_flags.recursion_available = recurse;
236   nmb->header.nm_flags.recursion_desired = recursion_desired;
237   nmb->header.nm_flags.trunc = False;
238   nmb->header.nm_flags.authoritative = True;
239   
240   nmb->header.qdcount = 0;
241   nmb->header.ancount = 1;
242   nmb->header.nscount = 0;
243   nmb->header.arcount = 0;
244   nmb->header.rcode = 0;
245   
246   bzero((char*)&nmb->question,sizeof(nmb->question));
247   
248   nmb->answers = &answers;
249   bzero((char*)nmb->answers,sizeof(*nmb->answers));
250   
251   nmb->answers->rr_name  = *rr_name;
252   nmb->answers->rr_type  = rr_type;
253   nmb->answers->rr_class = rr_class;
254   nmb->answers->ttl      = ttl;
255   
256   if (data && len)
257     {
258       nmb->answers->rdlength = len;
259       memcpy(nmb->answers->rdata, data, len);
260     }
261   
262   p.packet_type = NMB_PACKET;
263   
264   debug_nmb_packet(&p);
265   
266   send_packet(&p);
267 }
268
269
270 /*******************************************************************
271   the global packet linked-list. incoming entries are added to the
272   end of this list.  it is supposed to remain fairly short so we
273   won't bother with an end pointer.
274   ******************************************************************/
275 static struct packet_struct *packet_queue = NULL;
276
277 /*******************************************************************
278   queue a packet into the packet queue
279   ******************************************************************/
280 void queue_packet(struct packet_struct *packet)
281 {
282   struct packet_struct *p;
283
284   if (!packet_queue) {
285     packet->prev = NULL;
286     packet->next = NULL;
287     packet_queue = packet;
288     return;
289   }
290   
291   /* find the bottom */
292   for (p=packet_queue;p->next;p=p->next) ;
293
294   p->next = packet;
295   packet->next = NULL;
296   packet->prev = p;
297 }
298
299
300 /****************************************************************************
301   process udp 138 datagrams
302   ****************************************************************************/
303 static void process_dgram(struct packet_struct *p)
304 {
305   char *buf;
306   char *buf2;
307   int len;
308   struct dgram_packet *dgram = &p->packet.dgram;
309
310   if (dgram->header.msg_type != 0x10 &&
311       dgram->header.msg_type != 0x11 &&
312       dgram->header.msg_type != 0x12) {
313     /* don't process error packets etc yet */
314     return;
315   }
316
317   buf = &dgram->data[0];
318   buf -= 4; /* XXXX for the pseudo tcp length - 
319                someday I need to get rid of this */
320
321   if (CVAL(buf,smb_com) != SMBtrans) return;
322
323   len = SVAL(buf,smb_vwv11);
324   buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
325
326   DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
327            namestr(&dgram->source_name),namestr(&dgram->dest_name),
328            smb_buf(buf),CVAL(buf2,0),len));
329
330  
331   if (len <= 0) return;
332
333    /* datagram packet received for the browser mailslot */
334    if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) {
335      process_browse_packet(p,buf2,len);
336      return;
337    }
338
339    /* datagram packet received for the domain log on mailslot */
340    if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) {
341      process_logon_packet(p,buf2,len);
342      return;
343    }
344 }
345
346 /****************************************************************************
347   process a nmb packet
348   ****************************************************************************/
349 static void process_nmb(struct packet_struct *p)
350 {
351   struct nmb_packet *nmb = &p->packet.nmb;
352
353   debug_nmb_packet(p);
354
355   switch (nmb->header.opcode) 
356   {
357     case 8: /* what is this?? */
358     case NMB_REG:
359     case NMB_REG_REFRESH:
360     {
361         if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
362         if (nmb->header.response)
363           response_netbios_packet(p); /* response to registration dealt with here */
364         else
365           reply_name_reg(p);
366         break;
367     }
368       
369     case 0:
370     {
371           if (nmb->header.response)
372           {
373             switch (nmb->question.question_type)
374               {
375               case 0x0:
376                 {
377                   response_netbios_packet(p);
378                   break;
379                 }
380               }
381             return;
382           }
383       else if (nmb->header.qdcount>0) 
384           {
385             switch (nmb->question.question_type)
386               {
387               case NMB_QUERY:
388                 {
389                   reply_name_query(p);
390                   break;
391                 }
392               case NMB_STATUS:
393                 {
394                   reply_name_status(p);
395                   break;
396                 }
397               }
398             return;
399           }
400         break;
401       }
402       
403     case NMB_REL:
404     {
405       if (nmb->header.qdcount==0 || nmb->header.arcount==0)
406           {
407             DEBUG(2,("netbios release packet rejected\n"));
408             break;
409           }
410         
411         if (nmb->header.response)
412           response_netbios_packet(p); /* response to reply dealt with in here */
413         else
414           reply_name_release(p);
415       break;
416     }
417   }
418 }
419
420
421 /*******************************************************************
422   run elements off the packet queue till its empty
423   ******************************************************************/
424 void run_packet_queue()
425 {
426   struct packet_struct *p;
427
428   while ((p=packet_queue))
429     {
430       switch (p->packet_type)
431         {
432         case NMB_PACKET:
433           process_nmb(p);
434           break;
435           
436         case DGRAM_PACKET:
437           process_dgram(p);
438           break;
439         }
440       
441       packet_queue = packet_queue->next;
442       if (packet_queue) packet_queue->prev = NULL;
443       free_packet(p);
444     }
445 }
446
447 /****************************************************************************
448   listens for NMB or DGRAM packets, and queues them
449   ***************************************************************************/
450 void listen_for_packets(BOOL run_election)
451 {
452   fd_set fds;
453   int selrtn;
454   struct timeval timeout;
455
456   FD_ZERO(&fds);
457   FD_SET(ClientNMB,&fds);
458   FD_SET(ClientDGRAM,&fds);
459
460   /* during elections and when expecting a netbios response packet we need
461      to send election packets at one second intervals.
462      XXXX actually, it needs to be the interval (in ms) between time now and the
463      time we are expecting the next netbios packet */
464
465   timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
466   timeout.tv_usec = 0;
467
468   selrtn = sys_select(&fds,&timeout);
469
470   if (FD_ISSET(ClientNMB,&fds))
471     {
472       struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
473       if (packet) {
474 #if 1
475         if (ismyip(packet->ip) &&
476             (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
477           DEBUG(5,("discarding own packet from %s:%d\n",
478                    inet_ntoa(packet->ip),packet->port));          
479           free_packet(packet);
480         } else 
481 #endif
482           {
483             queue_packet(packet);
484           }
485       }
486     }
487
488   if (FD_ISSET(ClientDGRAM,&fds))
489     {
490       struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
491       if (packet) {
492 #if 1
493         if (ismyip(packet->ip) &&
494               (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
495           DEBUG(5,("discarding own packet from %s:%d\n",
496                    inet_ntoa(packet->ip),packet->port));          
497           free_packet(packet);
498         } else
499 #endif 
500           {
501             queue_packet(packet);
502           }
503       }
504     }
505 }
506
507
508
509 /****************************************************************************
510   construct and send a netbios DGRAM
511
512   Note that this currently sends all answers to port 138. thats the
513   wrong things to do! I should send to the requestors port. XXX
514   **************************************************************************/
515 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
516                          char *dstname,int src_type,int dest_type,
517                          struct in_addr dest_ip,struct in_addr src_ip)
518 {
519   struct packet_struct p;
520   struct dgram_packet *dgram = &p.packet.dgram;
521   struct in_addr wins_ip = ipgrp;
522   char *ptr,*p2;
523   char tmp[4];
524
525   /* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */
526   if (ip_equal(wins_ip, dest_ip)) return False;
527
528   bzero((char *)&p,sizeof(p));
529
530   update_name_trn_id();
531
532   dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
533   dgram->header.flags.node_type = M_NODE;
534   dgram->header.flags.first = True;
535   dgram->header.flags.more = False;
536   dgram->header.dgm_id = name_trn_id;
537   dgram->header.source_ip = src_ip;
538   dgram->header.source_port = DGRAM_PORT;
539   dgram->header.dgm_length = 0; /* let build_dgram() handle this */
540   dgram->header.packet_offset = 0;
541   
542   make_nmb_name(&dgram->source_name,srcname,src_type,scope);
543   make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
544
545   ptr = &dgram->data[0];
546
547   /* now setup the smb part */
548   ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
549   memcpy(tmp,ptr,4);
550   set_message(ptr,17,17 + len,True);
551   memcpy(ptr,tmp,4);
552
553   CVAL(ptr,smb_com) = SMBtrans;
554   SSVAL(ptr,smb_vwv1,len);
555   SSVAL(ptr,smb_vwv11,len);
556   SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
557   SSVAL(ptr,smb_vwv13,3);
558   SSVAL(ptr,smb_vwv14,1);
559   SSVAL(ptr,smb_vwv15,1);
560   SSVAL(ptr,smb_vwv16,2);
561   p2 = smb_buf(ptr);
562   strcpy(p2,mailslot);
563   p2 = skip_string(p2,1);
564
565   memcpy(p2,buf,len);
566   p2 += len;
567
568   dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
569
570   p.ip = dest_ip;
571   p.port = DGRAM_PORT;
572   p.fd = ClientDGRAM;
573   p.timestamp = time(NULL);
574   p.packet_type = DGRAM_PACKET;
575
576   DEBUG(4,("send mailslot %s from %s %s", mailslot,
577                     inet_ntoa(src_ip),namestr(&dgram->source_name)));
578   DEBUG(4,("to %s %s\n", inet_ntoa(dest_ip),namestr(&dgram->dest_name)));
579
580   return(send_packet(&p));
581 }