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 DEBUGLEVEL;
29 int num_good_receives=0;
30 static uint16 name_trn_id = 0;
31 BOOL CanRecurse = True;
34 /*******************************************************************
35 handle "compressed" name pointers
36 ******************************************************************/
37 static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
38 BOOL *got_pointer,int *ret)
42 while ((ubuf[*offset] & 0xC0) == 0xC0) {
43 if (!*got_pointer) (*ret) += 2;
45 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
46 if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
53 /*******************************************************************
54 parse a nmb name from "compressed" format to something readable
55 return the space taken by the name, or 0 if the name is invalid
56 ******************************************************************/
57 static int parse_nmb_name(char *inbuf,int offset,int length,
58 struct nmb_name *name)
61 unsigned char *ubuf = (unsigned char *)inbuf;
63 BOOL got_pointer=False;
65 if (length - offset < 2) return(0);
67 /* handle initial name pointers */
68 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
73 if ((m & 0xC0) || offset+m+2 > length) return(0);
75 bzero((char *)name,sizeof(*name));
77 /* the "compressed" part */
78 if (!got_pointer) ret += m + 2;
82 c1 = ubuf[offset++]-'A';
83 c2 = ubuf[offset++]-'A';
84 if ((c1 & 0xF0) || (c2 & 0xF0)) return(0);
85 name->name[n++] = (c1<<4) | c2;
91 /* parse out the name type,
92 its always in the 16th byte of the name */
93 name->name_type = name->name[15];
95 /* remove trailing spaces */
98 while (n && name->name[n]==' ') name->name[n--] = 0;
101 /* now the domain parts (if any) */
103 while ((m=ubuf[offset])) {
104 /* we can have pointers within the domain part as well */
105 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
107 if (!got_pointer) ret += m+1;
108 if (n) name->scope[n++] = '.';
109 if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0);
111 while (m--) name->scope[n++] = (char)ubuf[offset++];
113 name->scope[n++] = 0;
119 /*******************************************************************
120 put a compressed nmb name into a buffer. return the length of the
123 compressed names are really weird. The "compression" doubles the
124 size. The idea is that it also means that compressed names conform
125 to the doman name system. See RFC1002.
126 ******************************************************************/
127 static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
133 if (name->name[0] == '*') {
134 /* special case for wildcard name */
138 sprintf(buf1,"%-15.15s%c",name->name,name->name_type);
146 buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
147 buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
153 if (name->scope[0]) {
154 /* XXXX this scope handling needs testing */
155 ret += strlen(name->scope) + 1;
156 strcpy(&buf[offset+1],name->scope);
159 while ((p = strchr(p,'.'))) {
160 buf[offset] = PTR_DIFF(p,&buf[offset]);
161 offset += buf[offset];
164 buf[offset] = strlen(&buf[offset+1]);
170 /*******************************************************************
171 useful for debugging messages
172 ******************************************************************/
173 char *namestr(struct nmb_name *n)
176 static fstring ret[4];
180 sprintf(p,"%s(%x)",n->name,n->name_type);
182 sprintf(p,"%s(%x).%s",n->name,n->name_type,n->scope);
188 /*******************************************************************
189 allocate are parse some resource records
190 ******************************************************************/
191 static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
192 struct res_rec **recs,
196 *recs = (struct res_rec *)malloc(sizeof(**recs)*count);
197 if (!*recs) return(False);
199 bzero(*recs,sizeof(**recs)*count);
201 for (i=0;i<count;i++) {
202 int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
204 if (!l || (*offset)+10 > length) {
208 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
209 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
210 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
211 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
213 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
214 (*offset)+(*recs)[i].rdlength > length) {
218 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
219 (*offset) += (*recs)[i].rdlength;
224 /*******************************************************************
225 put a resource record into a packet
226 ******************************************************************/
227 static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
232 for (i=0;i<count;i++) {
233 int l = put_nmb_name(buf,offset,&recs[i].rr_name);
236 RSSVAL(buf,offset,recs[i].rr_type);
237 RSSVAL(buf,offset+2,recs[i].rr_class);
238 RSIVAL(buf,offset+4,recs[i].ttl);
239 RSSVAL(buf,offset+8,recs[i].rdlength);
240 memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
241 offset += 10+recs[i].rdlength;
242 ret += 10+recs[i].rdlength;
248 /*******************************************************************
249 parse a dgram packet. Return False if the packet can't be parsed
250 or is invalid for some reason, True otherwise
252 this is documented in section 4.4.1 of RFC1002
253 ******************************************************************/
254 static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
259 bzero((char *)dgram,sizeof(*dgram));
261 if (length < 14) return(False);
263 dgram->header.msg_type = CVAL(inbuf,0);
264 flags = CVAL(inbuf,1);
265 dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
266 if (flags & 1) dgram->header.flags.more = True;
267 if (flags & 2) dgram->header.flags.first = True;
268 dgram->header.dgm_id = RSVAL(inbuf,2);
269 putip((char *)&dgram->header.source_ip,inbuf+4);
270 dgram->header.source_port = RSVAL(inbuf,8);
271 dgram->header.dgm_length = RSVAL(inbuf,10);
272 dgram->header.packet_offset = RSVAL(inbuf,12);
276 if (dgram->header.msg_type == 0x10 ||
277 dgram->header.msg_type == 0x11 ||
278 dgram->header.msg_type == 0x12) {
279 offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name);
280 offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name);
283 if (offset >= length || (length-offset > sizeof(dgram->data)))
286 dgram->datasize = length-offset;
287 memcpy(dgram->data,inbuf+offset,dgram->datasize);
293 /*******************************************************************
294 parse a nmb packet. Return False if the packet can't be parsed
295 or is invalid for some reason, True otherwise
296 ******************************************************************/
297 static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
301 bzero((char *)nmb,sizeof(*nmb));
303 if (length < 12) return(False);
305 /* parse the header */
306 nmb->header.name_trn_id = RSVAL(inbuf,0);
307 nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
308 nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
309 nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
310 nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
311 nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
312 nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
313 nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
314 nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
315 nmb->header.rcode = CVAL(inbuf,3) & 0xF;
316 nmb->header.qdcount = RSVAL(inbuf,4);
317 nmb->header.ancount = RSVAL(inbuf,6);
318 nmb->header.nscount = RSVAL(inbuf,8);
319 nmb->header.arcount = RSVAL(inbuf,10);
321 if (nmb->header.qdcount) {
322 offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
323 if (!offset) return(False);
325 if (length - (12+offset) < 4) return(False);
326 nmb->question.question_type = RSVAL(inbuf,12+offset);
327 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
334 /* and any resource records */
335 if (nmb->header.ancount &&
336 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
337 nmb->header.ancount))
340 if (nmb->header.nscount &&
341 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
342 nmb->header.nscount))
345 if (nmb->header.arcount &&
346 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
347 nmb->header.arcount))
353 /*******************************************************************
354 free up any resources associated with an nmb packet
355 ******************************************************************/
356 void free_nmb_packet(struct nmb_packet *nmb)
358 if (nmb->answers) free(nmb->answers);
359 if (nmb->nsrecs) free(nmb->nsrecs);
360 if (nmb->additional) free(nmb->additional);
363 /*******************************************************************
364 free up any resources associated with a packet
365 ******************************************************************/
366 void free_packet(struct packet_struct *packet)
368 if (packet->packet_type == NMB_PACKET)
369 free_nmb_packet(&packet->packet.nmb);
373 /*******************************************************************
374 read a packet from a socket and parse it, returning a packet ready
375 to be used or put on the queue. This assumes a UDP socket
376 ******************************************************************/
377 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
379 extern struct in_addr lastip;
381 struct packet_struct *packet;
382 char buf[MAX_DGRAM_SIZE];
386 length = read_udp_socket(fd,buf,sizeof(buf));
387 if (length < MIN_DGRAM_SIZE) return(NULL);
389 packet = (struct packet_struct *)malloc(sizeof(*packet));
390 if (!packet) return(NULL);
395 packet->port = lastport;
397 packet->timestamp = time(NULL);
398 packet->packet_type = packet_type;
402 ok = parse_nmb(buf,length,&packet->packet.nmb);
406 ok = parse_dgram(buf,length,&packet->packet.dgram);
416 DEBUG(4,("%s received a packet of len %d from (%s) port %d\n",
417 timestring(),length,inet_ntoa(packet->ip),packet->port));
423 /*******************************************************************
424 send a udp packet on a already open socket
425 ******************************************************************/
426 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
429 struct sockaddr_in sock_out;
431 /* set the address and port */
432 bzero((char *)&sock_out,sizeof(sock_out));
433 putip((char *)&sock_out.sin_addr,(char *)&ip);
434 sock_out.sin_port = htons( port );
435 sock_out.sin_family = AF_INET;
437 DEBUG(4,("%s sending a packet of len %d to (%s) on port %d\n",
438 timestring(),len,inet_ntoa(ip),port));
440 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
441 sizeof(sock_out)) >= 0);
444 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
445 inet_ntoa(ip),port,strerror(errno)));
453 /*******************************************************************
454 build a dgram packet ready for sending
456 XXXX This currently doesn't handle packets too big for one
457 datagram. It should split them and use the packet_offset, more and
458 first flags to handle the fragmentation. Yuck.
459 ******************************************************************/
460 static int build_dgram(char *buf,struct packet_struct *p)
462 struct dgram_packet *dgram = &p->packet.dgram;
463 unsigned char *ubuf = (unsigned char *)buf;
466 /* put in the header */
467 ubuf[0] = dgram->header.msg_type;
468 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
469 if (dgram->header.flags.more) ubuf[1] |= 1;
470 if (dgram->header.flags.first) ubuf[1] |= 2;
471 RSSVAL(ubuf,2,dgram->header.dgm_id);
472 putip(ubuf+4,(char *)&dgram->header.source_ip);
473 RSSVAL(ubuf,8,dgram->header.source_port);
474 RSSVAL(ubuf,12,dgram->header.packet_offset);
478 if (dgram->header.msg_type == 0x10 ||
479 dgram->header.msg_type == 0x11 ||
480 dgram->header.msg_type == 0x12) {
481 offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
482 offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
485 memcpy(ubuf+offset,dgram->data,dgram->datasize);
486 offset += dgram->datasize;
488 /* automatically set the dgm_length */
489 dgram->header.dgm_length = offset;
490 RSSVAL(ubuf,10,dgram->header.dgm_length);
495 /*******************************************************************
497 ******************************************************************/
498 void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
500 strcpy(n->name,name);
503 strcpy(n->scope,this_scope);
507 /*******************************************************************
508 build a nmb packet ready for sending
510 XXXX this currently relies on not being passed something that expands
511 to a packet too big for the buffer. Eventually this should be
512 changed to set the trunc bit so the receiver can request the rest
513 via tcp (when that becomes supported)
514 ******************************************************************/
515 static int build_nmb(char *buf,struct packet_struct *p)
517 struct nmb_packet *nmb = &p->packet.nmb;
518 unsigned char *ubuf = (unsigned char *)buf;
521 /* put in the header */
522 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
523 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
524 if (nmb->header.response) ubuf[offset+2] |= (1<<7);
525 if (nmb->header.nm_flags.authoritative) ubuf[offset+2] |= 0x4;
526 if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
527 if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
528 if (nmb->header.nm_flags.recursion_available) ubuf[offset+3] |= 0x80;
529 if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
530 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
531 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
532 RSSVAL(ubuf,offset+6,nmb->header.ancount);
533 RSSVAL(ubuf,offset+8,nmb->header.nscount);
534 RSSVAL(ubuf,offset+10,nmb->header.arcount);
537 if (nmb->header.qdcount) {
538 /* XXXX this doesn't handle a qdcount of > 1 */
539 offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
540 RSSVAL(ubuf,offset,nmb->question.question_type);
541 RSSVAL(ubuf,offset+2,nmb->question.question_class);
545 if (nmb->header.ancount)
546 offset += put_res_rec((char *)ubuf,offset,nmb->answers,
547 nmb->header.ancount);
549 if (nmb->header.nscount)
550 offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
551 nmb->header.nscount);
553 if (nmb->header.arcount)
554 offset += put_res_rec((char *)ubuf,offset,nmb->additional,
555 nmb->header.arcount);
561 /*******************************************************************
563 ******************************************************************/
564 BOOL send_packet(struct packet_struct *p)
569 bzero(buf,sizeof(buf));
571 switch (p->packet_type)
574 len = build_nmb(buf,p);
578 len = build_dgram(buf,p);
582 if (!len) return(False);
584 return(send_udp(p->fd,buf,len,p->ip,p->port));
587 /****************************************************************************
588 receive a packet with timeout on a open UDP filedescriptor
589 The timeout is in milliseconds
590 ***************************************************************************/
591 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
594 struct timeval timeout;
598 timeout.tv_sec = t/1000;
599 timeout.tv_usec = 1000*(t%1000);
601 sys_select(&fds,&timeout);
603 if (FD_ISSET(fd,&fds))
604 return(read_packet(fd,type));
610 /****************************************************************************
611 interpret a node status response
612 ****************************************************************************/
613 static void interpret_node_status(char *p, char *master,char *rname)
615 int level = (master||rname)?4:0;
616 int numnames = CVAL(p,0);
617 DEBUG(level,("received %d names\n",numnames));
619 if (rname) *rname = 0;
620 if (master) *master = 0;
634 strcat(flags, (p[0] & 0x80) ? "<GROUP> " : " ");
635 if ((p[0] & 0x60) == 0x00) strcat(flags,"B ");
636 if ((p[0] & 0x60) == 0x20) strcat(flags,"P ");
637 if ((p[0] & 0x60) == 0x40) strcat(flags,"M ");
638 if ((p[0] & 0x60) == 0x60) strcat(flags,"_ ");
639 if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
640 if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
641 if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
642 if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
644 if (master && !*master && type == 0x1d) {
645 StrnCpy(master,qname,15);
646 trim_string(master,NULL," ");
649 if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) {
650 StrnCpy(rname,qname,15);
651 trim_string(rname,NULL," ");
654 for (i = strlen( qname) ; --i >= 0 ; ) {
655 if (!isprint(qname[i])) qname[i] = '.';
657 DEBUG(level,("\t%-15s <%02x> - %s\n",qname,type,flags));
660 DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
661 IVAL(p,20),IVAL(p,24)));
665 /****************************************************************************
666 do a netbios name status query on a host
668 the "master" parameter is a hack used for finding workgroups.
669 **************************************************************************/
670 BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
671 struct in_addr to_ip,char *master,char *rname,
676 int retry_time = 5000;
678 struct packet_struct p;
679 struct packet_struct *p2;
680 struct nmb_packet *nmb = &p.packet.nmb;
682 bzero((char *)&p,sizeof(p));
684 if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
685 (getpid()%(unsigned)100);
686 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
688 nmb->header.name_trn_id = name_trn_id;
689 nmb->header.opcode = 0;
690 nmb->header.response = False;
691 nmb->header.nm_flags.bcast = False;
692 nmb->header.nm_flags.recursion_available = CanRecurse;
693 nmb->header.nm_flags.recursion_desired = recurse;
694 nmb->header.nm_flags.trunc = False;
695 nmb->header.nm_flags.authoritative = False;
696 nmb->header.rcode = 0;
697 nmb->header.qdcount = 1;
698 nmb->header.ancount = 0;
699 nmb->header.nscount = 0;
700 nmb->header.arcount = 0;
702 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
704 nmb->question.question_type = 0x21;
705 nmb->question.question_class = 0x1;
710 p.timestamp = time(NULL);
711 p.packet_type = NMB_PACKET;
715 if (!send_packet(&p))
722 struct timeval tval2;
723 GetTimeOfDay(&tval2);
724 if (TvalDiff(&tval,&tval2) > retry_time) {
726 if (!found && !send_packet(&p))
732 if ((p2=receive_packet(fd,NMB_PACKET,90)))
734 struct nmb_packet *nmb2 = &p2->packet.nmb;
735 if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
736 !nmb2->header.response) {
737 /* its not for us - maybe deal with it later */
745 if (nmb2->header.opcode != 0 ||
746 nmb2->header.nm_flags.bcast ||
747 nmb2->header.rcode ||
748 !nmb2->header.ancount ||
749 nmb2->answers->rr_type != 0x21) {
750 /* XXXX what do we do with this? could be a redirect, but
751 we'll discard it for the moment */
756 interpret_node_status(&nmb2->answers->rdata[0], master,rname);
763 DEBUG(0,("No status response (this is not unusual)\n"));
769 /****************************************************************************
770 do a netbios name query to find someones IP
771 ****************************************************************************/
772 BOOL name_query(int fd,char *name,int name_type,
773 BOOL bcast,BOOL recurse,
774 struct in_addr to_ip, struct in_addr *ip,void (*fn)())
778 int retry_time = bcast?250:2000;
780 struct packet_struct p;
781 struct packet_struct *p2;
782 struct nmb_packet *nmb = &p.packet.nmb;
784 bzero((char *)&p,sizeof(p));
786 if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
787 (getpid()%(unsigned)100);
788 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
790 nmb->header.name_trn_id = name_trn_id;
791 nmb->header.opcode = 0;
792 nmb->header.response = False;
793 nmb->header.nm_flags.bcast = bcast;
794 nmb->header.nm_flags.recursion_available = CanRecurse;
795 nmb->header.nm_flags.recursion_desired = recurse;
796 nmb->header.nm_flags.trunc = False;
797 nmb->header.nm_flags.authoritative = False;
798 nmb->header.rcode = 0;
799 nmb->header.qdcount = 1;
800 nmb->header.ancount = 0;
801 nmb->header.nscount = 0;
802 nmb->header.arcount = 0;
804 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
806 nmb->question.question_type = 0x20;
807 nmb->question.question_class = 0x1;
812 p.timestamp = time(NULL);
813 p.packet_type = NMB_PACKET;
817 if (!send_packet(&p))
824 struct timeval tval2;
825 GetTimeOfDay(&tval2);
826 if (TvalDiff(&tval,&tval2) > retry_time) {
828 if (!found && !send_packet(&p))
834 if ((p2=receive_packet(fd,NMB_PACKET,90)))
836 struct nmb_packet *nmb2 = &p2->packet.nmb;
837 if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
838 !nmb2->header.response) {
839 /* its not for us - maybe deal with it later
840 (put it on the queue?) */
848 if (nmb2->header.opcode != 0 ||
849 nmb2->header.nm_flags.bcast ||
850 nmb2->header.rcode ||
851 !nmb2->header.ancount) {
852 /* XXXX what do we do with this? could be a redirect, but
853 we'll discard it for the moment */
859 putip((char *)ip,&nmb2->answers->rdata[2]);
860 DEBUG(fn?3:2,("Got a positive name query response from %s",
862 DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip)));
864 found=True; retries=0;
874 /****************************************************************************
875 construct and send a netbios DGRAM
877 Note that this currently sends all answers to port 138. thats the
878 wrong things to do! I should send to the requestors port. XXX
879 **************************************************************************/
880 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,
881 char *srcname,char *dstname,
882 int src_type,int dest_type,
883 struct in_addr dest_ip,
884 struct in_addr src_ip)
886 struct packet_struct p;
887 struct dgram_packet *dgram = &p.packet.dgram;
891 bzero((char *)&p,sizeof(p));
893 dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
894 dgram->header.flags.node_type = M_NODE;
895 dgram->header.flags.first = True;
896 dgram->header.flags.more = False;
897 dgram->header.dgm_id = name_trn_id++;
898 dgram->header.source_ip = src_ip;
899 dgram->header.source_port = DGRAM_PORT;
900 dgram->header.dgm_length = 0; /* let build_dgram() handle this */
901 dgram->header.packet_offset = 0;
903 make_nmb_name(&dgram->source_name,srcname,src_type,scope);
904 make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
906 ptr = &dgram->data[0];
908 /* now setup the smb part */
909 ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
911 set_message(ptr,17,17 + len,True);
914 CVAL(ptr,smb_com) = SMBtrans;
915 SSVAL(ptr,smb_vwv1,len);
916 SSVAL(ptr,smb_vwv11,len);
917 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
918 SSVAL(ptr,smb_vwv13,3);
919 SSVAL(ptr,smb_vwv14,1);
920 SSVAL(ptr,smb_vwv15,1);
921 SSVAL(ptr,smb_vwv16,2);
924 p2 = skip_string(p2,1);
929 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
934 p.timestamp = time(NULL);
935 p.packet_type = DGRAM_PACKET;
937 return(send_packet(&p));