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.
27 extern int ClientDGRAM;
29 /* this is our initiated name query response database */
30 struct name_response_record *nameresponselist = NULL;
32 extern int DEBUGLEVEL;
34 static uint16 name_trn_id=0;
35 BOOL CanRecurse = True;
37 extern pstring myname;
38 extern struct in_addr ipzero;
41 /***************************************************************************
42 add an initated name query into the list
43 **************************************************************************/
44 extern void add_response_record(struct name_response_record *n)
46 struct name_response_record *n2;
48 if (!nameresponselist)
56 for (n2 = nameresponselist; n2->next; n2 = n2->next) ;
64 /*******************************************************************
65 remove old name response entries
66 ******************************************************************/
67 void expire_netbios_response_entries(time_t t)
69 struct name_response_record *n;
70 struct name_response_record *nextn;
72 for (n = nameresponselist; n; n = nextn)
74 if (n->start_time < t)
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));
79 if (n->cmd_type == CHECK_MASTER)
81 /* if no response received, the master browser must have gone */
83 browser_gone(n->name.name, n->to_ip);
88 if (n->prev) n->prev->next = n->next;
89 if (n->next) n->next->prev = n->prev;
91 if (nameresponselist == n) nameresponselist = n->next;
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)
110 struct packet_struct p;
111 struct nmb_packet *nmb = &p.packet.nmb;
112 struct res_rec answers;
113 char *packet_type = "unknown";
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";
122 DEBUG(4,("replying netbios packet: %s %s\n",
123 packet_type, namestr(rr_name), inet_ntoa(p.ip)));
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;
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;
140 bzero((char*)&nmb->question,sizeof(nmb->question));
142 nmb->answers = &answers;
143 bzero((char*)nmb->answers,sizeof(*nmb->answers));
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;
152 nmb->answers->rdlength = len;
153 memcpy(nmb->answers->rdata, data, len);
156 p.packet_type = NMB_PACKET;
158 debug_nmb_packet(&p);
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)
171 struct packet_struct p;
172 struct nmb_packet *nmb = &p.packet.nmb;
173 struct res_rec additional_rec;
174 char *packet_type = "unknown";
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; }
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)));
185 if (opcode == -1) return False;
187 bzero((char *)&p,sizeof(p));
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;
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;
207 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
209 nmb->question.question_type = quest_type;
210 nmb->question.question_class = 0x1;
212 if (quest_type == NMB_REG || quest_type == NMB_REL)
214 nmb->additional = &additional_rec;
215 bzero((char *)nmb->additional,sizeof(*nmb->additional));
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;
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));
230 p.timestamp = time(NULL);
231 p.packet_type = NMB_PACKET;
233 if (!send_packet(&p))
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)
249 if ((!lp_wins_support()) && (*lp_wins_server()))
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());
255 if (!zero_ip(wins_ip))
262 /* oops. smb.conf's wins server parameter MUST be a host_name
264 DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
268 if (zero_ip(to_ip)) return;
270 queue_netbios_packet(fd, quest_type, cmd,
271 name, name_type, nb_flags,
272 bcast, recurse, to_ip);
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)
282 struct name_response_record *n;
284 if (!name || !name[0]) return NULL;
286 if (!(n = (struct name_response_record *)malloc(sizeof(*n))))
292 make_nmb_name(&n->name, name, type, scope);
294 n->recurse = recurse;
296 n->start_time = time(NULL);
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)
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;
320 make_name_query_record(cmd,id,fd,name,name_type,bcast,recurse,to_ip)))
322 add_response_record(n);
327 /****************************************************************************
328 find a response in the name query response list
329 **************************************************************************/
330 struct name_response_record *find_name_query(uint16 id)
332 struct name_response_record *n;
334 for (n = nameresponselist; n; n = n->next)
336 if (n->response_id == id) {
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;
352 /*******************************************************************
353 queue a packet into the packet queue
354 ******************************************************************/
355 void queue_packet(struct packet_struct *packet)
357 struct packet_struct *p;
362 packet_queue = packet;
366 /* find the bottom */
367 for (p=packet_queue;p->next;p=p->next) ;
374 /*******************************************************************
375 run elements off the packet queue till its empty
376 ******************************************************************/
377 void run_packet_queue()
379 struct packet_struct *p;
381 while ((p=packet_queue))
383 switch (p->packet_type)
394 packet_queue = packet_queue->next;
395 if (packet_queue) packet_queue->prev = NULL;
400 /****************************************************************************
401 listens for NMB or DGRAM packets, and queues them
402 ***************************************************************************/
403 void listen_for_packets(BOOL run_election)
407 struct timeval timeout;
410 FD_SET(ClientNMB,&fds);
411 FD_SET(ClientDGRAM,&fds);
413 /* during elections we need to send election packets at one
416 timeout.tv_sec = run_election ? 1 : NMBD_SELECT_LOOP;
419 selrtn = sys_select(&fds,&timeout);
421 if (FD_ISSET(ClientNMB,&fds))
423 struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
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));
434 queue_packet(packet);
439 if (FD_ISSET(ClientDGRAM,&fds))
441 struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
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));
452 queue_packet(packet);
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)
468 int level = t==0x20 ? 4 : 0;
469 int numnames = CVAL(p,0);
472 DEBUG(level,("received %d names\n",numnames));
476 if (serv_name) *serv_name = 0;
493 trim_string(qname,NULL," ");
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;}
507 /* might as well update our namelist while we're at it */
510 struct in_addr nameip;
511 enum name_source src;
520 add_netbios_entry(qname,type,nb_flags,2*60*60,src,nameip,True);
523 /* we want the server name */
524 if (serv_name && !*serv_name && !group && t == 0)
526 StrnCpy(serv_name,qname,15);
530 /* looking for a name and type? */
531 if (name && !found && (t == type))
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))
539 make_nmb_name(name,qname,type,scope);
543 DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
545 DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
546 IVAL(p,20),IVAL(p,24)));
551 /****************************************************************************
552 construct and send a netbios DGRAM
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)
561 struct packet_struct p;
562 struct dgram_packet *dgram = &p.packet.dgram;
566 bzero((char *)&p,sizeof(p));
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;
578 make_nmb_name(&dgram->source_name,srcname,src_type,scope);
579 make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
581 ptr = &dgram->data[0];
583 /* now setup the smb part */
584 ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
586 set_message(ptr,17,17 + len,True);
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);
599 p2 = skip_string(p2,1);
604 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
609 p.timestamp = time(NULL);
610 p.packet_type = DGRAM_PACKET;
612 return(send_packet(&p));