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;
633 if (p[0] & 0x80) strcat(flags,"<GROUP> ");
634 if ((p[0] & 0x60) == 0) strcat(flags,"B ");
635 if ((p[0] & 0x60) == 1) strcat(flags,"P ");
636 if ((p[0] & 0x60) == 2) strcat(flags,"M ");
637 if ((p[0] & 0x60) == 3) strcat(flags,"_ ");
638 if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
639 if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
640 if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
641 if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
643 if (master && !*master && type == 0x1d) {
644 StrnCpy(master,qname,15);
645 trim_string(master,NULL," ");
648 if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) {
649 StrnCpy(rname,qname,15);
650 trim_string(rname,NULL," ");
653 DEBUG(level,("\t%s (type=0x%x)\t%s\n",qname,type,flags));
656 DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
657 IVAL(p,20),IVAL(p,24)));
661 /****************************************************************************
662 do a netbios name status query on a host
664 the "master" parameter is a hack used for finding workgroups.
665 **************************************************************************/
666 BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
667 struct in_addr to_ip,char *master,char *rname,
672 int retry_time = 5000;
674 struct packet_struct p;
675 struct packet_struct *p2;
676 struct nmb_packet *nmb = &p.packet.nmb;
678 bzero((char *)&p,sizeof(p));
680 if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
681 (getpid()%(unsigned)100);
682 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
684 nmb->header.name_trn_id = name_trn_id;
685 nmb->header.opcode = 0;
686 nmb->header.response = False;
687 nmb->header.nm_flags.bcast = False;
688 nmb->header.nm_flags.recursion_available = CanRecurse;
689 nmb->header.nm_flags.recursion_desired = recurse;
690 nmb->header.nm_flags.trunc = False;
691 nmb->header.nm_flags.authoritative = False;
692 nmb->header.rcode = 0;
693 nmb->header.qdcount = 1;
694 nmb->header.ancount = 0;
695 nmb->header.nscount = 0;
696 nmb->header.arcount = 0;
698 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
700 nmb->question.question_type = 0x21;
701 nmb->question.question_class = 0x1;
706 p.timestamp = time(NULL);
707 p.packet_type = NMB_PACKET;
711 if (!send_packet(&p))
718 struct timeval tval2;
719 GetTimeOfDay(&tval2);
720 if (TvalDiff(&tval,&tval2) > retry_time) {
722 if (!found && !send_packet(&p))
728 if ((p2=receive_packet(fd,NMB_PACKET,90)))
730 struct nmb_packet *nmb2 = &p2->packet.nmb;
731 if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
732 !nmb2->header.response) {
733 /* its not for us - maybe deal with it later */
741 if (nmb2->header.opcode != 0 ||
742 nmb2->header.nm_flags.bcast ||
743 nmb2->header.rcode ||
744 !nmb2->header.ancount ||
745 nmb2->answers->rr_type != 0x21) {
746 /* XXXX what do we do with this? could be a redirect, but
747 we'll discard it for the moment */
752 interpret_node_status(&nmb2->answers->rdata[0], master,rname);
759 DEBUG(0,("No status response (this is not unusual)\n"));
765 /****************************************************************************
766 do a netbios name query to find someones IP
767 ****************************************************************************/
768 BOOL name_query(int fd,char *name,int name_type,
769 BOOL bcast,BOOL recurse,
770 struct in_addr to_ip, struct in_addr *ip,void (*fn)())
774 int retry_time = bcast?250:2000;
776 struct packet_struct p;
777 struct packet_struct *p2;
778 struct nmb_packet *nmb = &p.packet.nmb;
780 bzero((char *)&p,sizeof(p));
782 if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
783 (getpid()%(unsigned)100);
784 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
786 nmb->header.name_trn_id = name_trn_id;
787 nmb->header.opcode = 0;
788 nmb->header.response = False;
789 nmb->header.nm_flags.bcast = bcast;
790 nmb->header.nm_flags.recursion_available = CanRecurse;
791 nmb->header.nm_flags.recursion_desired = recurse;
792 nmb->header.nm_flags.trunc = False;
793 nmb->header.nm_flags.authoritative = False;
794 nmb->header.rcode = 0;
795 nmb->header.qdcount = 1;
796 nmb->header.ancount = 0;
797 nmb->header.nscount = 0;
798 nmb->header.arcount = 0;
800 make_nmb_name(&nmb->question.question_name,name,name_type,scope);
802 nmb->question.question_type = 0x20;
803 nmb->question.question_class = 0x1;
808 p.timestamp = time(NULL);
809 p.packet_type = NMB_PACKET;
813 if (!send_packet(&p))
820 struct timeval tval2;
821 GetTimeOfDay(&tval2);
822 if (TvalDiff(&tval,&tval2) > retry_time) {
824 if (!found && !send_packet(&p))
830 if ((p2=receive_packet(fd,NMB_PACKET,90)))
832 struct nmb_packet *nmb2 = &p2->packet.nmb;
833 if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
834 !nmb2->header.response) {
835 /* its not for us - maybe deal with it later
836 (put it on the queue?) */
844 if (nmb2->header.opcode != 0 ||
845 nmb2->header.nm_flags.bcast ||
846 nmb2->header.rcode ||
847 !nmb2->header.ancount) {
848 /* XXXX what do we do with this? could be a redirect, but
849 we'll discard it for the moment */
855 putip((char *)ip,&nmb2->answers->rdata[2]);
856 DEBUG(fn?3:2,("Got a positive name query response from %s",
858 DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip)));
860 found=True; retries=0;
870 /****************************************************************************
871 construct and send a netbios DGRAM
873 Note that this currently sends all answers to port 138. thats the
874 wrong things to do! I should send to the requestors port. XXX
875 **************************************************************************/
876 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,
877 char *srcname,char *dstname,
878 int src_type,int dest_type,
879 struct in_addr dest_ip,
880 struct in_addr src_ip)
882 struct packet_struct p;
883 struct dgram_packet *dgram = &p.packet.dgram;
887 bzero((char *)&p,sizeof(p));
889 dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
890 dgram->header.flags.node_type = M_NODE;
891 dgram->header.flags.first = True;
892 dgram->header.flags.more = False;
893 dgram->header.dgm_id = name_trn_id++;
894 dgram->header.source_ip = src_ip;
895 dgram->header.source_port = DGRAM_PORT;
896 dgram->header.dgm_length = 0; /* let build_dgram() handle this */
897 dgram->header.packet_offset = 0;
899 make_nmb_name(&dgram->source_name,srcname,src_type,scope);
900 make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
902 ptr = &dgram->data[0];
904 /* now setup the smb part */
905 ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
907 set_message(ptr,17,17 + len,True);
910 CVAL(ptr,smb_com) = SMBtrans;
911 SSVAL(ptr,smb_vwv1,len);
912 SSVAL(ptr,smb_vwv11,len);
913 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
914 SSVAL(ptr,smb_vwv13,3);
915 SSVAL(ptr,smb_vwv14,1);
916 SSVAL(ptr,smb_vwv15,1);
917 SSVAL(ptr,smb_vwv16,2);
920 p2 = skip_string(p2,1);
925 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
930 p.timestamp = time(NULL);
931 p.packet_type = DGRAM_PACKET;
933 return(send_packet(&p));