2 Unix SMB/Netbios implementation.
4 NBT netbios library routines
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.
26 extern int ClientDGRAM;
28 /* this is our initiated name query response database */
29 struct name_response_record *nameresponselist = NULL;
31 extern int DEBUGLEVEL;
33 static uint16 name_trn_id=0;
34 BOOL CanRecurse = True;
36 extern pstring myname;
37 extern struct in_addr ipzero;
40 /***************************************************************************
41 add an initated name query into the list
42 **************************************************************************/
43 extern void add_response_record(struct name_response_record *n)
45 struct name_response_record *n2;
47 if (!nameresponselist)
55 for (n2 = nameresponselist; n2->next; n2 = n2->next) ;
63 /*******************************************************************
64 remove old name response entries
65 ******************************************************************/
66 void expire_netbios_response_entries(time_t t)
68 struct name_response_record *n;
69 struct name_response_record *nextn;
71 for (n = nameresponselist; n; n = nextn)
73 if (n->start_time < t)
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));
78 if (n->cmd_type == CHECK_MASTER)
80 /* if no response received, the master browser must have gone */
82 browser_gone(n->name.name, n->to_ip);
87 if (n->prev) n->prev->next = n->next;
88 if (n->next) n->next->prev = n->prev;
90 if (nameresponselist == n) nameresponselist = n->next;
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)
109 struct packet_struct p;
110 struct nmb_packet *nmb = &p.packet.nmb;
111 struct res_rec answers;
112 char *packet_type = "unknown";
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";
121 DEBUG(4,("replying netbios packet: %s %s\n",
122 packet_type, namestr(rr_name), inet_ntoa(p.ip)));
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;
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;
139 bzero((char*)&nmb->question,sizeof(nmb->question));
141 nmb->answers = &answers;
142 bzero((char*)nmb->answers,sizeof(*nmb->answers));
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;
151 nmb->answers->rdlength = len;
152 memcpy(nmb->answers->rdata, data, len);
155 p.packet_type = NMB_PACKET;
157 debug_nmb_packet(&p);
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)
170 struct packet_struct p;
171 struct nmb_packet *nmb = &p.packet.nmb;
172 struct res_rec additional_rec;
173 char *packet_type = "unknown";
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; }
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)));
184 if (opcode == -1) return False;
186 bzero((char *)&p,sizeof(p));
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;
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;
206 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
208 nmb->question.question_type = quest_type;
209 nmb->question.question_class = 0x1;
211 if (quest_type == NMB_REG || quest_type == NMB_REL)
213 nmb->additional = &additional_rec;
214 bzero((char *)nmb->additional,sizeof(*nmb->additional));
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;
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));
229 p.timestamp = time(NULL);
230 p.packet_type = NMB_PACKET;
232 if (!send_packet(&p))
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)
248 if ((!lp_wins_support()) && (*lp_wins_server()))
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());
254 if (!zero_ip(wins_ip))
261 /* oops. smb.conf's wins server parameter MUST be a host_name
263 DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
267 if (zero_ip(to_ip)) return;
269 queue_netbios_packet(fd, quest_type, cmd,
270 name, name_type, nb_flags,
271 bcast, recurse, to_ip);
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)
281 struct name_response_record *n;
283 if (!name || !name[0]) return NULL;
285 if (!(n = (struct name_response_record *)malloc(sizeof(*n))))
291 make_nmb_name(&n->name, name, type, scope);
293 n->recurse = recurse;
295 n->start_time = time(NULL);
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)
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;
319 make_name_query_record(cmd,id,fd,name,name_type,bcast,recurse,to_ip)))
321 add_response_record(n);
326 /****************************************************************************
327 find a response in the name query response list
328 **************************************************************************/
329 struct name_response_record *find_name_query(uint16 id)
331 struct name_response_record *n;
333 for (n = nameresponselist; n; n = n->next)
335 if (n->response_id == id) {
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;
351 /*******************************************************************
352 queue a packet into the packet queue
353 ******************************************************************/
354 void queue_packet(struct packet_struct *packet)
356 struct packet_struct *p;
361 packet_queue = packet;
365 /* find the bottom */
366 for (p=packet_queue;p->next;p=p->next) ;
373 /*******************************************************************
374 run elements off the packet queue till its empty
375 ******************************************************************/
376 void run_packet_queue()
378 struct packet_struct *p;
380 while ((p=packet_queue))
382 switch (p->packet_type)
393 packet_queue = packet_queue->next;
394 if (packet_queue) packet_queue->prev = NULL;
399 /****************************************************************************
400 listens for NMB or DGRAM packets, and queues them
401 ***************************************************************************/
402 void listen_for_packets(BOOL run_election)
406 struct timeval timeout;
409 FD_SET(ClientNMB,&fds);
410 FD_SET(ClientDGRAM,&fds);
412 /* during elections we need to send election packets at one
415 timeout.tv_sec = run_election ? 1 : NMBD_SELECT_LOOP;
418 selrtn = sys_select(&fds,&timeout);
420 if (FD_ISSET(ClientNMB,&fds))
422 struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
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));
433 queue_packet(packet);
438 if (FD_ISSET(ClientDGRAM,&fds))
440 struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
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));
451 queue_packet(packet);
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)
467 int level = t==0x20 ? 4 : 0;
468 int numnames = CVAL(p,0);
471 DEBUG(level,("received %d names\n",numnames));
475 if (serv_name) *serv_name = 0;
492 trim_string(qname,NULL," ");
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;}
506 /* might as well update our namelist while we're at it */
509 struct in_addr nameip;
510 enum name_source src;
519 add_netbios_entry(qname,type,nb_flags,2*60*60,src,nameip,True);
522 /* we want the server name */
523 if (serv_name && !*serv_name && !group && t == 0)
525 StrnCpy(serv_name,qname,15);
529 /* looking for a name and type? */
530 if (name && !found && (t == type))
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))
538 make_nmb_name(name,qname,type,scope);
542 DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
544 DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
545 IVAL(p,20),IVAL(p,24)));
550 /****************************************************************************
551 construct and send a netbios DGRAM
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)
560 struct packet_struct p;
561 struct dgram_packet *dgram = &p.packet.dgram;
565 bzero((char *)&p,sizeof(p));
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;
577 make_nmb_name(&dgram->source_name,srcname,src_type,scope);
578 make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
580 ptr = &dgram->data[0];
582 /* now setup the smb part */
583 ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
585 set_message(ptr,17,17 + len,True);
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);
598 p2 = skip_string(p2,1);
603 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
608 p.timestamp = time(NULL);
609 p.packet_type = DGRAM_PACKET;
611 return(send_packet(&p));