c79c30d46f6001f5d68956f4935f45559a697e99
[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 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->state)
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 *d1 = find_subnet(ipgrp);
105                                 if (d1)
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(d1, 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 state_type state,
388                             char *name,int name_type,int nb_flags, time_t ttl,
389                             BOOL bcast,BOOL recurse,struct in_addr to_ip)
390 {
391   /* XXXX note: please see rfc1001.txt section 10 for details on this
392      function: it is currently inappropriate to use this - it will do
393      for now - once there is a clarification of B, M and P nodes and
394      which one samba is supposed to be
395    */
396
397   if ((!lp_wins_support()) && (*lp_wins_server()))
398     {
399       /* samba is not a WINS server, and we are using a WINS server */
400       struct in_addr wins_ip;
401       wins_ip = *interpret_addr2(lp_wins_server());
402
403       if (!zero_ip(wins_ip))
404         {
405           bcast = False;
406           to_ip = wins_ip;
407         }
408       else
409         {
410           /* oops. smb.conf's wins server parameter MUST be a host_name 
411              or an ip_address. */
412           DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
413         }
414     }
415
416   if (zero_ip(to_ip)) return;
417
418   queue_netbios_packet(d,fd, quest_type, state, 
419                        name, name_type, nb_flags, ttl,
420                        bcast, recurse, to_ip);
421 }
422
423 /****************************************************************************
424   create a name query response record
425   **************************************************************************/
426 static struct response_record *
427 make_response_queue_record(enum state_type state,int id,int fd,
428                                 int quest_type, char *name,int type, int nb_flags, time_t ttl,
429                                 BOOL bcast,BOOL recurse, struct in_addr ip)
430 {
431   struct response_record *n;
432         
433   if (!name || !name[0]) return NULL;
434         
435   if (!(n = (struct response_record *)malloc(sizeof(*n)))) 
436     return(NULL);
437
438   n->response_id = id;
439   n->state = state;
440   n->fd = fd;
441   n->quest_type = quest_type;
442   make_nmb_name(&n->name, name, type, scope);
443   n->nb_flags = nb_flags;
444   n->ttl = ttl;
445   n->bcast = bcast;
446   n->recurse = recurse;
447   n->to_ip = ip;
448
449   n->repeat_interval = 1; /* XXXX should be in ms */
450   n->repeat_count = 4;
451   n->repeat_time = time(NULL) + n->repeat_interval;
452
453   n->num_msgs = 0;
454
455   num_response_packets++; /* count of total number of packets still around */
456
457   return n;
458 }
459
460
461 /****************************************************************************
462   initiate a netbios name query to find someone's or someones' IP
463   this is intended to be used (not exclusively) for broadcasting to
464   master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
465   complete lists across a wide area network
466   ****************************************************************************/
467 void queue_netbios_packet(struct subnet_record *d,
468                         int fd,int quest_type,enum state_type state,char *name,
469                         int name_type,int nb_flags, time_t ttl,
470                         BOOL bcast,BOOL recurse, struct in_addr to_ip)
471 {
472   struct in_addr wins_ip = ipgrp;
473   struct response_record *n;
474   uint16 id = 0xffff;
475
476   /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
477   if (ip_equal(wins_ip, to_ip)) return;
478
479   initiate_netbios_packet(&id, fd, quest_type, name, name_type,
480                                       nb_flags, bcast, recurse, to_ip);
481
482   if (id == 0xffff) return;
483   
484   if ((n = make_response_queue_record(state,id,fd,
485                                                 quest_type,name,name_type,nb_flags,ttl,
486                                                 bcast,recurse,to_ip)))
487     {
488       add_response_record(d,n);
489     }
490 }
491
492
493 /****************************************************************************
494   find a response in a subnet's name query response list. 
495   **************************************************************************/
496 struct response_record *find_response_record(struct subnet_record **d,
497                                 uint16 id)
498 {  
499   struct response_record *n;
500
501   if (!d) return NULL;
502
503   for ((*d) = subnetlist; (*d); (*d) = (*d)->next)
504   {
505     for (n = (*d)->responselist; n; n = n->next)
506     {
507       if (n->response_id == id) {
508          return n;
509       }
510     }
511   }
512
513   *d = NULL;
514
515   return NULL;
516 }
517
518
519 /*******************************************************************
520   the global packet linked-list. incoming entries are added to the
521   end of this list.  it is supposed to remain fairly short so we
522   won't bother with an end pointer.
523   ******************************************************************/
524 static struct packet_struct *packet_queue = NULL;
525
526 /*******************************************************************
527   queue a packet into the packet queue
528   ******************************************************************/
529 void queue_packet(struct packet_struct *packet)
530 {
531   struct packet_struct *p;
532
533   if (!packet_queue) {
534     packet->prev = NULL;
535     packet->next = NULL;
536     packet_queue = packet;
537     return;
538   }
539   
540   /* find the bottom */
541   for (p=packet_queue;p->next;p=p->next) ;
542
543   p->next = packet;
544   packet->next = NULL;
545   packet->prev = p;
546 }
547
548 /*******************************************************************
549   run elements off the packet queue till its empty
550   ******************************************************************/
551 void run_packet_queue()
552 {
553   struct packet_struct *p;
554
555   while ((p=packet_queue))
556     {
557       switch (p->packet_type)
558         {
559         case NMB_PACKET:
560           process_nmb(p);
561           break;
562           
563         case DGRAM_PACKET:
564           process_dgram(p);
565           break;
566         }
567       
568       packet_queue = packet_queue->next;
569       if (packet_queue) packet_queue->prev = NULL;
570       free_packet(p);
571     }
572 }
573
574 /****************************************************************************
575   listens for NMB or DGRAM packets, and queues them
576   ***************************************************************************/
577 void listen_for_packets(BOOL run_election)
578 {
579   fd_set fds;
580   int selrtn;
581   struct timeval timeout;
582
583   FD_ZERO(&fds);
584   FD_SET(ClientNMB,&fds);
585   FD_SET(ClientDGRAM,&fds);
586
587   /* during elections and when expecting a netbios response packet we need
588      to send election packets at one second intervals.
589      XXXX actually, it needs to be the interval (in ms) between time now and the
590      time we are expecting the next netbios packet */
591
592   timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
593   timeout.tv_usec = 0;
594
595   selrtn = sys_select(&fds,&timeout);
596
597   if (FD_ISSET(ClientNMB,&fds))
598     {
599       struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
600       if (packet) {
601 #if 1
602         if (ismyip(packet->ip) &&
603             (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
604           DEBUG(5,("discarding own packet from %s:%d\n",
605                    inet_ntoa(packet->ip),packet->port));          
606           free_packet(packet);
607         } else 
608 #endif
609           {
610             queue_packet(packet);
611           }
612       }
613     }
614
615   if (FD_ISSET(ClientDGRAM,&fds))
616     {
617       struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
618       if (packet) {
619 #if 1
620         if (ismyip(packet->ip) &&
621               (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
622           DEBUG(5,("discarding own packet from %s:%d\n",
623                    inet_ntoa(packet->ip),packet->port));          
624           free_packet(packet);
625         } else
626 #endif 
627           {
628             queue_packet(packet);
629           }
630       }
631     }
632 }
633
634
635
636 /****************************************************************************
637 interpret a node status response. this is pretty hacked: we need two bits of
638 info. a) the name of the workgroup b) the name of the server. it will also
639 add all the names it finds into the namelist.
640 ****************************************************************************/
641 BOOL interpret_node_status(struct subnet_record *d,
642                                 char *p, struct nmb_name *name,int t,
643                            char *serv_name, struct in_addr ip, BOOL bcast)
644 {
645   int level = t==0x20 ? 4 : 0;
646   int numnames = CVAL(p,0);
647   BOOL found = False;
648
649   DEBUG(level,("received %d names\n",numnames));
650
651   p += 1;
652
653   if (serv_name) *serv_name = 0;
654
655   while (numnames--)
656     {
657       char qname[17];
658       int type;
659       fstring flags;
660       int nb_flags;
661       
662       BOOL group = False;
663       BOOL add   = False;
664       
665       *flags = 0;
666       
667       StrnCpy(qname,p,15);
668       type = CVAL(p,15);
669       nb_flags = p[16];
670       trim_string(qname,NULL," ");
671       
672       p += 18;
673       
674       if (NAME_GROUP    (nb_flags)) { strcat(flags,"<GROUP> "); group=True;}
675       if (NAME_BFLAG    (nb_flags)) { strcat(flags,"B "); }
676       if (NAME_PFLAG    (nb_flags)) { strcat(flags,"P "); }
677       if (NAME_MFLAG    (nb_flags)) { strcat(flags,"M "); }
678       if (NAME__FLAG    (nb_flags)) { strcat(flags,"_ "); }
679       if (NAME_DEREG    (nb_flags)) { strcat(flags,"<DEREGISTERING> "); }
680       if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); add=True;}
681       if (NAME_ACTIVE   (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; }
682       if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;}
683       
684       /* might as well update our namelist while we're at it */
685       if (add)
686         {
687           struct in_addr nameip;
688           enum name_source src;
689           
690           if (ismyip(ip)) {
691             nameip = ipzero;
692             src = SELF;
693           } else {
694             nameip = ip;
695             src = STATUS_QUERY;
696           }
697           add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast);
698         } 
699
700       /* we want the server name */
701       if (serv_name && !*serv_name && !group && t == 0)
702         {
703           StrnCpy(serv_name,qname,15);
704           serv_name[15] = 0;
705         }
706       
707       /* looking for a name and type? */
708       if (name && !found && (t == type))
709         {
710           /* take a guess at some of the name types we're going to ask for.
711              evaluate whether they are group names or no... */
712           if (((t == 0x1b || t == 0x1d             ) && !group) ||
713               ((t == 0x20 || t == 0x1c || t == 0x1e) &&  group))
714             {
715               found = True;
716               make_nmb_name(name,qname,type,scope);
717             }
718         }
719       
720       DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags));
721     }
722   DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
723                IVAL(p,20),IVAL(p,24)));
724   return found;
725 }
726
727
728 /****************************************************************************
729   construct and send a netbios DGRAM
730
731   Note that this currently sends all answers to port 138. thats the
732   wrong things to do! I should send to the requestors port. XXX
733   **************************************************************************/
734 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
735                          char *dstname,int src_type,int dest_type,
736                          struct in_addr dest_ip,struct in_addr src_ip)
737 {
738   struct packet_struct p;
739   struct dgram_packet *dgram = &p.packet.dgram;
740   struct in_addr wins_ip = ipgrp;
741   char *ptr,*p2;
742   char tmp[4];
743
744   /* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */
745   if (ip_equal(wins_ip, dest_ip)) return False;
746
747   bzero((char *)&p,sizeof(p));
748
749   update_name_trn_id();
750
751   dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
752   dgram->header.flags.node_type = M_NODE;
753   dgram->header.flags.first = True;
754   dgram->header.flags.more = False;
755   dgram->header.dgm_id = name_trn_id;
756   dgram->header.source_ip = src_ip;
757   dgram->header.source_port = DGRAM_PORT;
758   dgram->header.dgm_length = 0; /* let build_dgram() handle this */
759   dgram->header.packet_offset = 0;
760   
761   make_nmb_name(&dgram->source_name,srcname,src_type,scope);
762   make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
763
764   ptr = &dgram->data[0];
765
766   /* now setup the smb part */
767   ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
768   memcpy(tmp,ptr,4);
769   set_message(ptr,17,17 + len,True);
770   memcpy(ptr,tmp,4);
771
772   CVAL(ptr,smb_com) = SMBtrans;
773   SSVAL(ptr,smb_vwv1,len);
774   SSVAL(ptr,smb_vwv11,len);
775   SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
776   SSVAL(ptr,smb_vwv13,3);
777   SSVAL(ptr,smb_vwv14,1);
778   SSVAL(ptr,smb_vwv15,1);
779   SSVAL(ptr,smb_vwv16,2);
780   p2 = smb_buf(ptr);
781   strcpy(p2,mailslot);
782   p2 = skip_string(p2,1);
783
784   memcpy(p2,buf,len);
785   p2 += len;
786
787   dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
788
789   p.ip = dest_ip;
790   p.port = DGRAM_PORT;
791   p.fd = ClientDGRAM;
792   p.timestamp = time(NULL);
793   p.packet_type = DGRAM_PACKET;
794
795   return(send_packet(&p));
796 }
797
798