14b995618630d33c26519f9de192588d736de4ad
[kai/samba.git] / source3 / nameresp.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios library routines
5    Copyright (C) Andrew Tridgell 1994-1995
6    
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.
11    
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.
16    
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.
20    
21 */
22
23 #include "includes.h"
24
25 extern int ClientNMB;
26 extern int ClientDGRAM;
27
28 extern struct subnet_record *subnetlist;
29
30 extern int DEBUGLEVEL;
31
32 static uint16 name_trn_id=0;
33 BOOL CanRecurse = True;
34 extern pstring scope;
35 extern pstring myname;
36 extern struct in_addr ipzero;
37 extern struct in_addr ipgrp;
38
39 int num_response_packets = 0;
40
41 /***************************************************************************
42   updates the unique transaction identifier
43   **************************************************************************/
44 static void update_name_trn_id(void)
45 {
46   if (!name_trn_id)
47   {
48     name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
49   }
50   name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
51 }
52
53
54 /***************************************************************************
55   add an initated name query  into the list
56   **************************************************************************/
57 static void add_response_record(struct subnet_record *d,
58                                 struct response_record *n)
59 {
60   struct response_record *n2;
61
62   if (!d) return;
63
64   if (!d->responselist)
65     {
66       d->responselist = n;
67       n->prev = NULL;
68       n->next = NULL;
69       return;
70     }
71   
72   for (n2 = d->responselist; n2->next; n2 = n2->next) ;
73   
74   n2->next = n;
75   n->next = NULL;
76   n->prev = n2;
77 }
78
79
80 /***************************************************************************
81   deals with an entry before it dies
82   **************************************************************************/
83 static void dead_netbios_entry(struct subnet_record *d,
84                                 struct response_record *n)
85 {
86   DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n",
87            inet_ntoa(n->to_ip), namestr(&n->name), n->num_msgs));
88
89   switch (n->cmd_type)
90   {
91     case NAME_QUERY_CONFIRM:
92     {
93                 if (!lp_wins_support()) return; /* only if we're a WINS server */
94
95                 if (n->num_msgs == 0)
96         {
97                         /* oops. name query had no response. check that the name is
98                            unique and then remove it from our WINS database */
99
100                         /* IMPORTANT: see query_refresh_names() */
101
102                         if ((!NAME_GROUP(n->nb_flags)))
103                         {
104                                 struct subnet_record *d = find_subnet(ipgrp);
105                                 if (d)
106                                 {
107                                         /* remove the name that had been registered with us,
108                                            and we're now getting no response when challenging.
109                                            see rfc1001.txt 15.5.2
110                                          */
111                                         remove_netbios_name(d, n->name.name, n->name.name_type,
112                                                                         REGISTER, n->to_ip);
113                                 }
114                         }
115                 }
116                 break;
117     }
118
119         case NAME_QUERY_MST_CHK:
120         {
121           /* if no response received, the master browser must have gone
122                  down on that subnet, without telling anyone. */
123
124           /* IMPORTANT: see response_netbios_packet() */
125
126           if (n->num_msgs == 0)
127                   browser_gone(n->name.name, n->to_ip);
128           break;
129         }
130
131         case NAME_RELEASE:
132         {
133           /* if no response received, it must be OK for us to release the
134                  name. nobody objected (including a potentially dead or deaf
135                  WINS server) */
136
137           /* IMPORTANT: see response_name_release() */
138
139           if (ismyip(n->to_ip))
140           {
141                 remove_netbios_name(d,n->name.name,n->name.name_type,SELF,n->to_ip);
142           }
143           if (!n->bcast)
144           {
145                  DEBUG(1,("WINS server did not respond to name release!\n"));
146           }
147           break;
148         }
149
150         case NAME_REGISTER:
151         {
152           /* if no response received, and we are using a broadcast registration
153                  method, it must be OK for us to register the name: nobody objected 
154                  on that subnet. if we are using a WINS server, then the WINS
155                  server must be dead or deaf.
156            */
157           if (n->bcast)
158           {
159                 /* broadcast method: implicit acceptance of the name registration
160                    by not receiving any objections. */
161
162                 /* IMPORTANT: see response_name_reg() */
163
164                 enum name_source source = ismyip(n->to_ip) ? SELF : REGISTER;
165
166                 add_netbios_entry(d,n->name.name,n->name.name_type,
167                                 n->nb_flags, n->ttl, source,n->to_ip, True,!n->bcast);
168           }
169           else
170           {
171                 /* XXXX oops. this is where i wish this code could retry DGRAM
172                    packets. we directed a name registration at a WINS server, and
173                    received no response. rfc1001.txt states that after retrying,
174                    we should assume the WINS server is dead, and fall back to
175                    broadcasting. */
176                 
177                  DEBUG(1,("WINS server did not respond to name registration!\n"));
178           }
179           break;
180         }
181
182         default:
183         {
184           /* nothing to do but delete the dead expected-response structure */
185           /* this is normal. */
186           break;
187         }
188   }
189 }
190
191
192 /****************************************************************************
193   initiate a netbios packet
194   ****************************************************************************/
195 static void initiate_netbios_packet(uint16 *id,
196                                 int fd,int quest_type,char *name,int name_type,
197                             int nb_flags,BOOL bcast,BOOL recurse,
198                             struct in_addr to_ip)
199 {
200   struct packet_struct p;
201   struct nmb_packet *nmb = &p.packet.nmb;
202   struct res_rec additional_rec;
203   char *packet_type = "unknown";
204   int opcode = -1;
205
206   if (!id) return;
207
208   if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; }
209   if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; }
210   if (quest_type == NMB_REG   ) { packet_type = "nmb_reg"; opcode = 5; }
211   if (quest_type == NMB_REL   ) { packet_type = "nmb_rel"; opcode = 6; }
212   
213   DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
214            packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
215
216   if (opcode == -1) return;
217
218   bzero((char *)&p,sizeof(p));
219
220   update_name_trn_id();
221
222   if (*id == 0xffff) *id = name_trn_id; /* allow resending with same id */
223
224   nmb->header.name_trn_id = *id;
225   nmb->header.opcode = opcode;
226   nmb->header.response = False;
227   nmb->header.nm_flags.bcast = bcast;
228   nmb->header.nm_flags.recursion_available = CanRecurse;
229   nmb->header.nm_flags.recursion_desired = recurse;
230   nmb->header.nm_flags.trunc = False;
231   nmb->header.nm_flags.authoritative = False;
232   nmb->header.rcode = 0;
233   nmb->header.qdcount = 1;
234   nmb->header.ancount = 0;
235   nmb->header.nscount = 0;
236   nmb->header.arcount = (quest_type==NMB_REG || quest_type==NMB_REL) ? 1 : 0;
237   
238   make_nmb_name(&nmb->question.question_name,name,name_type,scope);
239   
240   nmb->question.question_type = quest_type;
241   nmb->question.question_class = 0x1;
242   
243   if (quest_type == NMB_REG || quest_type == NMB_REL)
244     {
245       nmb->additional = &additional_rec;
246       bzero((char *)nmb->additional,sizeof(*nmb->additional));
247       
248       nmb->additional->rr_name  = nmb->question.question_name;
249       nmb->additional->rr_type  = nmb->question.question_type;
250       nmb->additional->rr_class = nmb->question.question_class;
251       
252       nmb->additional->ttl = quest_type == NMB_REG ? lp_max_ttl() : 0;
253       nmb->additional->rdlength = 6;
254       nmb->additional->rdata[0] = nb_flags;
255       putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
256     }
257   
258   p.ip = to_ip;
259   p.port = NMB_PORT;
260   p.fd = fd;
261   p.timestamp = time(NULL);
262   p.packet_type = NMB_PACKET;
263   
264   if (!send_packet(&p)) *id = 0xffff;
265   
266   return;
267 }
268
269
270 /*******************************************************************
271   remove old name response entries
272   XXXX retry code needs to be added, including a retry wait period and a count
273        see name_query() and name_status() for suggested implementation.
274   ******************************************************************/
275 void expire_netbios_response_entries()
276 {
277   struct response_record *n;
278   struct response_record *nextn;
279   struct subnet_record *d;
280
281   for (d = subnetlist; d; d = d->next)
282    for (n = d->responselist; n; n = nextn)
283     {
284       if (n->repeat_time < time(NULL))
285           {
286                   if (n->repeat_count > 0)
287                   {
288                         /* resend the entry */
289                         initiate_netbios_packet(&n->response_id, n->fd, n->quest_type,
290                                                 n->name.name, n->name.name_type,
291                                       n->nb_flags, n->bcast, n->recurse, n->to_ip);
292
293             n->repeat_time += n->repeat_interval; /* XXXX ms needed */
294             n->repeat_count--;
295                   }
296                   else
297                   {
298                           dead_netbios_entry(d,n);
299
300                           nextn = n->next;
301                           
302                           if (n->prev) n->prev->next = n->next;
303                           if (n->next) n->next->prev = n->prev;
304                           
305                           if (d->responselist == n) d->responselist = n->next; 
306                           
307                           free(n);
308
309                           num_response_packets--;
310
311                           continue;
312                    }
313           }
314           nextn = n->next;
315     }
316 }
317
318
319 /****************************************************************************
320   reply to a netbios name packet 
321   ****************************************************************************/
322 void reply_netbios_packet(struct packet_struct *p1,int trn_id,
323                                 int rcode,int opcode, BOOL recurse,
324                                 struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
325                                 char *data,int len)
326 {
327   struct packet_struct p;
328   struct nmb_packet *nmb = &p.packet.nmb;
329   struct res_rec answers;
330   char *packet_type = "unknown";
331   
332   p = *p1;
333
334   if (rr_type == NMB_STATUS) packet_type = "nmb_status";
335   if (rr_type == NMB_QUERY ) packet_type = "nmb_query";
336   if (rr_type == NMB_REG   ) packet_type = "nmb_reg";
337   if (rr_type == NMB_REL   ) packet_type = "nmb_rel";
338   
339   DEBUG(4,("replying netbios packet: %s %s\n",
340            packet_type, namestr(rr_name), inet_ntoa(p.ip)));
341
342   nmb->header.name_trn_id = trn_id;
343   nmb->header.opcode = opcode;
344   nmb->header.response = True;
345   nmb->header.nm_flags.bcast = False;
346   nmb->header.nm_flags.recursion_available = recurse;
347   nmb->header.nm_flags.recursion_desired = True;
348   nmb->header.nm_flags.trunc = False;
349   nmb->header.nm_flags.authoritative = True;
350   
351   nmb->header.qdcount = 0;
352   nmb->header.ancount = 1;
353   nmb->header.nscount = 0;
354   nmb->header.arcount = 0;
355   nmb->header.rcode = 0;
356   
357   bzero((char*)&nmb->question,sizeof(nmb->question));
358   
359   nmb->answers = &answers;
360   bzero((char*)nmb->answers,sizeof(*nmb->answers));
361   
362   nmb->answers->rr_name  = *rr_name;
363   nmb->answers->rr_type  = rr_type;
364   nmb->answers->rr_class = rr_class;
365   nmb->answers->ttl      = ttl;
366   
367   if (data && len)
368     {
369       nmb->answers->rdlength = len;
370       memcpy(nmb->answers->rdata, data, len);
371     }
372   
373   p.packet_type = NMB_PACKET;
374   
375   debug_nmb_packet(&p);
376   
377   send_packet(&p);
378 }
379
380
381 /****************************************************************************
382   wrapper function to override a broadcast message and send it to the WINS
383   name server instead, if it exists. if wins is false, and there has been no
384   WINS server specified, the packet will NOT be sent.
385   ****************************************************************************/
386 void queue_netbios_pkt_wins(struct subnet_record *d,
387                                 int fd,int quest_type,enum cmd_type cmd,
388                             char *name,int name_type,int nb_flags, time_t ttl,
389                             BOOL bcast,BOOL recurse,struct in_addr to_ip)
390 {
391   if ((!lp_wins_support()) && (*lp_wins_server()))
392     {
393       /* samba is not a WINS server, and we are using a WINS server */
394       struct in_addr wins_ip;
395       wins_ip = *interpret_addr2(lp_wins_server());
396
397       if (!zero_ip(wins_ip))
398         {
399           bcast = False;
400           to_ip = wins_ip;
401         }
402       else
403         {
404           /* oops. smb.conf's wins server parameter MUST be a host_name 
405              or an ip_address. */
406           DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
407         }
408     }
409
410   if (zero_ip(to_ip)) return;
411
412   queue_netbios_packet(d,fd, quest_type, cmd, 
413                        name, name_type, nb_flags, ttl,
414                        bcast, recurse, to_ip);
415 }
416
417 /****************************************************************************
418   create a name query response record
419   **************************************************************************/
420 static struct response_record *
421 make_response_queue_record(enum cmd_type cmd,int id,int fd,
422                                 int quest_type, char *name,int type, int nb_flags, time_t ttl,
423                                 BOOL bcast,BOOL recurse, struct in_addr ip)
424 {
425   struct response_record *n;
426         
427   if (!name || !name[0]) return NULL;
428         
429   if (!(n = (struct response_record *)malloc(sizeof(*n)))) 
430     return(NULL);
431
432   n->response_id = id;
433   n->cmd_type = cmd;
434   n->fd = fd;
435   n->quest_type = quest_type;
436   make_nmb_name(&n->name, name, type, scope);
437   n->nb_flags = nb_flags;
438   n->ttl = ttl;
439   n->bcast = bcast;
440   n->recurse = recurse;
441   n->to_ip = ip;
442
443   n->repeat_interval = 1; /* XXXX should be in ms */
444   n->repeat_count = 4;
445   n->repeat_time = time(NULL) + n->repeat_interval;
446
447   n->num_msgs = 0;
448
449   num_response_packets++; /* count of total number of packets still around */
450
451   return n;
452 }
453
454
455 /****************************************************************************
456   initiate a netbios name query to find someone's or someones' IP
457   this is intended to be used (not exclusively) for broadcasting to
458   master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
459   complete lists across a wide area network
460   ****************************************************************************/
461 void queue_netbios_packet(struct subnet_record *d,
462                         int fd,int quest_type,enum cmd_type cmd,char *name,
463                         int name_type,int nb_flags, time_t ttl,
464                         BOOL bcast,BOOL recurse, struct in_addr to_ip)
465 {
466   struct in_addr wins_ip = ipgrp;
467   struct response_record *n;
468   uint16 id = 0xffff;
469
470   /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
471   if (ip_equal(wins_ip, to_ip)) return;
472
473   initiate_netbios_packet(&id, fd, quest_type, name, name_type,
474                                       nb_flags, bcast, recurse, to_ip);
475
476   if (id == 0xffff) return;
477   
478   if ((n = make_response_queue_record(cmd,id,fd,
479                                                 quest_type,name,name_type,nb_flags,ttl,
480                                                 bcast,recurse,to_ip)))
481     {
482       add_response_record(d,n);
483     }
484 }
485
486
487 /****************************************************************************
488   find a response in a subnet's name query response list. 
489   **************************************************************************/
490 struct response_record *find_response_record(struct subnet_record **d,
491                                 uint16 id)
492 {  
493   struct response_record *n;
494
495   if (!d) return NULL;
496
497   for ((*d) = subnetlist; (*d); (*d) = (*d)->next)
498   {
499     for (n = (*d)->responselist; n; n = n->next)
500     {
501       if (n->response_id == id) {
502          return n;
503       }
504     }
505   }
506
507   *d = NULL;
508
509   return NULL;
510 }
511
512
513 /*******************************************************************
514   the global packet linked-list. incoming entries are added to the
515   end of this list.  it is supposed to remain fairly short so we
516   won't bother with an end pointer.
517   ******************************************************************/
518 static struct packet_struct *packet_queue = NULL;
519
520 /*******************************************************************
521   queue a packet into the packet queue
522   ******************************************************************/
523 void queue_packet(struct packet_struct *packet)
524 {
525   struct packet_struct *p;
526
527   if (!packet_queue) {
528     packet->prev = NULL;
529     packet->next = NULL;
530     packet_queue = packet;
531     return;
532   }
533   
534   /* find the bottom */
535   for (p=packet_queue;p->next;p=p->next) ;
536
537   p->next = packet;
538   packet->next = NULL;
539   packet->prev = p;
540 }
541
542 /*******************************************************************
543   run elements off the packet queue till its empty
544   ******************************************************************/
545 void run_packet_queue()
546 {
547   struct packet_struct *p;
548
549   while ((p=packet_queue))
550     {
551       switch (p->packet_type)
552         {
553         case NMB_PACKET:
554           process_nmb(p);
555           break;
556           
557         case DGRAM_PACKET:
558           process_dgram(p);
559           break;
560         }
561       
562       packet_queue = packet_queue->next;
563       if (packet_queue) packet_queue->prev = NULL;
564       free_packet(p);
565     }
566 }
567
568 /****************************************************************************
569   listens for NMB or DGRAM packets, and queues them
570   ***************************************************************************/
571 void listen_for_packets(BOOL run_election)
572 {
573   fd_set fds;
574   int selrtn;
575   struct timeval timeout;
576
577   FD_ZERO(&fds);
578   FD_SET(ClientNMB,&fds);
579   FD_SET(ClientDGRAM,&fds);
580
581   /* during elections and when expecting a netbios response packet we need
582      to send election packets at one second intervals.
583      XXXX actually, it needs to be the interval (in ms) between time now and the
584      time we are expecting the next netbios packet */
585
586   timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
587   timeout.tv_usec = 0;
588
589   selrtn = sys_select(&fds,&timeout);
590
591   if (FD_ISSET(ClientNMB,&fds))
592     {
593       struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
594       if (packet) {
595 #if 1
596         if (ismyip(packet->ip) &&
597             (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
598           DEBUG(5,("discarding own packet from %s:%d\n",
599                    inet_ntoa(packet->ip),packet->port));          
600           free_packet(packet);
601         } else 
602 #endif
603           {
604             queue_packet(packet);
605           }
606       }
607     }
608
609   if (FD_ISSET(ClientDGRAM,&fds))
610     {
611       struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
612       if (packet) {
613 #if 1
614         if (ismyip(packet->ip) &&
615               (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
616           DEBUG(5,("discarding own packet from %s:%d\n",
617                    inet_ntoa(packet->ip),packet->port));          
618           free_packet(packet);
619         } else
620 #endif 
621           {
622             queue_packet(packet);
623           }
624       }
625     }
626 }
627
628
629
630 /****************************************************************************
631 interpret a node status response. this is pretty hacked: we need two bits of
632 info. a) the name of the workgroup b) the name of the server. it will also
633 add all the names it finds into the namelist.
634 ****************************************************************************/
635 BOOL interpret_node_status(struct subnet_record *d,
636                                 char *p, struct nmb_name *name,int t,
637                            char *serv_name, struct in_addr ip, BOOL bcast)
638 {
639   int level = t==0x20 ? 4 : 0;
640   int numnames = CVAL(p,0);
641   BOOL found = False;
642
643   DEBUG(level,("received %d names\n",numnames));
644
645   p += 1;
646
647   if (serv_name) *serv_name = 0;
648
649   while (numnames--)
650     {
651       char qname[17];
652       int type;
653       fstring flags;
654       int nb_flags;
655       
656       BOOL group = False;
657       BOOL add   = False;
658       
659       *flags = 0;
660       
661       StrnCpy(qname,p,15);
662       type = CVAL(p,15);
663       nb_flags = p[16];
664       trim_string(qname,NULL," ");
665       
666       p += 18;
667       
668       if (NAME_GROUP    (nb_flags)) { strcat(flags,"<GROUP> "); group=True;}
669       if (NAME_BFLAG    (nb_flags)) { strcat(flags,"B "); }
670       if (NAME_PFLAG    (nb_flags)) { strcat(flags,"P "); }
671       if (NAME_MFLAG    (nb_flags)) { strcat(flags,"M "); }
672       if (NAME__FLAG    (nb_flags)) { strcat(flags,"_ "); }
673       if (NAME_DEREG    (nb_flags)) { strcat(flags,"<DEREGISTERING> "); }
674       if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); add=True;}
675       if (NAME_ACTIVE   (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; }
676       if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;}
677       
678       /* might as well update our namelist while we're at it */
679       if (add)
680         {
681           struct in_addr nameip;
682           enum name_source src;
683           
684           if (ismyip(ip)) {
685             nameip = ipzero;
686             src = SELF;
687           } else {
688             nameip = ip;
689             src = STATUS_QUERY;
690           }
691           add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast);
692         } 
693
694       /* we want the server name */
695       if (serv_name && !*serv_name && !group && t == 0)
696         {
697           StrnCpy(serv_name,qname,15);
698           serv_name[15] = 0;
699         }
700       
701       /* looking for a name and type? */
702       if (name && !found && (t == type))
703         {
704           /* take a guess at some of the name types we're going to ask for.
705              evaluate whether they are group names or no... */
706           if (((t == 0x1b || t == 0x1d             ) && !group) ||
707               ((t == 0x20 || t == 0x1c || t == 0x1e) &&  group))
708             {
709               found = True;
710               make_nmb_name(name,qname,type,scope);
711             }
712         }
713       
714       DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
715     }
716   DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
717                IVAL(p,20),IVAL(p,24)));
718   return found;
719 }
720
721
722 /****************************************************************************
723   construct and send a netbios DGRAM
724
725   Note that this currently sends all answers to port 138. thats the
726   wrong things to do! I should send to the requestors port. XXX
727   **************************************************************************/
728 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
729                          char *dstname,int src_type,int dest_type,
730                          struct in_addr dest_ip,struct in_addr src_ip)
731 {
732   struct packet_struct p;
733   struct dgram_packet *dgram = &p.packet.dgram;
734   struct in_addr wins_ip = ipgrp;
735   char *ptr,*p2;
736   char tmp[4];
737
738   /* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */
739   if (ip_equal(wins_ip, dest_ip)) return False;
740
741   bzero((char *)&p,sizeof(p));
742
743   update_name_trn_id();
744
745   dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
746   dgram->header.flags.node_type = M_NODE;
747   dgram->header.flags.first = True;
748   dgram->header.flags.more = False;
749   dgram->header.dgm_id = name_trn_id;
750   dgram->header.source_ip = src_ip;
751   dgram->header.source_port = DGRAM_PORT;
752   dgram->header.dgm_length = 0; /* let build_dgram() handle this */
753   dgram->header.packet_offset = 0;
754   
755   make_nmb_name(&dgram->source_name,srcname,src_type,scope);
756   make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
757
758   ptr = &dgram->data[0];
759
760   /* now setup the smb part */
761   ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
762   memcpy(tmp,ptr,4);
763   set_message(ptr,17,17 + len,True);
764   memcpy(ptr,tmp,4);
765
766   CVAL(ptr,smb_com) = SMBtrans;
767   SSVAL(ptr,smb_vwv1,len);
768   SSVAL(ptr,smb_vwv11,len);
769   SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
770   SSVAL(ptr,smb_vwv13,3);
771   SSVAL(ptr,smb_vwv14,1);
772   SSVAL(ptr,smb_vwv15,1);
773   SSVAL(ptr,smb_vwv16,2);
774   p2 = smb_buf(ptr);
775   strcpy(p2,mailslot);
776   p2 = skip_string(p2,1);
777
778   memcpy(p2,buf,len);
779   p2 += len;
780
781   dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
782
783   p.ip = dest_ip;
784   p.port = DGRAM_PORT;
785   p.fd = ClientDGRAM;
786   p.timestamp = time(NULL);
787   p.packet_type = DGRAM_PACKET;
788
789   return(send_packet(&p));
790 }
791
792