This commit was manufactured by cvs2svn to create tag
[Samba/gbeck.git] / source / namepacket.c
blob84b0a1b355ebbb124c781b59e2ba5d32724e12d7
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
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.
21 Revision History:
23 14 jan 96: lkcl@pires.co.uk
24 added multiple workgroup domain master support
28 #include "includes.h"
30 extern int ClientNMB;
31 extern int ClientDGRAM;
33 extern int DEBUGLEVEL;
35 extern int num_response_packets;
37 BOOL CanRecurse = True;
38 extern pstring scope;
39 extern struct in_addr ipgrp;
41 static uint16 name_trn_id=0;
44 /***************************************************************************
45 updates the unique transaction identifier
46 **************************************************************************/
47 void debug_browse_data(char *outbuf, int len)
49 int i,j;
50 for (i = 0; i < len; i+= 16)
52 DEBUG(4, ("%3x char ", i));
54 for (j = 0; j < 16; j++)
56 unsigned char x = outbuf[i+j];
57 if (x < 32 || x > 127) x = '.';
59 if (i+j >= len) break;
60 DEBUG(4, ("%c", x));
63 DEBUG(4, (" hex ", i));
65 for (j = 0; j < 16; j++)
67 if (i+j >= len) break;
68 DEBUG(4, (" %02x", outbuf[i+j]));
71 DEBUG(4, ("\n"));
77 /***************************************************************************
78 updates the unique transaction identifier
79 **************************************************************************/
80 static void update_name_trn_id(void)
82 if (!name_trn_id)
84 name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
86 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
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)
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;
104 if (!id) return;
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_REG_REFRESH ) { packet_type = "nmb_reg_refresh"; opcode = 9; }
110 if (quest_type == NMB_REL ) { packet_type = "nmb_rel"; opcode = 6; }
112 DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
113 packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
115 if (opcode == -1) return;
117 bzero((char *)&p,sizeof(p));
119 if (*id == 0xffff) {
120 update_name_trn_id();
121 *id = name_trn_id; /* allow resending with same id */
124 nmb->header.name_trn_id = *id;
125 nmb->header.opcode = opcode;
126 nmb->header.response = False;
128 nmb->header.nm_flags.bcast = bcast;
129 nmb->header.nm_flags.recursion_available = False;
130 nmb->header.nm_flags.recursion_desired = recurse;
131 nmb->header.nm_flags.trunc = False;
132 nmb->header.nm_flags.authoritative = False;
134 nmb->header.rcode = 0;
135 nmb->header.qdcount = 1;
136 nmb->header.ancount = 0;
137 nmb->header.nscount = 0;
138 nmb->header.arcount = (quest_type==NMB_REG ||
139 quest_type==NMB_REL ||
140 quest_type==NMB_REG_REFRESH) ? 1 : 0;
142 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
144 nmb->question.question_type = 0x20;
145 nmb->question.question_class = 0x1;
147 if (quest_type == NMB_REG ||
148 quest_type == NMB_REG_REFRESH ||
149 quest_type == NMB_REL)
151 nmb->additional = &additional_rec;
152 bzero((char *)nmb->additional,sizeof(*nmb->additional));
154 nmb->additional->rr_name = nmb->question.question_name;
155 nmb->additional->rr_type = 0x20;
156 nmb->additional->rr_class = 0x1;
158 if (quest_type == NMB_REG || quest_type == NMB_REG_REFRESH)
159 nmb->additional->ttl = lp_max_ttl();
160 else
161 nmb->additional->ttl = 0;
163 nmb->additional->rdlength = 6;
164 nmb->additional->rdata[0] = nb_flags;
165 putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
168 p.ip = to_ip;
169 p.port = NMB_PORT;
170 p.fd = fd;
171 p.timestamp = time(NULL);
172 p.packet_type = NMB_PACKET;
174 if (!send_packet(&p)) {
175 DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port));
176 *id = 0xffff;
179 return;
183 /****************************************************************************
184 reply to a netbios name packet
185 ****************************************************************************/
186 void reply_netbios_packet(struct packet_struct *p1,int trn_id,
187 int rcode, int rcv_code, int opcode, BOOL recurse,
188 struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
189 char *data,int len)
191 struct packet_struct p;
192 struct nmb_packet *nmb = &p.packet.nmb;
193 struct res_rec answers;
194 char *packet_type = "unknown";
195 BOOL recursion_desired = False;
197 p = *p1;
199 switch (rcv_code)
201 case NMB_STATUS:
203 packet_type = "nmb_status";
204 recursion_desired = True;
205 break;
207 case NMB_QUERY:
209 packet_type = "nmb_query";
210 recursion_desired = True;
211 break;
213 case NMB_REG:
215 packet_type = "nmb_reg";
216 recursion_desired = True;
217 break;
219 case NMB_REL:
221 packet_type = "nmb_rel";
222 recursion_desired = False;
223 break;
225 case NMB_WAIT_ACK:
227 packet_type = "nmb_wack";
228 recursion_desired = False;
229 break;
231 default:
233 DEBUG(1,("replying netbios packet: %s %s\n",
234 packet_type, namestr(rr_name), inet_ntoa(p.ip)));
236 return;
240 DEBUG(4,("replying netbios packet: %s %s\n",
241 packet_type, namestr(rr_name), inet_ntoa(p.ip)));
243 nmb->header.name_trn_id = trn_id;
244 nmb->header.opcode = opcode;
245 nmb->header.response = True;
246 nmb->header.nm_flags.bcast = False;
247 nmb->header.nm_flags.recursion_available = recurse;
248 nmb->header.nm_flags.recursion_desired = recursion_desired;
249 nmb->header.nm_flags.trunc = False;
250 nmb->header.nm_flags.authoritative = True;
252 nmb->header.qdcount = 0;
253 nmb->header.ancount = 1;
254 nmb->header.nscount = 0;
255 nmb->header.arcount = 0;
256 nmb->header.rcode = rcode;
258 bzero((char*)&nmb->question,sizeof(nmb->question));
260 nmb->answers = &answers;
261 bzero((char*)nmb->answers,sizeof(*nmb->answers));
263 nmb->answers->rr_name = *rr_name;
264 nmb->answers->rr_type = rr_type;
265 nmb->answers->rr_class = rr_class;
266 nmb->answers->ttl = ttl;
268 if (data && len)
270 nmb->answers->rdlength = len;
271 memcpy(nmb->answers->rdata, data, len);
274 p.packet_type = NMB_PACKET;
276 debug_nmb_packet(&p);
278 send_packet(&p);
282 /*******************************************************************
283 the global packet linked-list. incoming entries are added to the
284 end of this list. it is supposed to remain fairly short so we
285 won't bother with an end pointer.
286 ******************************************************************/
287 static struct packet_struct *packet_queue = NULL;
289 /*******************************************************************
290 queue a packet into the packet queue
291 ******************************************************************/
292 void queue_packet(struct packet_struct *packet)
294 struct packet_struct *p;
296 if (!packet_queue) {
297 packet->prev = NULL;
298 packet->next = NULL;
299 packet_queue = packet;
300 return;
303 /* find the bottom */
304 for (p=packet_queue;p->next;p=p->next) ;
306 p->next = packet;
307 packet->next = NULL;
308 packet->prev = p;
311 /****************************************************************************
312 determine if a packet is for us. Note that to have any chance of
313 being efficient we need to drop as many packets as possible at this
314 stage as subsequent processing is expensive.
316 We also must make absolutely sure we don't tread on another machines
317 property by answering a packet that is not for us.
318 ****************************************************************************/
319 static BOOL listening(struct packet_struct *p,struct nmb_name *n)
321 struct subnet_record *d;
322 struct name_record *n1;
324 d = find_subnet(p->ip);
326 n1 = find_name_search(&d,n,FIND_LOCAL|FIND_WINS|FIND_SELF,p->ip);
328 return (n1 != NULL);
332 /****************************************************************************
333 process udp 138 datagrams
334 ****************************************************************************/
335 static void process_dgram(struct packet_struct *p)
337 char *buf;
338 char *buf2;
339 int len;
340 struct dgram_packet *dgram = &p->packet.dgram;
342 /* if we aren't listening to the destination name then ignore the packet */
343 if (!listening(p,&dgram->dest_name))
344 return;
347 if (dgram->header.msg_type != 0x10 &&
348 dgram->header.msg_type != 0x11 &&
349 dgram->header.msg_type != 0x12) {
350 /* don't process error packets etc yet */
351 return;
354 buf = &dgram->data[0];
355 buf -= 4; /* XXXX for the pseudo tcp length -
356 someday I need to get rid of this */
358 if (CVAL(buf,smb_com) != SMBtrans) return;
360 len = SVAL(buf,smb_vwv11);
361 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
363 DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
364 namestr(&dgram->source_name),namestr(&dgram->dest_name),
365 smb_buf(buf),CVAL(buf2,0),len));
368 if (len <= 0) return;
370 /* datagram packet received for the browser mailslot */
371 if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) {
372 process_browse_packet(p,buf2,len);
373 return;
376 /* datagram packet received for the domain log on mailslot */
377 if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) {
378 process_logon_packet(p,buf2,len);
379 return;
383 /****************************************************************************
384 process a nmb packet
385 ****************************************************************************/
386 static void process_nmb(struct packet_struct *p)
388 struct nmb_packet *nmb = &p->packet.nmb;
390 debug_nmb_packet(p);
392 switch (nmb->header.opcode)
394 case 8: /* what is this?? */
395 case NMB_REG:
396 case NMB_REG_REFRESH:
398 if (nmb->header.response)
400 if (nmb->header.ancount ==0) break;
401 response_netbios_packet(p); /* response to registration dealt
402 with here */
404 else
406 if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
407 reply_name_reg(p);
409 break;
412 case 0:
414 if (nmb->header.response)
416 switch (nmb->question.question_type)
418 case 0x0:
420 response_netbios_packet(p);
421 break;
424 return;
426 else if (nmb->header.qdcount>0)
428 switch (nmb->question.question_type)
430 case NMB_QUERY:
432 reply_name_query(p);
433 break;
435 case NMB_STATUS:
437 reply_name_status(p);
438 break;
441 return;
443 break;
446 case NMB_REL:
448 if (nmb->header.response)
450 if (nmb->header.ancount ==0) break;
451 response_netbios_packet(p); /* response to release dealt
452 with here */
454 else
456 if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
457 reply_name_release(p);
459 break;
465 /*******************************************************************
466 run elements off the packet queue till its empty
467 ******************************************************************/
468 void run_packet_queue()
470 struct packet_struct *p;
472 while ((p=packet_queue))
474 switch (p->packet_type)
476 case NMB_PACKET:
477 process_nmb(p);
478 break;
480 case DGRAM_PACKET:
481 process_dgram(p);
482 break;
485 packet_queue = packet_queue->next;
486 if (packet_queue) packet_queue->prev = NULL;
487 free_packet(p);
491 /****************************************************************************
492 listens for NMB or DGRAM packets, and queues them
493 ***************************************************************************/
494 void listen_for_packets(BOOL run_election)
496 fd_set fds;
497 int selrtn;
498 struct timeval timeout;
500 FD_ZERO(&fds);
501 FD_SET(ClientNMB,&fds);
502 FD_SET(ClientDGRAM,&fds);
504 /* during elections and when expecting a netbios response packet we
505 need to send election packets at tighter intervals
507 ideally it needs to be the interval (in ms) between time now and
508 the time we are expecting the next netbios packet */
510 timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP;
511 timeout.tv_usec = 0;
513 selrtn = sys_select(&fds,&timeout);
515 if (FD_ISSET(ClientNMB,&fds))
517 struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
518 if (packet)
520 if (ismyip(packet->ip) && packet->port == NMB_PORT)
522 DEBUG(7,("discarding own packet from %s:%d\n",
523 inet_ntoa(packet->ip),packet->port));
524 free_packet(packet);
526 else
528 queue_packet(packet);
533 if (FD_ISSET(ClientDGRAM,&fds))
535 struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
536 if (packet)
538 if (ismyip(packet->ip) && packet->port == DGRAM_PORT)
540 DEBUG(7,("discarding own packet from %s:%d\n",
541 inet_ntoa(packet->ip),packet->port));
542 free_packet(packet);
544 else
546 queue_packet(packet);
554 /****************************************************************************
555 construct and send a netbios DGRAM
557 Note that this currently sends all answers to port 138. thats the
558 wrong things to do! I should send to the requestors port. XXX
559 **************************************************************************/
560 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
561 char *dstname,int src_type,int dest_type,
562 struct in_addr dest_ip,struct in_addr src_ip)
564 struct packet_struct p;
565 struct dgram_packet *dgram = &p.packet.dgram;
566 struct in_addr wins_ip = ipgrp;
567 char *ptr,*p2;
568 char tmp[4];
570 /* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */
571 if (ip_equal(wins_ip, dest_ip)) return False;
573 bzero((char *)&p,sizeof(p));
575 update_name_trn_id();
577 dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
578 dgram->header.flags.node_type = M_NODE;
579 dgram->header.flags.first = True;
580 dgram->header.flags.more = False;
581 dgram->header.dgm_id = name_trn_id;
582 dgram->header.source_ip = src_ip;
583 dgram->header.source_port = DGRAM_PORT;
584 dgram->header.dgm_length = 0; /* let build_dgram() handle this */
585 dgram->header.packet_offset = 0;
587 make_nmb_name(&dgram->source_name,srcname,src_type,scope);
588 make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
590 ptr = &dgram->data[0];
592 /* now setup the smb part */
593 ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
594 memcpy(tmp,ptr,4);
595 set_message(ptr,17,17 + len,True);
596 memcpy(ptr,tmp,4);
598 CVAL(ptr,smb_com) = SMBtrans;
599 SSVAL(ptr,smb_vwv1,len);
600 SSVAL(ptr,smb_vwv11,len);
601 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
602 SSVAL(ptr,smb_vwv13,3);
603 SSVAL(ptr,smb_vwv14,1);
604 SSVAL(ptr,smb_vwv15,1);
605 SSVAL(ptr,smb_vwv16,2);
606 p2 = smb_buf(ptr);
607 strcpy(p2,mailslot);
608 p2 = skip_string(p2,1);
610 memcpy(p2,buf,len);
611 p2 += len;
613 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
615 p.ip = dest_ip;
616 p.port = DGRAM_PORT;
617 p.fd = ClientDGRAM;
618 p.timestamp = time(NULL);
619 p.packet_type = DGRAM_PACKET;
621 DEBUG(4,("send mailslot %s from %s %s", mailslot,
622 inet_ntoa(src_ip),namestr(&dgram->source_name)));
623 DEBUG(4,("to %s %s\n", inet_ntoa(dest_ip),namestr(&dgram->dest_name)));
625 return(send_packet(&p));