update to 9.7.1-P2
[tridge/bind9.git] / contrib / sdb / ldap / zone2ldap.c
1 /*
2  * Copyright (C) 2001 Jeff McNeil <jeff@snapcase.g-rock.net>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  * 
8  * Change Log
9  *
10  * Tue May  1 19:19:54 EDT 2001 - Jeff McNeil
11  * Update to objectClass code, and add_to_rr_list function
12  * (I need to rename that) to support the dNSZone schema,
13  * ditched dNSDomain2 schema support. Version 0.3-ALPHA
14  */
15
16 #include <errno.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <getopt.h>
21
22 #include <isc/buffer.h>
23 #include <isc/entropy.h>
24 #include <isc/hash.h>
25 #include <isc/mem.h>
26 #include <isc/print.h>
27 #include <isc/result.h>
28
29 #include <dns/db.h>
30 #include <dns/dbiterator.h>
31 #include <dns/fixedname.h>
32 #include <dns/name.h>
33 #include <dns/rdata.h>
34 #include <dns/rdataset.h>
35 #include <dns/rdatasetiter.h>
36 #include <dns/result.h>
37 #include <dns/rdatatype.h>
38
39 #include <ldap.h>
40
41 #define DNS_OBJECT 6
42 #define DNS_TOP    2
43
44 #define VERSION    "0.4-ALPHA"
45
46 #define NO_SPEC 0 
47 #define WI_SPEC  1
48
49 /* Global Zone Pointer */
50 char *gbl_zone = NULL;
51
52 typedef struct LDAP_INFO
53 {
54   char *dn;
55   LDAPMod **attrs;
56   struct LDAP_INFO *next;
57   int attrcnt;
58 }
59 ldap_info;
60
61 /* usage Info */
62 void usage ();
63
64 /* Add to the ldap dit */
65 void add_ldap_values (ldap_info * ldinfo);
66
67 /* Init an ldap connection */
68 void init_ldap_conn ();
69
70 /* Ldap error checking */
71 void ldap_result_check (char *msg, char *dn, int err);
72
73 /* Put a hostname into a char ** array */
74 char **hostname_to_dn_list (char *hostname, char *zone, unsigned int flags);
75
76 /* Find out how many items are in a char ** array */
77 int get_attr_list_size (char **tmp);
78
79 /* Get a DN */
80 char *build_dn_from_dc_list (char **dc_list, unsigned int ttl, int flag);
81
82 /* Add to RR list */
83 void add_to_rr_list (char *dn, char *name, char *type, char *data,
84                      unsigned int ttl, unsigned int flags);
85
86 /* Error checking */
87 void isc_result_check (isc_result_t res, char *errorstr);
88
89 /* Generate LDIF Format files */
90 void generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata,
91                     unsigned int ttl);
92
93 /* head pointer to the list */
94 ldap_info *ldap_info_base = NULL;
95
96 char *argzone, *ldapbase, *binddn, *bindpw = NULL;
97 char *ldapsystem = "localhost";
98 static char *objectClasses[] =
99   { "top", "dNSZone", NULL };
100 static char *topObjectClasses[] = { "top", NULL };
101 LDAP *conn;
102 unsigned int debug = 0;
103
104 #ifdef DEBUG
105 debug = 1;
106 #endif
107
108 int
109 main (int *argc, char **argv)
110 {
111   isc_mem_t *mctx = NULL;
112   isc_entropy_t *ectx = NULL;
113   isc_result_t result;
114   char *basedn;
115   ldap_info *tmp;
116   LDAPMod *base_attrs[2];
117   LDAPMod base;
118   isc_buffer_t buff;
119   char *zonefile;
120   char fullbasedn[1024];
121   char *ctmp;
122   dns_fixedname_t fixedzone, fixedname;
123   dns_rdataset_t rdataset;
124   char **dc_list;
125   dns_rdata_t rdata = DNS_RDATA_INIT;
126   dns_rdatasetiter_t *riter;
127   dns_name_t *zone, *name;
128   dns_db_t *db = NULL;
129   dns_dbiterator_t *dbit = NULL;
130   dns_dbnode_t *node;
131   extern char *optarg;
132   extern int optind, opterr, optopt;
133   int create_base = 0;
134   int topt;
135
136   if ((int) argc < 2)
137     {
138       usage ();
139       exit (-1);
140     }
141
142   while ((topt = getopt ((int) argc, argv, "D:w:b:z:f:h:?dcv")) != -1)
143     {
144       switch (topt)
145         {
146         case 'v':
147                 printf("%s\n", VERSION);
148                 exit(0);
149         case 'c':
150           create_base++;
151           break;
152         case 'd':
153           debug++;
154           break;
155         case 'D':
156           binddn = strdup (optarg);
157           break;
158         case 'w':
159           bindpw = strdup (optarg);
160           break;
161         case 'b':
162           ldapbase = strdup (optarg);
163           break;
164         case 'z':
165           argzone = strdup (optarg);
166           // We wipe argzone all to hell when we parse it for the DN */
167           gbl_zone = strdup(argzone);
168           break;
169         case 'f':
170           zonefile = strdup (optarg);
171           break;
172         case 'h':
173           ldapsystem = strdup (optarg);
174           break;
175         case '?':
176         default:
177           usage ();
178           exit (0);
179         }
180     }
181
182   if ((argzone == NULL) || (zonefile == NULL))
183     {
184       usage ();
185       exit (-1);
186     }
187
188   if (debug)
189     printf ("Initializing ISC Routines, parsing zone file\n");
190
191   result = isc_mem_create (0, 0, &mctx);
192   isc_result_check (result, "isc_mem_create");
193
194   result = isc_entropy_create(mctx, &ectx);
195   isc_result_check (result, "isc_entropy_create");
196
197   result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
198   isc_result_check (result, "isc_hash_create");
199
200   isc_buffer_init (&buff, argzone, strlen (argzone));
201   isc_buffer_add (&buff, strlen (argzone));
202   dns_fixedname_init (&fixedzone);
203   zone = dns_fixedname_name (&fixedzone);
204   result = dns_name_fromtext (zone, &buff, dns_rootname, 0, NULL);
205   isc_result_check (result, "dns_name_fromtext");
206
207   result = dns_db_create (mctx, "rbt", zone, dns_dbtype_zone,
208                           dns_rdataclass_in, 0, NULL, &db);
209   isc_result_check (result, "dns_db_create");
210
211   result = dns_db_load (db, zonefile);
212   isc_result_check (result, "Check Zone Syntax: dns_db_load");
213
214   result = dns_db_createiterator (db, 0, &dbit);
215   isc_result_check (result, "dns_db_createiterator");
216
217   result = dns_dbiterator_first (dbit);
218   isc_result_check (result, "dns_dbiterator_first");
219
220   dns_fixedname_init (&fixedname);
221   name = dns_fixedname_name (&fixedname);
222   dns_rdataset_init (&rdataset);
223   dns_rdata_init (&rdata);
224
225   while (result == ISC_R_SUCCESS)
226     {
227       node = NULL;
228       result = dns_dbiterator_current (dbit, &node, name);
229
230       if (result == ISC_R_NOMORE)
231         break;
232
233       isc_result_check (result, "dns_dbiterator_current");
234
235       riter = NULL;
236       result = dns_db_allrdatasets (db, node, NULL, 0, &riter);
237       isc_result_check (result, "dns_db_allrdatasets");
238
239       result = dns_rdatasetiter_first (riter);
240       //isc_result_check(result, "dns_rdatasetiter_first");
241
242       while (result == ISC_R_SUCCESS)
243         {
244           dns_rdatasetiter_current (riter, &rdataset);
245           result = dns_rdataset_first (&rdataset);
246           isc_result_check (result, "dns_rdatasetiter_current");
247
248           while (result == ISC_R_SUCCESS)
249             {
250               dns_rdataset_current (&rdataset, &rdata);
251               generate_ldap (name, &rdata, rdataset.ttl);
252               dns_rdata_reset (&rdata);
253               result = dns_rdataset_next (&rdataset);
254             }
255           dns_rdataset_disassociate (&rdataset);
256           result = dns_rdatasetiter_next (riter);
257
258         }
259       dns_rdatasetiter_destroy (&riter);
260       result = dns_dbiterator_next (dbit);
261
262     }
263
264   /* Initialize the LDAP Connection */
265   if (debug)
266     printf ("Initializing LDAP Connection to %s as %s\n", ldapsystem, binddn);
267
268   init_ldap_conn ();
269
270   if (create_base)
271     {
272       if (debug)
273         printf ("Creating base zone DN %s\n", argzone);
274
275       dc_list = hostname_to_dn_list (argzone, argzone, DNS_TOP);
276       basedn = build_dn_from_dc_list (dc_list, 0, NO_SPEC);
277
278       for (ctmp = &basedn[strlen (basedn)]; ctmp >= &basedn[0]; ctmp--)
279         {
280           if ((*ctmp == ',') || (ctmp == &basedn[0]))
281             {
282               base.mod_op = LDAP_MOD_ADD;
283               base.mod_type = "objectClass";
284               base.mod_values = topObjectClasses;
285               base_attrs[0] = &base;
286               base_attrs[1] = NULL;
287
288               if (ldapbase)
289                 {
290                   if (ctmp != &basedn[0])
291                     sprintf (fullbasedn, "%s,%s", ctmp + 1, ldapbase);
292                   else
293                     sprintf (fullbasedn, "%s,%s", ctmp, ldapbase);
294
295                 }
296               else
297                 {
298                   if (ctmp != &basedn[0])
299                     sprintf (fullbasedn, "%s", ctmp + 1);
300                   else
301                     sprintf (fullbasedn, "%s", ctmp);
302                 }
303               result = ldap_add_s (conn, fullbasedn, base_attrs);
304               ldap_result_check ("intial ldap_add_s", fullbasedn, result);
305             }
306
307         }
308     }
309   else
310     {
311       if (debug)
312         printf ("Skipping zone base dn creation for %s\n", argzone);
313     }
314
315   for (tmp = ldap_info_base; tmp != NULL; tmp = tmp->next)
316     {
317
318       if (debug)
319         printf ("Adding DN: %s\n", tmp->dn);
320
321       add_ldap_values (tmp);
322     }
323
324   if (debug)
325         printf("Operation Complete.\n");
326
327   /* Cleanup */
328   isc_hash_destroy();
329   isc_entropy_detach(&ectx);
330   isc_mem_destroy(&mctx);
331
332   return 0;
333 }
334
335
336 /* Check the status of an isc_result_t after any isc routines.
337  * I should probably rename this function, as not to cause any
338  * confusion with the isc* routines. Will exit on error. */
339 void
340 isc_result_check (isc_result_t res, char *errorstr)
341 {
342   if (res != ISC_R_SUCCESS)
343     {
344       fprintf (stderr, " %s: %s\n", errorstr, isc_result_totext (res));
345       exit (-1);
346     }
347 }
348
349
350 /* Takes DNS information, in bind data structure format, and adds textual
351  * zone information to the LDAP run queue. */
352 void
353 generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, unsigned int ttl)
354 {
355   unsigned char name[DNS_NAME_MAXTEXT + 1];
356   unsigned int len;
357   unsigned char type[20];
358   unsigned char data[2048];
359   char **dc_list;
360   char *dn;
361
362   isc_buffer_t buff;
363   isc_result_t result;
364
365   isc_buffer_init (&buff, name, sizeof (name));
366   result = dns_name_totext (dnsname, ISC_TRUE, &buff);
367   isc_result_check (result, "dns_name_totext");
368   name[isc_buffer_usedlength (&buff)] = 0;
369
370   isc_buffer_init (&buff, type, sizeof (type));
371   result = dns_rdatatype_totext (rdata->type, &buff);
372   isc_result_check (result, "dns_rdatatype_totext");
373   type[isc_buffer_usedlength (&buff)] = 0;
374
375   isc_buffer_init (&buff, data, sizeof (data));
376   result = dns_rdata_totext (rdata, NULL, &buff);
377   isc_result_check (result, "dns_rdata_totext");
378   data[isc_buffer_usedlength (&buff)] = 0;
379
380   dc_list = hostname_to_dn_list (name, argzone, DNS_OBJECT);
381   len = (get_attr_list_size (dc_list) - 2);
382   dn = build_dn_from_dc_list (dc_list, ttl, WI_SPEC);
383
384   if (debug)
385     printf ("Adding %s (%s %s) to run queue list.\n", dn, type, data);
386
387   add_to_rr_list (dn, dc_list[len], type, data, ttl, DNS_OBJECT);
388 }
389
390
391 /* Locate an item in the Run queue linked list, by DN. Used by functions
392  * which add items to the run queue.
393  */
394 ldap_info *
395 locate_by_dn (char *dn)
396 {
397   ldap_info *tmp;
398   for (tmp = ldap_info_base; tmp != (ldap_info *) NULL; tmp = tmp->next)
399     {
400       if (!strncmp (tmp->dn, dn, strlen (dn)))
401         return tmp;
402     }
403   return (ldap_info *) NULL;
404 }
405
406
407
408 /* Take textual zone data, and add to the LDAP Run queue. This works like so:
409  * If locate_by_dn does not return, alloc a new ldap_info structure, and then
410  * calloc a LDAPMod array, fill in the default "everyone needs this" information,
411  * including object classes and dc's. If it locate_by_dn does return, then we'll
412  * realloc for more LDAPMod structs, and appened the new data.  If an LDAPMod exists
413  * for the parameter we're adding, then we'll realloc the mod_values array, and 
414  * add the new value to the existing LDAPMod. Finnaly, it assures linkage exists
415  * within the Run queue linked ilst*/
416
417 void
418 add_to_rr_list (char *dn, char *name, char *type,
419                 char *data, unsigned int ttl, unsigned int flags)
420 {
421   int i;
422   int x;
423   ldap_info *tmp;
424   int attrlist;
425   char ldap_type_buffer[128];
426   char charttl[64];
427
428
429   if ((tmp = locate_by_dn (dn)) == NULL)
430     {
431
432       /* There wasn't one already there, so we need to allocate a new one,
433        * and stick it on the list */
434
435       tmp = (ldap_info *) malloc (sizeof (ldap_info));
436       if (tmp == (ldap_info *) NULL)
437         {
438           fprintf (stderr, "malloc: %s\n", strerror (errno));
439           ldap_unbind_s (conn);
440           exit (-1);
441         }
442
443       tmp->dn = strdup (dn);
444       tmp->attrs = (LDAPMod **) calloc (sizeof (LDAPMod *), flags);
445       if (tmp->attrs == (LDAPMod **) NULL)
446         {
447           fprintf (stderr, "calloc: %s\n", strerror (errno));
448           ldap_unbind_s (conn);
449           exit (-1);
450         }
451
452       for (i = 0; i < flags; i++)
453         {
454           tmp->attrs[i] = (LDAPMod *) malloc (sizeof (LDAPMod));
455           if (tmp->attrs[i] == (LDAPMod *) NULL)
456             {
457               fprintf (stderr, "malloc: %s\n", strerror (errno));
458               exit (-1);
459             }
460         }
461       tmp->attrs[0]->mod_op = LDAP_MOD_ADD;
462       tmp->attrs[0]->mod_type = "objectClass";
463
464       if (flags == DNS_OBJECT)
465         tmp->attrs[0]->mod_values = objectClasses;
466       else
467         {
468           tmp->attrs[0]->mod_values = topObjectClasses;
469           tmp->attrs[1] = NULL;
470           tmp->attrcnt = 2;
471           tmp->next = ldap_info_base;
472           ldap_info_base = tmp;
473           return;
474         }
475
476       tmp->attrs[1]->mod_op = LDAP_MOD_ADD;
477       tmp->attrs[1]->mod_type = "relativeDomainName";
478       tmp->attrs[1]->mod_values = (char **) calloc (sizeof (char *), 2);
479
480       if (tmp->attrs[1]->mod_values == (char **)NULL)
481                exit(-1);
482
483       tmp->attrs[1]->mod_values[0] = strdup (name);
484       tmp->attrs[1]->mod_values[2] = NULL;
485
486       sprintf (ldap_type_buffer, "%sRecord", type);
487
488       tmp->attrs[2]->mod_op = LDAP_MOD_ADD;
489       tmp->attrs[2]->mod_type = strdup (ldap_type_buffer);
490       tmp->attrs[2]->mod_values = (char **) calloc (sizeof (char *), 2);
491
492        if (tmp->attrs[2]->mod_values == (char **)NULL)
493                exit(-1);
494
495       tmp->attrs[2]->mod_values[0] = strdup (data);
496       tmp->attrs[2]->mod_values[1] = NULL;
497
498       tmp->attrs[3]->mod_op = LDAP_MOD_ADD;
499       tmp->attrs[3]->mod_type = "dNSTTL";
500       tmp->attrs[3]->mod_values = (char **) calloc (sizeof (char *), 2);
501
502       if (tmp->attrs[3]->mod_values == (char **)NULL)
503               exit(-1);
504
505       sprintf (charttl, "%d", ttl);
506       tmp->attrs[3]->mod_values[0] = strdup (charttl);
507       tmp->attrs[3]->mod_values[1] = NULL;
508
509       tmp->attrs[4]->mod_op = LDAP_MOD_ADD;
510       tmp->attrs[4]->mod_type = "zoneName";
511       tmp->attrs[4]->mod_values = (char **)calloc(sizeof(char *), 2);
512       tmp->attrs[4]->mod_values[0] = gbl_zone;
513       tmp->attrs[4]->mod_values[1] = NULL;
514
515       tmp->attrs[5] = NULL;
516       tmp->attrcnt = flags;
517       tmp->next = ldap_info_base;
518       ldap_info_base = tmp;
519     }
520   else
521     {
522
523       for (i = 0; tmp->attrs[i] != NULL; i++)
524         {
525           sprintf (ldap_type_buffer, "%sRecord", type);
526           if (!strncmp
527               (ldap_type_buffer, tmp->attrs[i]->mod_type,
528                strlen (tmp->attrs[i]->mod_type)))
529             {
530               attrlist = get_attr_list_size (tmp->attrs[i]->mod_values);
531               tmp->attrs[i]->mod_values =
532                 (char **) realloc (tmp->attrs[i]->mod_values,
533                                    sizeof (char *) * (attrlist + 1));
534
535               if (tmp->attrs[i]->mod_values == (char **) NULL)
536                 {
537                   fprintf (stderr, "realloc: %s\n", strerror (errno));
538                   ldap_unbind_s (conn);
539                   exit (-1);
540                 }
541               for (x = 0; tmp->attrs[i]->mod_values[x] != NULL; x++);
542
543               tmp->attrs[i]->mod_values[x] = strdup (data);
544               tmp->attrs[i]->mod_values[x + 1] = NULL;
545               return;
546             }
547         }
548       tmp->attrs =
549         (LDAPMod **) realloc (tmp->attrs,
550                               sizeof (LDAPMod) * ++(tmp->attrcnt));
551       if (tmp->attrs == NULL)
552         {
553           fprintf (stderr, "realloc: %s\n", strerror (errno));
554           ldap_unbind_s (conn);
555           exit (-1);
556         }
557
558       for (x = 0; tmp->attrs[x] != NULL; x++);
559       tmp->attrs[x] = (LDAPMod *) malloc (sizeof (LDAPMod));
560       tmp->attrs[x]->mod_op = LDAP_MOD_ADD;
561       tmp->attrs[x]->mod_type = strdup (ldap_type_buffer);
562       tmp->attrs[x]->mod_values = (char **) calloc (sizeof (char *), 2);
563       tmp->attrs[x]->mod_values[0] = strdup (data);
564       tmp->attrs[x]->mod_values[1] = NULL;
565       tmp->attrs[x + 1] = NULL;
566     }
567 }
568
569 /* Size of a mod_values list, plus the terminating NULL field. */
570 int
571 get_attr_list_size (char **tmp)
572 {
573   int i = 0;
574   char **ftmp = tmp;
575   while (*ftmp != NULL)
576     {
577       i++;
578       ftmp++;
579     }
580   return ++i;
581 }
582
583
584 /* take a hostname, and split it into a char ** of the dc parts,
585  * example, we have www.domain.com, this function will return:
586  * array[0] = com, array[1] = domain, array[2] = www. */
587
588 char **
589 hostname_to_dn_list (char *hostname, char *zone, unsigned int flags)
590 {
591   char *tmp;
592   static char *dn_buffer[64];
593   int i = 0;
594   char *zname;
595   char *hnamebuff;
596
597   zname = strdup (hostname);
598
599   if (flags == DNS_OBJECT)
600     {
601
602       if (strlen (zname) != strlen (zone))
603         {
604           tmp = &zname[strlen (zname) - strlen (zone)];
605           *--tmp = '\0';
606           hnamebuff = strdup (zname);
607           zname = ++tmp;
608         }
609       else
610         hnamebuff = "@";
611     }
612   else
613     {
614       zname = zone;
615       hnamebuff = NULL;
616     }
617
618   for (tmp = strrchr (zname, '.'); tmp != (char *) 0;
619        tmp = strrchr (zname, '.'))
620     {
621       *tmp++ = '\0';
622       dn_buffer[i++] = tmp;
623     }
624   dn_buffer[i++] = zname;
625   dn_buffer[i++] = hnamebuff;
626   dn_buffer[i] = NULL;
627
628   return dn_buffer;
629 }
630
631
632 /* build an sdb compatible LDAP DN from a "dc_list" (char **).
633  * will append dNSTTL information to each RR Record, with the 
634  * exception of "@"/SOA. */
635
636 char *
637 build_dn_from_dc_list (char **dc_list, unsigned int ttl, int flag)
638 {
639   int size;
640   int x;
641   static char dn[1024];
642   char tmp[128];
643
644   bzero (tmp, sizeof (tmp));
645   bzero (dn, sizeof (dn));
646   size = get_attr_list_size (dc_list);
647   for (x = size - 2; x > 0; x--)
648     {
649     if (flag == WI_SPEC)
650     {
651       if (x == (size - 2) && (strncmp (dc_list[x], "@", 1) == 0) && (ttl))
652         sprintf (tmp, "relativeDomainName=%s + dNSTTL=%d,", dc_list[x], ttl);
653       else if (x == (size - 2))
654               sprintf(tmp, "relativeDomainName=%s,",dc_list[x]);
655       else
656               sprintf(tmp,"dc=%s,", dc_list[x]);
657     }
658     else
659     {
660             sprintf(tmp, "dc=%s,", dc_list[x]);
661     }
662
663
664       strncat (dn, tmp, sizeof (dn) - strlen (dn));
665     }
666
667   sprintf (tmp, "dc=%s", dc_list[0]);
668   strncat (dn, tmp, sizeof (dn) - strlen (dn));
669
670             fflush(NULL);
671   return dn;
672 }
673
674
675 /* Initialize LDAP Conn */
676 void
677 init_ldap_conn ()
678 {
679   int result;
680   conn = ldap_open (ldapsystem, LDAP_PORT);
681   if (conn == NULL)
682     {
683       fprintf (stderr, "Error opening Ldap connection: %s\n",
684                strerror (errno));
685       exit (-1);
686     }
687
688   result = ldap_simple_bind_s (conn, binddn, bindpw);
689   ldap_result_check ("ldap_simple_bind_s", "LDAP Bind", result);
690 }
691
692 /* Like isc_result_check, only for LDAP */
693 void
694 ldap_result_check (char *msg, char *dn, int err)
695 {
696   if ((err != LDAP_SUCCESS) && (err != LDAP_ALREADY_EXISTS))
697     {
698       fprintf(stderr, "Error while adding %s (%s):\n",
699                       dn, msg);
700       ldap_perror (conn, dn);
701       ldap_unbind_s (conn);
702       exit (-1);
703     }
704 }
705
706
707
708 /* For running the ldap_info run queue. */
709 void
710 add_ldap_values (ldap_info * ldinfo)
711 {
712   int result;
713   char dnbuffer[1024];
714
715
716   if (ldapbase != NULL)
717     sprintf (dnbuffer, "%s,%s", ldinfo->dn, ldapbase);
718   else
719     sprintf (dnbuffer, "%s", ldinfo->dn);
720
721   result = ldap_add_s (conn, dnbuffer, ldinfo->attrs);
722   ldap_result_check ("ldap_add_s", dnbuffer, result);
723 }
724
725
726
727
728 /* name says it all */
729 void
730 usage ()
731 {
732   fprintf (stderr,
733            "zone2ldap -D [BIND DN] -w [BIND PASSWORD] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST]
734            [-c Create LDAP Base structure][-d Debug Output (lots !)] \n ");}