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