23ca0a398f521ddd854e7aac5857acd0e1a9794c
[samba.git] / source3 / nmbd / nmbd_browsesync.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines and daemon - version 2
5    Copyright (C) Andrew Tridgell 1994-1998
6    Copyright (C) Luke Kenneth Casson Leighton 1994-1998
7    Copyright (C) Jeremy Allison 1994-1998
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22    
23 */
24
25 #include "includes.h"
26 #include "smb.h"
27
28 extern int DEBUGLEVEL;
29 extern struct in_addr ipzero;
30 extern pstring global_myname;
31 extern fstring global_myworkgroup;
32
33 /* This is our local master browser list database. */
34 extern ubi_dlList lmb_browserlist[];
35
36 /****************************************************************************
37 As a domain master browser, do a sync with a local master browser.
38 **************************************************************************/
39 static void sync_with_lmb(struct browse_cache_record *browc)
40 {                     
41   struct work_record *work;
42
43   if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) )
44   {
45     if( DEBUGLVL( 0 ) )
46     {
47       dbgtext( "sync_with_lmb:\n" );
48       dbgtext( "Failed to get a workgroup for a local master browser " );
49       dbgtext( "cache entry workgroup " );
50       dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
51     }
52     return;
53   }
54
55   /* We should only be doing this if we are a domain master browser for
56      the given workgroup. Ensure this is so. */
57
58   if(!AM_DOMAIN_MASTER_BROWSER(work))
59   {
60     if( DEBUGLVL( 0 ) )
61     {
62       dbgtext( "sync_with_lmb:\n" );
63       dbgtext( "We are trying to sync with a local master browser " );
64       dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
65       dbgtext( "and we are not a domain master browser on this workgroup.\n" );
66       dbgtext( "Error!\n" );
67     }
68     return;
69   }
70
71   if( DEBUGLVL( 2 ) )
72   {
73     dbgtext( "sync_with_lmb:\n" );
74     dbgtext( "Initiating sync with local master browser " );
75     dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
76     dbgtext( "for workgroup %s\n", browc->work_group );
77   }
78
79   sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);
80
81   browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
82 }
83
84 /****************************************************************************
85 Sync or expire any local master browsers.
86 **************************************************************************/
87 void dmb_expire_and_sync_browser_lists(time_t t)
88 {
89   static time_t last_run = 0;
90   struct browse_cache_record *browc;
91
92   /* Only do this every 20 seconds. */  
93   if (t - last_run < 20) 
94    return;
95
96   last_run = t;
97
98   expire_lmb_browsers(t);
99
100   for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
101        browc;
102        browc = (struct browse_cache_record *)ubi_dlNext( browc ) )
103   {
104     if (browc->sync_time < t)
105       sync_with_lmb(browc);
106   }
107 }
108
109 /****************************************************************************
110 As a local master browser, send an announce packet to the domain master browser.
111 **************************************************************************/
112
113 static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
114 {
115   pstring outbuf;
116   char *p;
117
118   if(ismyip(work->dmb_addr))
119   {
120     if( DEBUGLVL( 2 ) )
121     {
122       dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
123       dbgtext( "We are both a domain and a local master browser for " );
124       dbgtext( "workgroup %s.  ", work->work_group );
125       dbgtext( "Do not announce to ourselves.\n" );
126     }
127     return;
128   }
129
130   memset(outbuf,'\0',sizeof(outbuf));
131   p = outbuf;
132   CVAL(p,0) = ANN_MasterAnnouncement;
133   p++;
134
135   StrnCpy(p,global_myname,15);
136   strupper(p);
137   p = skip_string(p,1);
138
139   if( DEBUGLVL( 4 ) )
140   {
141     dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
142     dbgtext( "Sending local master announce to " );
143     dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
144                                        work->work_group );
145   }
146
147   send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
148                 global_myname, 0x0, work->dmb_name.name, 0x0, 
149                 work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
150
151 }
152
153 /****************************************************************************
154 As a local master browser, do a sync with a domain master browser.
155 **************************************************************************/
156
157 static void sync_with_dmb(struct work_record *work)
158 {
159   if( DEBUGLVL( 2 ) )
160   {
161     dbgtext( "sync_with_dmb:\n" );
162     dbgtext( "Initiating sync with domain master browser " );
163     dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
164     dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
165     dbgtext( "for workgroup %s\n", work->work_group );
166   }
167
168   sync_browse_lists(work, work->dmb_name.name, work->dmb_name.name_type, 
169                     work->dmb_addr, False, True);
170 }
171
172 /****************************************************************************
173   Function called when a node status query to a domain master browser IP succeeds.
174 ****************************************************************************/
175
176 static void domain_master_node_status_success(struct subnet_record *subrec,
177                                               struct userdata_struct *userdata,
178                                               struct res_rec *answers,
179                                               struct in_addr from_ip)
180 {
181   struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
182
183   if( work == NULL )
184   {
185     if( DEBUGLVL( 0 ) )
186     {
187       dbgtext( "domain_master_node_status_success:\n" );
188       dbgtext( "Unable to find workgroup " );
189       dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
190     }
191     return;
192   }
193
194   if( DEBUGLVL( 3 ) )
195   {
196     dbgtext( "domain_master_node_status_success:\n" );
197     dbgtext( "Success in node status for workgroup " );
198     dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
199   }
200
201   /* Go through the list of names found at answers->rdata and look for
202      the first SERVER<0x20> name. */
203
204   if(answers->rdata != NULL)
205   {
206     char *p = answers->rdata;
207     int numnames = CVAL(p, 0);
208
209     p += 1;
210
211     while (numnames--)
212     {
213       char qname[17];
214       uint16 nb_flags;
215       int name_type;
216
217       StrnCpy(qname,p,15);
218       name_type = CVAL(p,15);
219       nb_flags = get_nb_flags(&p[16]);
220       trim_string(qname,NULL," ");
221
222       p += 18;
223
224       if(!(nb_flags & NB_GROUP) && (name_type == 0x20))
225       {
226         struct nmb_name nmbname;
227
228         make_nmb_name(&nmbname, qname, name_type);
229
230         /* Copy the dmb name and IP address
231            into the workgroup struct. */
232
233         work->dmb_name = nmbname;
234         putip((char *)&work->dmb_addr, &from_ip);
235
236         /* Do the local master browser announcement to the domain
237            master browser name and IP. */
238         announce_local_master_browser_to_domain_master_browser( work );
239
240         /* Now synchronise lists with the domain master browser. */
241         sync_with_dmb(work);
242         break;
243       }
244     }
245   }
246   else
247     if( DEBUGLVL( 0 ) )
248     {
249       dbgtext( "domain_master_node_status_success:\n" );
250       dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
251       dbgtext( "%s.\n", inet_ntoa(from_ip) );
252     }
253 }
254
255 /****************************************************************************
256   Function called when a node status query to a domain master browser IP fails.
257 ****************************************************************************/
258
259 static void domain_master_node_status_fail(struct subnet_record *subrec,
260                        struct response_record *rrec)
261 {
262   struct userdata_struct *userdata = rrec->userdata;
263
264   if( DEBUGLVL( 0 ) )
265   {
266     dbgtext( "domain_master_node_status_fail:\n" );
267     dbgtext( "Doing a node status request to the domain master browser\n" );
268     dbgtext( "for workgroup %s ", userdata->data );
269     dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
270     dbgtext( "Cannot sync browser lists.\n" );
271   }
272 }
273
274 /****************************************************************************
275   Function called when a query for a WORKGROUP<1b> name succeeds.
276 ****************************************************************************/
277
278 static void find_domain_master_name_query_success(struct subnet_record *subrec,
279                         struct userdata_struct *userdata_in,
280                         struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
281 {
282   /* 
283    * Unfortunately, finding the IP address of the Domain Master Browser,
284    * as we have here, is not enough. We need to now do a sync to the
285    * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
286    * respond to the SMBSERVER name. To get this name from IP
287    * address we do a Node status request, and look for the first
288    * NAME<0x20> in the response, and take that as the server name.
289    * We also keep a cache of the Domain Master Browser name for this
290    * workgroup in the Workgroup struct, so that if the same IP addess
291    * is returned every time, we don't need to do the node status
292    * request.
293    */
294
295   struct work_record *work;
296   struct nmb_name nmbname;
297   struct userdata_struct *userdata;
298   int size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
299
300   if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) )
301   {
302     if( DEBUGLVL( 0 ) )
303       {
304       dbgtext( "find_domain_master_name_query_success:\n" );
305       dbgtext( "Failed to find workgroup %s\n", q_name->name );
306       }
307     return;
308   }
309
310   /* First check if we already have a dmb for this workgroup. */
311
312   if(!ip_equal(work->dmb_addr, ipzero) && ip_equal(work->dmb_addr, answer_ip))
313   {
314     /* Do the local master browser announcement to the domain
315        master browser name and IP. */
316     announce_local_master_browser_to_domain_master_browser( work );
317
318     /* Now synchronise lists with the domain master browser. */
319     sync_with_dmb(work);
320     return;
321   }
322   else
323     putip((char *)&work->dmb_addr, &ipzero);
324
325   /* Now initiate the node status request. */
326   make_nmb_name(&nmbname,"*",0x0);
327
328   /* Put the workgroup name into the userdata so we know
329      what workgroup we're talking to when the reply comes
330      back. */
331
332   /* Setup the userdata_struct - this is copied so we can use
333      a stack variable for this. */
334   if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
335   {
336     DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
337     return;
338   }
339
340   userdata->copy_fn = NULL;
341   userdata->free_fn = NULL;
342   userdata->userdata_len = strlen(work->work_group)+1;
343   pstrcpy(userdata->data, work->work_group);
344
345   node_status( subrec, &nmbname, answer_ip, 
346                domain_master_node_status_success,
347                domain_master_node_status_fail,
348                userdata);
349
350   zero_free(userdata, size);
351 }
352
353 /****************************************************************************
354   Function called when a query for a WORKGROUP<1b> name fails.
355   ****************************************************************************/
356 static void find_domain_master_name_query_fail(struct subnet_record *subrec,
357                                     struct response_record *rrec,
358                                     struct nmb_name *question_name, int fail_code)
359 {
360   if( DEBUGLVL( 0 ) )
361   {
362     dbgtext( "find_domain_master_name_query_fail:\n" );
363     dbgtext( "Unable to find the Domain Master Browser name " );
364     dbgtext( "%s for the workgroup %s.\n",
365              nmb_namestr(question_name), question_name->name );
366     dbgtext( "Unable to sync browse lists in this workgroup.\n" );
367   }
368 }
369
370 /****************************************************************************
371 As a local master browser for a workgroup find the domain master browser
372 name, announce ourselves as local master browser to it and then pull the
373 full domain browse lists from it onto the given subnet.
374 **************************************************************************/
375
376 void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
377                                                    struct work_record *work)
378 {
379   struct nmb_name nmbname;
380
381   /* Only do this if we are using a WINS server. */
382   if(we_are_a_wins_client() == False)
383   {
384     if( DEBUGLVL( 10 ) )
385     {
386       dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
387       dbgtext( "Ignoring, as we are not a WINS client.\n" );
388     }
389     return;
390   }
391
392   make_nmb_name(&nmbname,work->work_group,0x1b);
393
394   /* First, query for the WORKGROUP<1b> name from the WINS server. */
395   query_name(unicast_subnet, nmbname.name, nmbname.name_type,
396              find_domain_master_name_query_success,
397              find_domain_master_name_query_fail,
398              NULL);
399
400 }
401
402 /****************************************************************************
403   Function called when a node status query to a domain master browser IP succeeds.
404   This function is only called on query to a Samba 1.9.18 or above WINS server.
405
406   Note that adding the workgroup name is enough for this workgroup to be
407   browsable by clients, as clients query the WINS server or broadcast 
408   nets for the WORKGROUP<1b> name when they want to browse a workgroup
409   they are not in. We do not need to do a sync with this Domain Master
410   Browser in order for our browse clients to see machines in this workgroup.
411   JRA.
412 ****************************************************************************/
413
414 static void get_domain_master_name_node_status_success(struct subnet_record *subrec,
415                                               struct userdata_struct *userdata,
416                                               struct res_rec *answers,
417                                               struct in_addr from_ip)
418 {
419   struct work_record *work;
420   fstring server_name;
421
422   server_name[0] = 0;
423
424   if( DEBUGLVL( 3 ) )
425   {
426     dbgtext( "get_domain_master_name_node_status_success:\n" );
427     dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
428   }
429
430   /* 
431    * Go through the list of names found at answers->rdata and look for
432    * the first WORKGROUP<0x1b> name.
433    */
434
435   if(answers->rdata != NULL)
436   {
437     char *p = answers->rdata;
438     int numnames = CVAL(p, 0);
439
440     p += 1;
441
442     while (numnames--)
443     {
444       char qname[17];
445       uint16 nb_flags;
446       int name_type;
447
448       StrnCpy(qname,p,15);
449       name_type = CVAL(p,15);
450       nb_flags = get_nb_flags(&p[16]);
451       trim_string(qname,NULL," ");
452
453       p += 18;
454
455       if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && 
456          server_name[0] == 0) {
457               /* this is almost certainly the server netbios name */
458               fstrcpy(server_name, qname);
459               continue;
460       }
461
462       if(!(nb_flags & NB_GROUP) && (name_type == 0x1b))
463       {
464         if( DEBUGLVL( 5 ) )
465         {
466           dbgtext( "get_domain_master_name_node_status_success:\n" );
467           dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
468           dbgtext( "is a domain master browser for workgroup " );
469           dbgtext( "%s. Adding this name.\n", qname );
470         }
471
472         /* 
473          * If we don't already know about this workgroup, add it
474          * to the workgroup list on the unicast_subnet.
475          */
476         if((work = find_workgroup_on_subnet( subrec, qname)) == NULL)
477         {
478                 struct nmb_name nmbname;
479                 /* 
480                  * Add it - with an hour in the cache.
481                  */
482                 if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
483                         return;
484
485                 /* remember who the master is */
486                 fstrcpy(work->local_master_browser_name, server_name);
487                 make_nmb_name(&nmbname, server_name, 0x20);
488                 work->dmb_name = nmbname;
489                 work->dmb_addr = from_ip;
490         }
491         break;
492       }
493     }
494   }
495   else
496     if( DEBUGLVL( 0 ) )
497     {
498       dbgtext( "get_domain_master_name_node_status_success:\n" );
499       dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
500       dbgtext( "%s.\n", inet_ntoa(from_ip) );
501     }
502 }
503
504 /****************************************************************************
505   Function called when a node status query to a domain master browser IP fails.
506 ****************************************************************************/
507
508 static void get_domain_master_name_node_status_fail(struct subnet_record *subrec,
509                        struct response_record *rrec)
510 {
511   if( DEBUGLVL( 0 ) )
512   {
513     dbgtext( "get_domain_master_name_node_status_fail:\n" );
514     dbgtext( "Doing a node status request to the domain master browser " );
515     dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
516     dbgtext( "Cannot get workgroup name.\n" );
517   }
518 }
519
520 /****************************************************************************
521   Function called when a query for *<1b> name succeeds.
522 ****************************************************************************/
523
524 static void find_all_domain_master_names_query_success(struct subnet_record *subrec,
525                         struct userdata_struct *userdata_in,
526                         struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
527 {
528   /* 
529    * We now have a list of all the domain master browsers for all workgroups
530    * that have registered with the WINS server. Now do a node status request
531    * to each one and look for the first 1b name in the reply. This will be
532    * the workgroup name that we will add to the unicast subnet as a 'non-local'
533    * workgroup.
534    */
535
536   struct nmb_name nmbname;
537   struct in_addr send_ip;
538   int i;
539
540   if( DEBUGLVL( 5 ) )
541   {
542     dbgtext( "find_all_domain_master_names_query_succes:\n" );
543     dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
544     dbgtext( "IP addresses for Domain Master Browsers.\n" );
545   }
546
547   for(i = 0; i < rrec->rdlength / 6; i++)
548   {
549     /* Initiate the node status requests. */
550     make_nmb_name(&nmbname, "*", 0);
551
552     putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
553
554     /* 
555      * Don't send node status requests to ourself.
556      */
557
558     if(ismyip( send_ip ))
559     {
560       if( DEBUGLVL( 5 ) )
561       {
562         dbgtext( "find_all_domain_master_names_query_succes:\n" );
563         dbgtext( "Not sending node status to our own IP " );
564         dbgtext( "%s.\n", inet_ntoa(send_ip) );
565       }
566       continue;
567     }
568
569     if( DEBUGLVL( 5 ) )
570     {
571       dbgtext( "find_all_domain_master_names_query_success:\n" );
572       dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
573     }
574
575     node_status( subrec, &nmbname, send_ip, 
576                  get_domain_master_name_node_status_success,
577                  get_domain_master_name_node_status_fail,
578                  NULL);
579   }
580 }
581
582 /****************************************************************************
583   Function called when a query for *<1b> name fails.
584   ****************************************************************************/
585 static void find_all_domain_master_names_query_fail(struct subnet_record *subrec,
586                                     struct response_record *rrec,
587                                     struct nmb_name *question_name, int fail_code)
588 {
589   if( DEBUGLVL( 10 ) )
590   {
591     dbgtext( "find_domain_master_name_query_fail:\n" );
592     dbgtext( "WINS server did not reply to a query for name " );
593     dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
594     dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
595   }
596 }
597
598 /****************************************************************************
599  If we are a domain master browser on the unicast subnet, do a query to the
600  WINS server for the *<1b> name. This will only work to a Samba WINS server,
601  so ignore it if we fail. If we succeed, contact each of the IP addresses in
602  turn and do a node status request to them. If this succeeds then look for a
603  <1b> name in the reply - this is the workgroup name. Add this to the unicast
604  subnet. This is expensive, so we only do this every 15 minutes.
605 **************************************************************************/
606 void collect_all_workgroup_names_from_wins_server(time_t t)
607 {
608   static time_t lastrun = 0;
609   struct work_record *work;
610   struct nmb_name nmbname;
611
612   /* Only do this if we are using a WINS server. */
613   if(we_are_a_wins_client() == False)
614     return;
615
616   /* Check to see if we are a domain master browser on the unicast subnet. */
617   if((work = find_workgroup_on_subnet( unicast_subnet, global_myworkgroup)) == NULL)
618   {
619     if( DEBUGLVL( 0 ) )
620     {
621       dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
622       dbgtext( "Cannot find my workgroup %s ", global_myworkgroup );
623       dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
624     }
625     return;
626   }
627
628   if(!AM_DOMAIN_MASTER_BROWSER(work))
629     return;
630
631   if ((lastrun != 0) && (t < lastrun + (15 * 60)))
632     return;
633      
634   lastrun = t;
635
636   make_nmb_name(&nmbname,"*",0x1b);
637
638   /* First, query for the *<1b> name from the WINS server. */
639   query_name(unicast_subnet, nmbname.name, nmbname.name_type,
640              find_all_domain_master_names_query_success,
641              find_all_domain_master_names_query_fail,
642              NULL);
643
644
645
646 /****************************************************************************
647  If we are a domain master browser on the unicast subnet, do a regular sync
648  with all other DMBs that we know of on that subnet.
649
650 To prevent exponential network traffic with large numbers of workgroups
651 we use a randomised system where sync probability is inversely proportional
652 to the number of known workgroups
653 **************************************************************************/
654 void sync_all_dmbs(time_t t)
655 {
656         static time_t lastrun = 0;
657         struct work_record *work;
658         int count=0;
659
660         /* Only do this if we are using a WINS server. */
661         if(we_are_a_wins_client() == False)
662                 return;
663
664         /* Check to see if we are a domain master browser on the
665            unicast subnet. */
666         work = find_workgroup_on_subnet(unicast_subnet, global_myworkgroup);
667         if (!work) return;
668
669         if (!AM_DOMAIN_MASTER_BROWSER(work))
670                 return;
671
672         if ((lastrun != 0) && (t < lastrun + (5 * 60)))
673                 return;
674      
675         /* count how many syncs we might need to do */
676         for (work=unicast_subnet->workgrouplist; work; work = work->next) {
677                 if (strcmp(global_myworkgroup, work->work_group)) {
678                         count++;
679                 }
680         }
681
682         /* sync with a probability of 1/count */
683         for (work=unicast_subnet->workgrouplist; work; work = work->next) {
684                 if (strcmp(global_myworkgroup, work->work_group)) {
685                         if (((unsigned)sys_random()) % count != 0) continue;
686
687                         lastrun = t;
688
689                         if (!work->dmb_name.name[0]) {
690                                 /* we don't know the DMB - assume it is
691                                    the same as the unicast local master */
692                                 make_nmb_name(&work->dmb_name, 
693                                               work->local_master_browser_name,
694                                               0x20);
695                         }
696
697                         DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
698                                  work->dmb_name.name, 
699                                  inet_ntoa(work->dmb_addr)));
700                         sync_browse_lists(work, 
701                                           work->dmb_name.name,
702                                           work->dmb_name.name_type, 
703                                           work->dmb_addr, False, False);
704                 }
705         }
706