mirror of
https://github.com/bklang/ldap2dns.git
synced 2025-10-26 14:04:14 -04:00
Back importing ldap2dns from Jacob Rief - 0.2.0
git-svn-id: https://svn.alkaloid.net/gpl/ldap2dns/trunk@1 06cd67b6-e706-0410-b29e-9de616bca6e9
This commit is contained in:
55
Makefile
Normal file
55
Makefile
Normal file
@@ -0,0 +1,55 @@
|
||||
# ldap2dns Makefile
|
||||
VERSION=0.2.0
|
||||
RELEASE=1
|
||||
WITHTINYDNS=-DWITH_TINYDNS
|
||||
CC=gcc -O2
|
||||
DJBDNSDIR=../djbdns-1.02
|
||||
INC=-I$(DJBDNSDIR)
|
||||
CFLAGS=$(INC) $(WITHTINYDNS) -DVERSION='"$(VERSION)"'
|
||||
OBJS=ldap2dns.o
|
||||
LIBS=-lldap -llber -lresolv
|
||||
LD=gcc
|
||||
LDFLAGS=
|
||||
ALIBS=$(DJBDNSDIR)/dns.a $(DJBDNSDIR)/env.a $(DJBDNSDIR)/libtai.a \
|
||||
$(DJBDNSDIR)/cdb.a $(DJBDNSDIR)/alloc.a $(DJBDNSDIR)/buffer.a \
|
||||
$(DJBDNSDIR)/unix.a $(DJBDNSDIR)/byte.a
|
||||
INSTALL_PREFIX=
|
||||
PREFIXDIR=$(INSTALL_PREFIX)/usr
|
||||
LDAPCONFDIR=$(INSTALL_PREFIX)/etc/openldap
|
||||
TARFILE=/usr/src/redhat/SOURCES/ldap2dns-$(VERSION).tar.gz
|
||||
SPECFILE=ldap2dns.spec
|
||||
|
||||
all: ldap2dns
|
||||
|
||||
ldap2dns: $(OBJS) $(LIBS) $(ALIBS)
|
||||
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(ALIBS) $(LIBS)
|
||||
ln -f ldap2dns ldap2dnsd
|
||||
|
||||
ldap2dns.o: ldap2dns.c
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
install: all
|
||||
mkdir -p $(PREFIXDIR)/bin
|
||||
mkdir -p $(LDAPCONFDIR)
|
||||
install -s -o root -g root -m 755 ldap2dns $(PREFIXDIR)/bin/
|
||||
ln -f $(PREFIXDIR)/bin/ldap2dns $(PREFIXDIR)/bin/ldap2dnsd
|
||||
install -o root -g root -m 755 ldap2tinydns-conf $(PREFIXDIR)/bin/
|
||||
install -o root -g root -m 644 dns.at.conf $(LDAPCONFDIR)/
|
||||
install -o root -g root -m 644 dns.oc.conf $(LDAPCONFDIR)/
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) ldap2dns ldap2dnsd data* $(SPECFILE)
|
||||
|
||||
tar: clean
|
||||
cd ..; \
|
||||
tar czf $(TARFILE) ldap2dns-$(VERSION) --exclude CVS
|
||||
|
||||
$(SPECFILE): Specfile
|
||||
sed -e 's#%VERSION%#$(VERSION)#g' \
|
||||
-e 's#%RELEASE%#$(RELEASE)#g' \
|
||||
< $< > $@
|
||||
|
||||
rpm: tar $(SPECFILE)
|
||||
rpm -ba $(SPECFILE)
|
||||
|
||||
|
||||
332
README.html
Normal file
332
README.html
Normal file
@@ -0,0 +1,332 @@
|
||||
<H1 align=center>LDAP to DNS gateway</H1>
|
||||
<P>
|
||||
<B>ldap2dns</B> is a program to create DNS records directly from a LDAP directory.
|
||||
It can and should be be used to replace the secondary name-server by a second
|
||||
primary one.<BR>
|
||||
<B>ldap2dns</B> helps to reduce all kind of administration overhead.
|
||||
No more flat file editing, no more zone file editing. After having installed
|
||||
<B>ldap2dns</B>, the administrator only has to access the LDAP directory.<BR>
|
||||
If he desires he can add access control for each zone, create a webbased GUI
|
||||
and add all other kind of zone and resource record information without
|
||||
interfering with the DNS server.<BR>
|
||||
<B>ldap2dns</B> is designed to write binary data.cdb files used by tinydns, but
|
||||
also may be used to write .db-files used by named.<BR>
|
||||
<P>
|
||||
|
||||
<H3>1. Introduction</H3>
|
||||
Often it is desirable to store DNS information in a database rather than
|
||||
in flat text files. This can greatly help to reduce administration overhead
|
||||
since associate information such as billing contact, account management, etc.
|
||||
can be stored and processed inside the same database. Also due to the nature of
|
||||
DNS, information must be stored redundantly on two or more hosts.
|
||||
The classical data replication through zone transfer is unreliable, insecure
|
||||
and difficult to administer.<BR>
|
||||
To solve this problem some proprietary attempts have been proposed to
|
||||
store DNS information in relational databases. The nature of DNS however
|
||||
is hierarchical and such should the database be. Using a relational database
|
||||
to store DNS information is undesirable, because it becomes difficult
|
||||
to store free form information. Within a hierachical data scheme, the
|
||||
administrator might define more than one IP-address for each canonical name.
|
||||
To implement such a feature in a relational database without breaking the
|
||||
normalization rules, one would have to add another table.<BR>
|
||||
One of the most widely spread hierarchical database protocols is LDAP.
|
||||
<B>ldap2dns</B> retrieves DNS information stored in an LDAP directory service
|
||||
and generates a file suitable for name-servers.<BR>
|
||||
Actually the most widely spread name-servers
|
||||
<A HREF="http://www.isc.org/products/BIND/">named</A> and
|
||||
<A HREF="http://cr.yp.to/djbdns/tinydns.html">tinydns</A> are
|
||||
supported. <B>ldap2dns</B> has been specially designed to work with
|
||||
tinydns and is the favored name server daemon for the author of this program.
|
||||
<B>ldap2dns</B> can also generate files suitable for named, but this feature
|
||||
is not well supported.
|
||||
There is a
|
||||
<A HREF="http://www.alternic.org/drafts/drafts-m-n/draft-miller-dns-ldap-schema-00.txt">
|
||||
RFC</A> for a format description how to store DNS information in LDAP.
|
||||
This paper however is a draft RFC and expired in February 1999. The scheme this RFC
|
||||
describes, looks as if it has been designed to be used only by 'named'. This scheme
|
||||
does not have strict attribute-value-pair mapping, making it difficult to be used by
|
||||
user interfaces. It also lacks of an implementation (I have never heard of any).<BR>
|
||||
Since tinydns is going another descriptive way, I implemented a similar object-scheme
|
||||
more suitable for tinydns. Two objectclasses have been defined. <B>DNSzone</B> stores
|
||||
all the information to define a DNS zone, such as the SOA (Start Of Authority), serial
|
||||
numbers etc. <B>DNSrrset</B> is used to store the information for a single resource record,
|
||||
such as the domain name, IP-addresses, class and type.<BR>
|
||||
Here are the tables:
|
||||
<P>
|
||||
<H4>DNSzone</H4>
|
||||
This object-class represents a DNS zone. It is the container for all the resource records
|
||||
within a zone. Zones can be primary or secondary, if used in conjunction with
|
||||
tinydns zones are always primary. Secondary zones don't make sense anyway!
|
||||
In addition to being a container, the zone object has attributes related to
|
||||
the management of the zone. These include the zone's SOA information. Each zone-object
|
||||
can have none to many children of class <B>DNSrrset</B>.<BR>
|
||||
|
||||
<TABLE bgcolor=#EEEEEE>
|
||||
<TR><TH>ATTRIBUTE</TH><TH>VALUE</TH><TH>Comment</TH></TR>
|
||||
<TR><TD>objectclass</TD><TD>DNSzone</TD><TD>required</TD></TR>
|
||||
<TR><TD>cn</TD><TD><I>common name</I></TD><TD>required</TD></TR>
|
||||
<TR><TD>DNSzonename</TD><TD><I>Name of the zone</I></TD><TD>required, multivalued</TD></TR>
|
||||
<TR><TD>DNSserial</TD><TD><I>Serial number of SOA</I></TD><TD>optional</TD></TR>
|
||||
<TR><TD>DNSrefresh</TD><TD><I>Refresh time of SOA</I></TD><TD>optional, only used for zone transfers</TD></TR>
|
||||
<TR><TD>DNSretry</TD><TD><I>Retry time of SOA</I></TD><TD>optional, only used for zone transfers</TD></TR>
|
||||
<TR><TD>DNSexpire</TD><TD><I>Expire time of SOA</I></TD><TD>optional, only used for zone transfers</TD></TR>
|
||||
<TR><TD>DNSminimum</TD><TD><I>Minimum time to live</I></TD><TD>optional, only used for zone transfers</TD></TR>
|
||||
<TR><TD>DNSadminmailbox</TD><TD><I>Hostmaster's contact address</I></TD><TD>optional</TD></TR>
|
||||
<TR><TD>DNSzonemaster</TD><TD><I>Primary nameserver for this zone</I></TD><TD>optional</TD></TR>
|
||||
<TR><TD>DNStype</TD><TD>SOA</TD><TD>must be SOA</TD></TR>
|
||||
<TR><TD>DNSclass</TD><TD>IN</TD><TD>must be IN</TD></TR>
|
||||
<TR><TD>DNSttl</TD><TD><I>time to live</I></TD><TD>optional, only used with tinydns</TD></TR>
|
||||
<TR><TD>DNStimestamp</TD><TD><I>timestamp</I></TD><TD>optional, only used with tinydns</TD></TR>
|
||||
</TABLE>
|
||||
<UL>
|
||||
<LI><B>DNSzonename:</B> This field is rquired to describe the zone's domain name, for instance
|
||||
myorg.com. More than one <B>DNSzonename</B> my be specified for a <B>DNSzone</B> so that the
|
||||
same host is accessable with different zonenames.</LI>
|
||||
|
||||
<LI><B>DNSserial:</B> This is the serial number as used for BIND's zone transfers. Here it is
|
||||
used to inform <B>ldap2dns</B> that it has to rebuild its data-file. Without increasing the serial
|
||||
number <B>ldap2dns</B> will do nothing.</LI>
|
||||
|
||||
<LI><B>DNSrefresh, DNSretry, DNSexpire, DNSminimum:</B> You may safly ignore these numbers
|
||||
if You don't do zone-transfers. Since Your secondary nameserver will connect to the LDAP
|
||||
server the same way Your primary does, You don't need zone-transfers anyway.</LI>
|
||||
|
||||
<LI><B>DNSzonemaster:</B> Here You specify the canonical name of Your primary nameserver.</LI>
|
||||
|
||||
<LI><B>DNSadminmailbox:</B> This is the contact address of Your DNS-administrator. The first dot
|
||||
is converted to a <I>@</I>.</LI>
|
||||
|
||||
<LI><B>DNStype:</B> Must be <B>SOA</B> (which stands for Start Of Authority)</LI>
|
||||
|
||||
<LI><B>DNSclass:</B> Must be <B>IN</B> (which stands for Internet, or do You have anything else?)</LI>
|
||||
|
||||
<LI><B>DNSttl:</B> This is the time-to-live value as used by <B>tinydns</B>.
|
||||
If TTL is nonzero (or omitted), the timestamp is a starting time from whereon this zone's
|
||||
information is valid. If TTL is zero, the timestamp is an ending time (``time to die'').</LI>
|
||||
|
||||
<LI><B>DNStimestamp:</B> This is the timestamp as used by <B>tinydns</B>. It represents a
|
||||
string as external TAI64 timestamp, printed as 16 lowercase hexadecimal characters</LI>
|
||||
</UL>
|
||||
<P>
|
||||
|
||||
<H4>DNSrrset</H4>
|
||||
The Resource Record Set represents all of the resource records for
|
||||
a given host name within a zone. It must be a child of a DNSzone object.<BR>
|
||||
|
||||
<TABLE bgcolor=#EEEEEE>
|
||||
<TR><TH>ATTRIBUTE</TH><TH>VALUE</TH><TH>Comment</TH></TR>
|
||||
<TR><TD>objectclass</TD><TD>DNSrrset</TD><TD>required</TD></TR>
|
||||
<TR><TD>cn</TD><TD><I>common name</I></TD><TD>required</TD></TR>
|
||||
<TR><TD>DNSdomainname</TD><TD><I>Name of this record</I></TD><TD>optional, relative to zonename</TD></TR>
|
||||
<TR><TD>DNSipaddr</TD><TD><I>IP address</I></TD><TD>optional, mutivalued</TD></TR>
|
||||
<TR><TD>DNScname</TD><TD><I>Canonical name</I></TD><TD>optional, without ending dot relative to zonename</TD></TR>
|
||||
<TR><TD>DNSpreference</TD><TD><I>integer</I></TD><TD>optional, only used for MX records</TD></TR>
|
||||
<TR><TD>DNStype</TD><TD>A, CNAME, NS, MX, PTR or TXT</TD><TD>must be any valid record type</TD></TR>
|
||||
<TR><TD>DNSclass</TD><TD>IN</TD><TD>must be IN</TD></TR>
|
||||
<TR><TD>DNSttl</TD><TD><I>time to live</I></TD><TD>optional, only used with tinydns</TD></TR>
|
||||
<TR><TD>DNStimestamp</TD><TD><I>timestamp</I></TD><TD>optional, only used with tinydns</TD></TR>
|
||||
</TABLE>
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
<LI><B>DNSrrset:</B> This object-class must be a direct child of DNSzone. Its <B>dn</B> must be
|
||||
specified as <PRE>cn=<I>domainname</I>,cn=<I>zonename</I>,...</PRE></LI>
|
||||
|
||||
<LI><B>DNSdomainname</B> This is the partial domainname, ie. the part in front of the
|
||||
zonename.</LI>
|
||||
|
||||
<LI><B>DNSipaddr:</B> This specifies the IP-address in dotted format. It can be used for <B>DNSrrset</B>'s
|
||||
of type <B>A, NS, MX</B> or <B>PTR</B>. <B>DNSipaddr</B> is multivalued to specifiy more than one
|
||||
IP-address for a service. If used in combination with <B>PTR</B> it overrides the old-fashioned form
|
||||
used in <B>DNSdomainname</B> such as 13.178.23.in-addr.arpa for reverse lookups.</LI>
|
||||
|
||||
<LI><B>DNScname:</B> Whereever there is a mapping of a domainname to a canonical name, use
|
||||
this attribute. <B>DNScname</B> may be used for <B>DNSrrset</B>'s with <B>DNStype CNAME,
|
||||
NS, MX, PTR or TXT</B>. If the last character of a CNAME is a dot its name is considered
|
||||
absolute. If it does not contain a dot, it name is prepended to the zonename.</LI>
|
||||
|
||||
<LI><B>DNSpreference:</B> This number is the mail-exchange preference as used by BIND.</LI>
|
||||
|
||||
<LI><B>DNStype:</B> This must be <B>A, CNAME, NS, MX, PTR</B> or <B>TXT</B>. It specifies
|
||||
the DNSrrset type.</LI>
|
||||
|
||||
<LI><B>DNSclass:</B> Must be <B>IN</B> (which stands for Internet, or do You have anything else?)</LI>
|
||||
|
||||
<LI><B>DNSttl:</B> This is the time-to-live value as used by <B>tinydns</B>.
|
||||
If TTL is nonzero (or omitted), the timestamp is a starting time from whereon this zone's
|
||||
information is valid. If TTL is zero, the timestamp is an ending time (``time to die'').</LI>
|
||||
|
||||
<LI><B>DNStimestamp:</B> This is the timestamp as used by <B>tinydns</B>. It represents a
|
||||
string as external TAI64 timestamp, printed as 16 lowercase hexadecimal characters</LI>
|
||||
</UL>
|
||||
<P>
|
||||
|
||||
<H3>2. Installation</H3>
|
||||
<UL>
|
||||
<LI>Install an LDAP server such as <A HREF="www.openldap.org">openldap</A>. Other
|
||||
LDAP implementations may work but have not been tested. Also install the
|
||||
development libraries and include files.</LI>
|
||||
|
||||
<LI>Install <A HREF="http://cr.yp.to/djbdns.html">djbdns</A> or if You really
|
||||
have to, go with BIND.<BR>
|
||||
I suggest to install tinydns included in the <B>djbdns</B> package, because it is
|
||||
safer, but You may have reasons why You want to use BIND.</LI>
|
||||
|
||||
<LI>Install <B>ldap2dns</B><BR>
|
||||
Unpack the package with gzcat ldap2dns.tar.gz | tar x
|
||||
If You use <B>tinydns</B> put the directory dns2ldap onto
|
||||
the same directory level where You have the directory dnscache.
|
||||
cd into the package and type make.</LI>
|
||||
|
||||
<LI>If You do not want to use tinydns edit the Makefile,
|
||||
comment the lines starting with WITHTINYDNS and ALIBS. Then do a make.</LI>
|
||||
|
||||
<LI>Now add the extra object-classes to the slapd.conf file. To do this
|
||||
if You are using openldap-1.2.x:<BR>
|
||||
copy the files dns.oc.conf and dns.ac.conf into the directory /etc/openldap or
|
||||
appropriate and add the following two lines to Your slapd.conf file:<BR>
|
||||
<PRE>
|
||||
include /etc/openldap/dns.at.conf
|
||||
include /etc/openldap/dns.oc.conf
|
||||
</PRE>
|
||||
or, if You are using openldap-2.0.x:<BR>
|
||||
copy the file dns.schema into the directory /etc/openldap/schema or
|
||||
appropriate and add the following line to Your slapd.conf file:<BR>
|
||||
<PRE>
|
||||
include /etc/openldap/schema/dns.schema
|
||||
</PRE>
|
||||
Now restart Your LDAP server.</LI>
|
||||
<P>
|
||||
|
||||
<LI>Start to populate Your LDAP server with DNS information, as a first test do
|
||||
<PRE>
|
||||
$ ldapadd -D "<I>binddn</I>" -w <I>password</I> < example.ldif
|
||||
</PRE>
|
||||
Replace 'myorg' and 'binddn' with whatever is appropriate on Your system.
|
||||
Start a search and see if something was added
|
||||
<PRE>
|
||||
$ ldapsearch -D "<I>binddn</I>" "objectclass=dnsrrset" </LI>
|
||||
</PRE>
|
||||
|
||||
<LI>Test <B>ldap2dns</B>
|
||||
<PRE>
|
||||
$ ./ldap2dns -D "<I>binddn</I>" [ -b "<I>searchbase</I>" ] [ -w <I>passwd</I> ] -o 7 -L
|
||||
</PRE>
|
||||
This should create a 'data' file, a 'data.cdb' file, a 'corp.local.db'
|
||||
file and should print the DNS content. If You disabled the tinydns
|
||||
option no 'data.cdb' file is generated.<BR>
|
||||
Note: The 'data' file is text data which can be processed with tinydns-data.
|
||||
The 'data.cdb' file is the binary version of 'data' processed as tinydns-data
|
||||
would. You must not restart tinydns to inform about the modification as You
|
||||
would have with named.<BR>
|
||||
'corp.local.db' is the file as used by named. If You are using bind, You also
|
||||
have to adopt the file '/etc/named.conf' and You have to restart named. </LI>
|
||||
</UL>
|
||||
<P>
|
||||
|
||||
<H3>3. Running ldap2dns</H3>
|
||||
If You are a tinydns user, run <B>ldap2dns</B> in /services/tinydns/root.<BR>
|
||||
If You are an openldap user, the command line switches are the same as for ldapsearch
|
||||
or ldapadd.
|
||||
<PRE>
|
||||
$ ldap2dns -D "<I>binddn</I>" [ -w <I>passwd</I> ] -b "<I>searchbase</I>" -o 1
|
||||
</PRE>
|
||||
This generates a data.cdb file which is automatically updated by tinydns. The password
|
||||
is required if You restrict read queries to authenticated users only. Now test with
|
||||
<PRE>
|
||||
$ dnsq any corp.local <I>ipaddr</I>
|
||||
</PRE>
|
||||
Replace <I>ipaddr</I> with whatever You configured tinydns to listen to.
|
||||
<P>
|
||||
|
||||
If You are a BIND user, run <B>ldap2dns</B> in /var/named with
|
||||
<PRE>
|
||||
$ ldap2dns -D "<I>binddn</I>" -w <I>passwd</I> -b "<I>searchbase</I>" -o 4
|
||||
</PRE>
|
||||
Do not forget to add You primary definition to Your named.boot file and
|
||||
do not forget to restart named with
|
||||
<PRE>
|
||||
# kill -HUP <I>PID</I>
|
||||
</PRE>
|
||||
Now run
|
||||
<PRE>
|
||||
$ nslookup - localhost
|
||||
> ns1.corp.local
|
||||
</PRE>
|
||||
Note that nslookup only works with tinydns if Your nameserver resolves its IP-address
|
||||
backwards.
|
||||
<P>
|
||||
|
||||
<H3>4. Running ldap2dnsd</H3>
|
||||
<B>ldap2dnsd</B> is a hard link onto <B>ldap2dns</B>. If invoked the program
|
||||
starts as backgound-daemon and contineously checks for modifications in the LDAP directory.
|
||||
If the the daemon sees a modification in the <B>DNSserial</B> numbers it updates the data.cdb
|
||||
file. This check is done about once a minute.<BR>
|
||||
The command-line options for <B>ldap2dnsd</B> are the same as for <B>ldap2dns</B>.
|
||||
Use the -u option to modify the update intervall. You may also use -u on <B>ldap2dns</B>
|
||||
to start as a foreground daemon. This is useful if You want to run <B>ldap2dns</B> from
|
||||
<A HREF="http://cr.yp.to/daemontools.html">daemontools</A>. To do this run <B>ldap2tinydns-conf</B>
|
||||
in /service/tinydns and link /service/ldap2dns onto /service/tinydns/ldap2dns.
|
||||
<PRE>
|
||||
# ln -s /service/tinydns/ldap2dns /service/ldap2dns
|
||||
</PRE>
|
||||
After a few seconds <B>daemontools</B> starts <B>ldap2dns</B> which itself generates data.cdb
|
||||
files whenever a modification is commited into the LDAP directory.
|
||||
<P>
|
||||
<B>ldap2dns</B> and <B>ldap2dnsd</B> recognize the following options:
|
||||
<PRE>
|
||||
-D <I>binddn</I> specify the distinguished name to bind to the LDAP directory
|
||||
-w <I>bindpasswd</I> use bindpasswd as the password for simple authentication
|
||||
-b <I>searchbase</I> use searchbase as the starting point for the search instead of the default
|
||||
-o 1|2|4 output format number or any binary or-ed combination. Defaults to 1
|
||||
1: generate a binary file named 'data.cdb' to be used directly by tinydns
|
||||
2: generate a text file named 'data' to be parsed by tinydns-data
|
||||
4: for each zone generate a file named '<zonename>.db' to be used by named
|
||||
-L[<I>filename</I>] print output in LDIF format for reimport, defaults to stdout if filename is omitted
|
||||
-h <I>host</I> specify the hostname of LDAP directory, defaults to localhost
|
||||
-p <I>port</I> portnumber to connect to LDAP directory, defaults to 389
|
||||
-v run in verbose mode
|
||||
-vv even more verbose
|
||||
-V print version and exit
|
||||
-u <I>numsecs</I> update DNS data every numsecs. If started as ldap2dnsd this defaults to 59.
|
||||
</PRE>
|
||||
<P>
|
||||
|
||||
<H3>5. Importing DNS data from Your named</H3>
|
||||
A perl-script 'import.pl' is contained in this package. Edit the first
|
||||
lines of the script to conform to Your configuration.
|
||||
If You have installed the Perl packages Net::LDAP and Net::DNS
|
||||
skip the following lines, otherwise do
|
||||
<PRE>
|
||||
# perl -MCPAN -e 'shell'
|
||||
(...snip...)
|
||||
> install Net::DNS
|
||||
> install Net::LDAP
|
||||
</PRE>
|
||||
Now check that Your nameserver allows zone transfers to Your host and run the import script:
|
||||
<PRE>
|
||||
$ echo 'primary mydomain.org ' | ./import.pl
|
||||
</PRE>
|
||||
for a single domain or
|
||||
<PRE>
|
||||
# cat named.boot | ./import.pl
|
||||
</PRE>
|
||||
to populate Your LDAP directory.
|
||||
<P>
|
||||
|
||||
<H3>5. To Do</H3>
|
||||
<UL>
|
||||
<LI>Write a man page.</LI>
|
||||
<LI><B>named</B> should be restarted automatically sending a HUP signal to the appropriate daemon.</LI>
|
||||
<LI>named.conf should be created automatically.</LI>
|
||||
<LI>The option -o is not very nice.</LI>
|
||||
</UL>
|
||||
<P>
|
||||
|
||||
<H3>6. Copyright</H3>
|
||||
This program is licensed under the GPL version 2 or at Your choice any later
|
||||
version.<BR>
|
||||
It was written in autumn 2000 by
|
||||
<A HREF="mailto:jacob.rief@bigfoot.com?subject=ldap2dns">Jacob Rief</A>
|
||||
in the hope it may be useful.
|
||||
|
||||
53
Specfile
Normal file
53
Specfile
Normal file
@@ -0,0 +1,53 @@
|
||||
%define djbdns djbdns-1.02
|
||||
|
||||
Summary: LDAP to DNS gateway.
|
||||
Name: ldap2dns
|
||||
Version: %VERSION%
|
||||
Release: %RELEASE%
|
||||
Copyright: GPL
|
||||
Group: Daemons/DNS
|
||||
Source: ldap2dns-%{version}.tar.gz
|
||||
Source1: http://cr.yp.to/djbdns/%{djbdns}.tar.gz
|
||||
BuildRoot: /var/tmp/%{name}-root
|
||||
Requires: openldap
|
||||
|
||||
%description
|
||||
ldap2dns is a program to create DNS records directly from an LDAP database. It can
|
||||
be be used to replace the secondary name-server by a second primary one.
|
||||
ldap2dns helps to reduce all kind of administration overhead. No more flat file editing,
|
||||
no more zone file editing. After having installed ldap2dns, the administrator only has
|
||||
to access the LDAP database.
|
||||
If he desires he can add access control for each zone, create a webbased GUI and add
|
||||
all other kind of zone and resource record information without interfering with the DNS
|
||||
server.
|
||||
ldap2dns is designed to write binary data.cdb files used by tinydns, but also may be
|
||||
used to write .db-files used by named.
|
||||
|
||||
%prep
|
||||
%setup -a1 -q
|
||||
|
||||
%build
|
||||
make -C %{djbdns}
|
||||
make DJBDNSDIR="%{djbdns}" VERSION=%{version} RPM_OPT_FLAGS="$RPM_OPT_FLAGS"
|
||||
|
||||
%install
|
||||
[ -n "%{buildroot}" -a "%{buildroot}" != / ] && rm -rf %{buildroot}
|
||||
make DJBDNSDIR="%{djbdns}" INSTALL_PREFIX=$RPM_BUILD_ROOT install
|
||||
|
||||
%clean
|
||||
[ -n "%{buildroot}" -a "%{buildroot}" != / ] && rm -rf %{buildroot}
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
/usr/bin/ldap2dns
|
||||
/usr/bin/ldap2dnsd
|
||||
/usr/bin/ldap2tinydns-conf
|
||||
%doc README.html
|
||||
%doc import.pl
|
||||
%config /etc/openldap/dns.at.conf
|
||||
%config /etc/openldap/dns.oc.conf
|
||||
|
||||
%changelog
|
||||
* Wed Dec 06 2000 Jacob Rief <jacob.rief@tiscover.com>
|
||||
- initial revision for version 0.2.0
|
||||
|
||||
24
dns.at.conf
Normal file
24
dns.at.conf
Normal file
@@ -0,0 +1,24 @@
|
||||
# include this file into Your slapd.conf for openldap-1.2.x
|
||||
# $Id: dns.at.conf,v 1.5 2000/12/04 12:59:57 jrief Exp $
|
||||
attribute DNSzonename cis
|
||||
attribute DNSserial cis
|
||||
attribute DNSrefresh cis
|
||||
attribute DNSretry cis
|
||||
attribute DNSexpire cis
|
||||
attribute DNSminimum cis
|
||||
attribute DNSadminmailbox cis
|
||||
attribute DNSzonemaster cis
|
||||
attribute DNStype cis
|
||||
attribute DNSclass cis
|
||||
attribute DNSdomainname cis
|
||||
attribute DNSipaddr cis
|
||||
attribute DNScname cis
|
||||
attribute DNSpreference cis
|
||||
attribute DNSttl cis
|
||||
attribute DNStimestamp cis
|
||||
|
||||
#attribute DNSaliasedobjectname cis
|
||||
#attribute DNSrr cis
|
||||
#attribute DNSrrcount cis
|
||||
#attribute DNSmacaddress cis
|
||||
|
||||
45
dns.oc.conf
Normal file
45
dns.oc.conf
Normal file
@@ -0,0 +1,45 @@
|
||||
# include this file into Your slapd.conf for openldap-1.2.x
|
||||
# $Id: dns.oc.conf,v 1.4 2000/12/01 14:48:25 jrief Exp $
|
||||
|
||||
# child of anybody
|
||||
# information to setup a DNS zone
|
||||
objectclass DNSzone
|
||||
requires
|
||||
objectclass,
|
||||
cn
|
||||
allows
|
||||
DNSzonename,
|
||||
DNSserial,
|
||||
DNSrefresh,
|
||||
DNSretry,
|
||||
DNSexpire,
|
||||
DNSminimum,
|
||||
DNSadminmailbox,
|
||||
DNSzonemaster,
|
||||
DNStype,
|
||||
DNSclass,
|
||||
DNSttl,
|
||||
DNStimestamp
|
||||
|
||||
#DNSrrcount,
|
||||
|
||||
# child of a DNSzone
|
||||
# information to setup a resource record
|
||||
objectclass DNSrrset
|
||||
requires
|
||||
objectclass,
|
||||
cn
|
||||
allows
|
||||
DNSdomainname,
|
||||
DNSclass,
|
||||
DNStype,
|
||||
DNSipaddr,
|
||||
DNScname,
|
||||
DNSpreference,
|
||||
DNSttl,
|
||||
DNStimestamp
|
||||
|
||||
#DNSaliasedobjectname,
|
||||
#DNSrr,
|
||||
#DNSmacaddress,
|
||||
|
||||
111
dns.schema
Normal file
111
dns.schema
Normal file
@@ -0,0 +1,111 @@
|
||||
# schema for DNS data
|
||||
# include this file into Your slapd.conf for openldap-2.0.x
|
||||
# $Id: dns.schema,v 1.3 2000/12/01 14:48:25 jrief Exp $
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.1
|
||||
NAME 'DNSzonename'
|
||||
SUP name )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.2
|
||||
NAME 'DNSserial'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.3
|
||||
NAME 'DNSrefresh'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.4
|
||||
NAME 'DNSretry'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.5
|
||||
NAME 'DNSexpire'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.6
|
||||
NAME 'DNSminimum'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.7
|
||||
NAME 'DNSadminmailbox'
|
||||
SUP name )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.8
|
||||
NAME 'DNSzonemaster'
|
||||
SUP name )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.9
|
||||
NAME 'DNStype'
|
||||
SUP name )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.10
|
||||
NAME 'DNSclass'
|
||||
SUP name )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.11
|
||||
NAME 'DNSdomainname'
|
||||
SUP name )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.12
|
||||
NAME 'DNSipaddr'
|
||||
EQUALITY numericStringMatch
|
||||
SUBSTR numericStringSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )
|
||||
|
||||
#attributetype ( 1.2.840.113556.1.17.13
|
||||
# NAME 'DNSaliasedobjectname'
|
||||
# SUP name )
|
||||
|
||||
#attributetype ( 1.2.840.113556.1.17.14
|
||||
# NAME 'DNSrrcount'
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
# SINGLE-VALUE )
|
||||
|
||||
#attributetype ( 1.2.840.113556.1.17.15
|
||||
# NAME 'DNSmacaddress'
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.38
|
||||
# SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.16
|
||||
NAME 'DNScname'
|
||||
SUP name )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.17
|
||||
NAME 'DNSpreference'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.18
|
||||
NAME 'DNSrr'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.19
|
||||
NAME 'DNSttl'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.2.840.113556.1.17.20
|
||||
NAME 'DNStimestamp'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
|
||||
SINGLE-VALUE )
|
||||
|
||||
objectclass ( 1.2.840.113556.1.17.21
|
||||
NAME 'DNSzone'
|
||||
MUST ( objectclass $ cn )
|
||||
MAY ( zonedomainname $ serial $ refresh $ retry $ expire $ minimum
|
||||
$ adminmailbox $ zonemaster $ zonetype $ zoneclass $ rrcount
|
||||
$ ttl $ timestamp ) )
|
||||
|
||||
objectclass ( 1.2.840.113556.1.17.22
|
||||
NAME 'DNSrrset'
|
||||
SUP DNSzone
|
||||
MUST ( objectclass $ cn )
|
||||
MAY ( dnsdomainname $ aliasedobjectname $ rr $ macaddress $ zoneclass
|
||||
$ zonetype $ ipaddr $ cname $ preference $ ttl $ timestamp ) )
|
||||
|
||||
45
example.ldif
Normal file
45
example.ldif
Normal file
@@ -0,0 +1,45 @@
|
||||
dn: ou=dns,o=myorg
|
||||
objectclass: organizationalUnit
|
||||
ou: dns
|
||||
userpassword: dnsadmin
|
||||
|
||||
dn: cn=corp.local,ou=dns,o=myorg
|
||||
objectclass: DNSzone
|
||||
cn: corp.local
|
||||
DNSzonename: corp.local
|
||||
DNSserial: 12345
|
||||
DNSrefresh: 10800
|
||||
DNSretry: 3600
|
||||
DNSexpire: 3600000
|
||||
DNSminimum: 86400
|
||||
DNSadminmailbox: domainmaster.myorg
|
||||
DNSzonemaster: ldap.myorg
|
||||
|
||||
dn: cn=mail,cn=corp.local,ou=dns,o=myorg
|
||||
objectclass: DNSrrset
|
||||
cn: mail
|
||||
DNScname: mail
|
||||
DNStype: mx
|
||||
DNSipaddr: 17.19.21.23
|
||||
|
||||
dn: cn=ns1,cn=corp.local,ou=dns,o=myorg
|
||||
objectclass: DNSrrset
|
||||
cn: ns1
|
||||
DNScname: ns1
|
||||
DNStype: ns
|
||||
DNSipaddr: 17.19.23.24
|
||||
|
||||
dn: cn=ns2,cn=corp.local,ou=dns,o=myorg
|
||||
objectclass: DNSrrset
|
||||
cn: ns2
|
||||
DNScname: ns2
|
||||
DNStype: ns
|
||||
DNSipaddr: 17.19.23.25
|
||||
|
||||
dn: cn=www,cn=corp.local,ou=dns,o=myorg
|
||||
objectclass: DNSrrset
|
||||
cn: www
|
||||
DNSdomainname: www
|
||||
DNStype: a
|
||||
DNSipaddr: 17.19.23.30
|
||||
|
||||
241
import.pl
Executable file
241
import.pl
Executable file
@@ -0,0 +1,241 @@
|
||||
#!/usr/bin/perl
|
||||
# Script to import data from DNS into LDAP
|
||||
# Copyright 2000, Jacob Rief
|
||||
# $Id: import.pl,v 1.24 2000/12/14 12:44:29 jrief Exp $
|
||||
|
||||
###### configure this ######
|
||||
# remember to allow zone transfers from Your nameserver
|
||||
$LDAPHOST = "ldap.myorg.com";
|
||||
$LDAPBINDDN = "ou=dns,o=myorg";
|
||||
$LDAPPASSWD = "secret";
|
||||
$NAMESERVER = "ns1.myorg.com";
|
||||
$BASEDN = "ou=dns,o=myorg";
|
||||
$FULL_QUALIFIED_NAME = 0;
|
||||
|
||||
###### don't edit below this line ######
|
||||
use Net::DNS;
|
||||
use Net::LDAP;
|
||||
|
||||
$ldap = Net::LDAP->new($LDAPHOST) or die "Can't connect to LDAP server";
|
||||
$mesg = $ldap->bind( dn => $LDAPBINDDN, password => $LDAPPASSWD );
|
||||
die "Unable to bind to LDAP ", $mesg->error if ($mesg->code);
|
||||
|
||||
@domains;
|
||||
while (<>) {
|
||||
chomp;
|
||||
$_ = lc;
|
||||
if (/primary\s+([0-9A-Za-z._+-]+)\s+/) {
|
||||
push(@domains, $1);
|
||||
}
|
||||
}
|
||||
if ($#domains>=0) {
|
||||
@domains = sort(@domains);
|
||||
for ($i = 1; $i<=$#domains; $i++) {
|
||||
if ($domains[$i-1] eq $domains[$i]) {
|
||||
print "Warning: removing double entry for zone: $domains[$i]\n";
|
||||
splice(@domains, $i, 1);
|
||||
}
|
||||
}
|
||||
print "Adding ". ($#domains+1) ." zones to LDAP server\n";
|
||||
foreach(@domains) {
|
||||
read_zone($_);
|
||||
}
|
||||
} else {
|
||||
print "No domain added to LDAP server\n";
|
||||
}
|
||||
|
||||
|
||||
sub add_attrs
|
||||
{
|
||||
my ($attr, $zonename) = @_;
|
||||
|
||||
# correct DNScname
|
||||
if (defined $$attr{'DNScname'}) {
|
||||
# check if DNScname is a real name
|
||||
if ($$attr{'DNScname'} =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/) {
|
||||
$$attr{'DNSipaddr'} = "$1.$2.$3.$4";
|
||||
undef $$attr{'DNScname'};
|
||||
}
|
||||
}
|
||||
|
||||
my ($tail);
|
||||
if ($$attr{'DNSdomainname'} eq $zonename) {
|
||||
$tail = "";
|
||||
} else {
|
||||
split /\.$zonename/, $$attr{'DNSdomainname'};
|
||||
die "Corrupt DNSdomainname" unless (defined @_[0]);
|
||||
$tail = @_[0];
|
||||
}
|
||||
|
||||
if ($FULL_QUALIFIED_NAME) {
|
||||
$$attr{'DNSdomainname'} = "$zonename." if ($tail eq "");
|
||||
$$attr{'DNSdomainname'} = "$tail.$zonename." unless ($tail eq "");
|
||||
$$attr{'DNScname'} .= "." if (defined $$attr{'DNScname'});
|
||||
} else {
|
||||
$$attr{'DNSdomainname'} = "$tail";
|
||||
if (defined $$attr{'DNScname'}) {
|
||||
split /\.$zonename/, $$attr{'DNScname'};
|
||||
$$attr{'DNScname'} = @_[0] if (defined @_[0]);
|
||||
}
|
||||
}
|
||||
|
||||
my $rrdn;
|
||||
if ($$attr{'DNStype'} eq "A") {
|
||||
# A records are multivalued, use one rrset for all ipaddresses
|
||||
$$attr{'cn'} = "A:$tail";
|
||||
$rrdn = "cn=$$attr{'cn'},cn=$zonename,$BASEDN";
|
||||
$mesg = $ldap->search(base=>$rrdn, scope=>"base", filter => "(objectclass=DNSrrset)");
|
||||
if ($mesg->count==0) {
|
||||
$mesg = $ldap->add(dn=>$rrdn, attr=>list_attrs($attr));
|
||||
die "Failed to add entry:", $rrdn, " ", $mesg->error if ($mesg->code);
|
||||
} else {
|
||||
$mesg = $ldap->modify(dn=>$rrdn, add=>{ 'DNSipaddr'=>$$attr{'DNSipaddr'} });
|
||||
die "Failed to modify entry:", $rrdn, " ", $mesg->error if ($mesg->code);
|
||||
}
|
||||
} else {
|
||||
# All other records are siglevalued, use one rrset for each entry
|
||||
my $i = 0;
|
||||
do {
|
||||
$i++;
|
||||
$$attr{'cn'} = "$$attr{'DNStype'}$i:$tail";
|
||||
$rrdn = "cn=$$attr{'cn'},cn=$zonename,$BASEDN";
|
||||
|
||||
$mesg = $ldap->search(base=>$rrdn, scope=>"base", filter=>"(objectclass=DNSrrset)");
|
||||
} while ($mesg->count>0);
|
||||
if ($FULL_QUALIFIED_NAME) {
|
||||
$$attr{'DNScname'} = "$$attr{'DNStype'}$i.$zonename." unless defined $$attr{'DNScname'};
|
||||
} else {
|
||||
$$attr{'DNScname'} = "$$attr{'DNStype'}$i" unless defined $$attr{'DNScname'};
|
||||
}
|
||||
$mesg = $ldap->add(dn=>$rrdn, attr=>list_attrs($attr));
|
||||
die "Failed to add entry:", $rrdn, " ", $mesg->error if ($mesg->code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub list_attrs
|
||||
{
|
||||
my $attr = shift;
|
||||
my (@list, $key, $value);
|
||||
while (($key, $value) = each %$attr) {
|
||||
push(@list, $key => $value);
|
||||
}
|
||||
return \@list;
|
||||
}
|
||||
|
||||
|
||||
sub read_zone
|
||||
{
|
||||
my $zonename = shift;
|
||||
|
||||
$res = new Net::DNS::Resolver;
|
||||
$res->nameservers($NAMESERVER);
|
||||
@zone = $res->axfr($zonename);
|
||||
while (!@zone) {
|
||||
print "Query failed for $zonename: ", $res->errorstring, ".\n";
|
||||
if ($res->errorstring eq "couldn't connect") {
|
||||
print "Trying to reconnect\n";
|
||||
sleep(10);
|
||||
@zone = $res->axfr($zonename);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
print "---------- reading zone $zonename ----------\n";
|
||||
foreach $rr (@zone) {
|
||||
$rr->print;
|
||||
if ($rr->type eq "SOA") {
|
||||
die "Invalid SOA record for ", $rr->name, " " unless ($rr->string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)\s+([0-9a-zA-Z_.+-]+)\s+\((.*)\)/s);
|
||||
die "Corrupt SOA record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type);
|
||||
|
||||
my %attr;
|
||||
$attr{'objectclass'} = "DNSzone";
|
||||
$attr{'DNSzonename'} = lc $1;
|
||||
$attr{'DNSttl'} = $2;
|
||||
$attr{'DNSclass'} = $3;
|
||||
$attr{'DNStype'} = $4;
|
||||
$attr{'DNSzonemaster'} = lc $5;
|
||||
$attr{'DNSadminmailbox'} = lc $6;
|
||||
my $soa = $7;
|
||||
die "Invalid SOA fields for ", $zonename, " " unless ($soa =~ /\s*(\d+)\D*(\d+)\D*(\d+)\D*(\d+)\D*(\d+)\s*/s);
|
||||
$attr{'DNSserial'} = $1;
|
||||
$attr{'DNSrefresh'} = $2;
|
||||
$attr{'DNSretry'} = $3;
|
||||
$attr{'DNSexpire'} = $4;
|
||||
$attr{'DNSminimum'} = $5;
|
||||
$attr{'cn'} = $zonename;
|
||||
|
||||
$mesg = $ldap->add(dn=>"cn=$zonename,$BASEDN", attr=>list_attrs(\%attr));
|
||||
die "Failed to add entry:", $zonename, " ", $mesg->error if ($mesg->code);
|
||||
} elsif ($rr->type eq "A") {
|
||||
die "Invalid A record for ", $rr->name, " " unless ($rr->string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9.]+)/);
|
||||
die "Corrupt A record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type && $5 eq $rr->address);
|
||||
|
||||
next if $1 eq "localhost.$zonename";
|
||||
my %attr;
|
||||
$attr{'objectclass'} = "DNSrrset";
|
||||
$attr{'DNSdomainname'} = lc $1;
|
||||
$attr{'DNSttl'} = $2;
|
||||
$attr{'DNSclass'} = $3;
|
||||
$attr{'DNStype'} = $4;
|
||||
$attr{'DNSipaddr'} = $5;
|
||||
add_attrs(\%attr, $zonename);
|
||||
} elsif ($rr->type eq "MX") {
|
||||
die "Invalid MX record for ", $rr->name, " " unless ($rr->string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+([0-9a-zA-Z_.+-]+)/);
|
||||
die "Corrupt MX record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type);
|
||||
|
||||
my %attr;
|
||||
$attr{'objectclass'} = "DNSrrset";
|
||||
$attr{'DNSdomainname'} = lc $1;
|
||||
$attr{'DNSttl'} = $2;
|
||||
$attr{'DNSclass'} = $3;
|
||||
$attr{'DNStype'} = $4;
|
||||
$attr{'DNSpreference'} = $5;
|
||||
$attr{'DNScname'} = lc $6;
|
||||
add_attrs(\%attr, $zonename);
|
||||
} elsif ($rr->type eq "NS") {
|
||||
die "Invalid NS record for ", $rr->name, " " unless ($rr->string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)/);
|
||||
die "Corrupt NS record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type);
|
||||
|
||||
my %attr;
|
||||
$attr{'objectclass'} = "DNSrrset";
|
||||
$attr{'DNSdomainname'} = lc $1;
|
||||
$attr{'DNSttl'} = $2;
|
||||
$attr{'DNSclass'} = $3;
|
||||
$attr{'DNStype'} = $4;
|
||||
$attr{'DNScname'} = lc $5;
|
||||
add_attrs(\%attr, $zonename);
|
||||
} elsif ($rr->type eq "CNAME" || $rr->type eq "TXT") {
|
||||
die "Invalid ", $rr->type, " record for ", $rr->name, " " unless ($rr->string =~ /^([0-9a-zA-Z_.+-]+)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)/);
|
||||
die "Corrupt ", $rr->type, " record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type);
|
||||
|
||||
my %attr;
|
||||
$attr{'objectclass'} = "DNSrrset";
|
||||
$attr{'DNSdomainname'} = $1;
|
||||
$attr{'DNSttl'} = $2;
|
||||
$attr{'DNSclass'} = $3;
|
||||
$attr{'DNStype'} = $4;
|
||||
$attr{'DNScname'} = $5;
|
||||
add_attrs(\%attr, $zonename);
|
||||
} elsif ($rr->type eq "PTR") {
|
||||
die "Invalid PTR record for ", $rr->name, " " unless ($rr->string =~ /^([0-9.]+\.in-addr\.arpa)\.\s+(\d+)\s+(\w+)\s+(\w+)\s+([0-9a-zA-Z_.+-]+)/);
|
||||
die "Corrupt PTR record for ", $rr->name, " " unless ($1 eq $rr->name && $2 eq $rr->ttl && $3 eq $rr->class && $4 eq $rr->type);
|
||||
|
||||
my %attr;
|
||||
$attr{'objectclass'} = "DNSrrset";
|
||||
$attr{'DNSdomainname'} = "$1.";
|
||||
$attr{'DNSttl'} = $2;
|
||||
$attr{'DNSclass'} = $3;
|
||||
$attr{'DNStype'} = $4;
|
||||
$attr{'DNScname'} = $5;
|
||||
if ($attr{'DNSdomainname'} =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/) {
|
||||
$attr{'DNSipaddr'} = "$4.$3.$2.$1";
|
||||
$attr{'cn'} = "PTR:$1"; # Only for C-level domains yet
|
||||
} else { die "Corrupt IP address for", $rr->name; }
|
||||
my $rrdn = "cn=$attr{'cn'},cn=$zonename,$BASEDN";
|
||||
$mesg = $ldap->add(dn=>$rrdn, attr=>list_attrs(\%attr));
|
||||
die "Failed to add entry:", $rrdn, " ", $mesg->error if ($mesg->code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
index.html
Normal file
41
index.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>LDAP to DNS gateway</TITLE>
|
||||
<STYLE TYPE="text/css">
|
||||
H1 {
|
||||
font-weight: bold;
|
||||
font-size: 18pt;
|
||||
line-height: 18pt;
|
||||
font-family: arial,helvetica;
|
||||
font-variant: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
</STYLE>
|
||||
</HEAD>
|
||||
<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
|
||||
<BODY
|
||||
BGCOLOR="#FFFFFF"
|
||||
TEXT="#000000"
|
||||
LINK="#0000FF"
|
||||
VLINK="#000080"
|
||||
ALINK="#FF0000"
|
||||
>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
<!--#include file="README.html"--->
|
||||
<P>
|
||||
<H3 align=center>Download</H3>
|
||||
<TABLE border=2 cellpadding=4 align=center>
|
||||
<TR align=center><TH>Version</TH><TH>tar.gz</TH><TH>rpm</TH><TH>srpm</TH><TH>Released</TH></TR>
|
||||
<TR align=center><TD>0.1.1</TD><TD><A HREF="ldap2dns-0.1.1.tar.gz">ldap2dns</A></TD><TD></TD><TD></TD><TD>2000-Sep-19</TD></TR>
|
||||
<TR align=center><TD>0.1.2</TD><TD><A HREF="ldap2dns-0.1.2.tar.gz">ldap2dns</A></TD><TD></TD><TD></TD><TD>2000-Sep-22</TD></TR>
|
||||
<TR align=center><TD>0.1.3</TD><TD><A HREF="ldap2dns-0.1.3.tar.gz">ldap2dns</A></TD><TD></TD><TD></TD><TD>2000-Sep-28</TD></TR>
|
||||
<TR align=center><TD>0.1.4</TD><TD><A HREF="ldap2dns-0.1.4.tar.gz">ldap2dns</A></TD><TD></TD><TD></TD><TD>2000-Oct-04</TD></TR>
|
||||
<TR align=center><TD>0.2.0</TD><TD><A HREF="ldap2dns-0.2.0.tar.gz">ldap2dns</A></TD><TD><A HREF="ldap2dns-0.2.0-1.i386.rpm">ldap2dns</A></TD><TD><A HREF="ldap2dns-0.2.0-1.src.rpm">ldap2dns</A></TD><TD>2000-Dec-14</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
</BLOCKQUOTE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
915
ldap2dns.c
Normal file
915
ldap2dns.c
Normal file
@@ -0,0 +1,915 @@
|
||||
/*
|
||||
* Create data from an LDAP directory service to be used for tinydns
|
||||
* $Id: ldap2dns.c,v 1.20 2000/12/12 09:48:07 jrief Exp $
|
||||
* Copyright 2000 by Jacob Rief <jacob.rief@tiscover.com>
|
||||
* License: GPL version 2 or later. See http://www.fsf.org for details
|
||||
*/
|
||||
|
||||
#include <lber.h>
|
||||
#include <ldap.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define UPDATE_INTERVALL 59
|
||||
#define LDAP_CONF "/etc/openldap/ldap.conf"
|
||||
|
||||
#if defined WITH_TINYDNS
|
||||
# include "uint16.h"
|
||||
# include "uint32.h"
|
||||
# include "str.h"
|
||||
# include "byte.h"
|
||||
# include "fmt.h"
|
||||
# include "ip4.h"
|
||||
# include "exit.h"
|
||||
# include "readwrite.h"
|
||||
# include "buffer.h"
|
||||
# include "strerr.h"
|
||||
# include "getln.h"
|
||||
# include "cdb_make.h"
|
||||
# include "stralloc.h"
|
||||
# include "open.h"
|
||||
# include "dns.h"
|
||||
|
||||
int fdcdb;
|
||||
struct cdb_make cdb;
|
||||
buffer b;
|
||||
char bspace[1024];
|
||||
static stralloc key;
|
||||
static stralloc result;
|
||||
static char* dottemp1;
|
||||
static char* dottemp2;
|
||||
static char tinydns_datafile[256];
|
||||
static char tinydns_tempfile[256];
|
||||
|
||||
#endif
|
||||
|
||||
static char tinydns_textfile[256];
|
||||
static LDAP* ldap_con;
|
||||
static FILE* bindfile;
|
||||
static FILE* tinyfile;
|
||||
static FILE* ldifout;
|
||||
static time_t time_now;
|
||||
static int autoreverse;
|
||||
static char* const* main_argv;
|
||||
static int main_argc;
|
||||
|
||||
|
||||
static void print_version(void)
|
||||
{
|
||||
printf("ldap2dns, version %s\n", VERSION);
|
||||
printf(" Copyright 2000 by Jacob Rief <jacob.rief@tiscover.com>\n\n");
|
||||
}
|
||||
|
||||
|
||||
static void die_ldap(int err)
|
||||
{
|
||||
fprintf(stderr, "Fatal error: %s\n", ldap_err2string(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
char domainname[64];
|
||||
char zonemaster[64];
|
||||
char adminmailbox[64];
|
||||
unsigned long serial;
|
||||
unsigned long refresh;
|
||||
unsigned long retry;
|
||||
unsigned long expire;
|
||||
unsigned long minimum;
|
||||
int ttl;
|
||||
char timestamp[16];
|
||||
} zone;
|
||||
|
||||
struct resourcerecord
|
||||
{
|
||||
char cn[64];
|
||||
char dnsdomainname[64];
|
||||
char class[16];
|
||||
char type[16];
|
||||
char ipaddr[256][32];
|
||||
char cname[64];
|
||||
int ttl;
|
||||
char timestamp[16];
|
||||
int preference;
|
||||
#if defined DRAFT_RFC
|
||||
char rr[1024];
|
||||
char aliasedobjectname[256];
|
||||
char macaddress[32];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
char searchbase[128];
|
||||
char binddn[128];
|
||||
char hostname[128];
|
||||
char password[128];
|
||||
int is_daemon;
|
||||
int update_iv;
|
||||
int port;
|
||||
unsigned int output;
|
||||
int verbose;
|
||||
char ldifname[128];
|
||||
} options;
|
||||
|
||||
|
||||
static void die_exit(const char* message)
|
||||
{
|
||||
if (message)
|
||||
fprintf(stderr, "Fatal error: %s\n", message);
|
||||
else
|
||||
fprintf(stderr, "Fatal memory error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
#if defined WITH_TINYDNS
|
||||
|
||||
static void rr_add(char *buf, unsigned int len)
|
||||
{
|
||||
if (!stralloc_catb(&result, buf, len)) die_exit(0);
|
||||
}
|
||||
|
||||
static void rr_addname(char *d)
|
||||
{
|
||||
rr_add(d,dns_domain_length(d));
|
||||
}
|
||||
|
||||
static void rr_start(char type[2], unsigned long ttl, char ttd[8])
|
||||
{
|
||||
char buf[4];
|
||||
if (!stralloc_copyb(&result, type,2)) die_exit(0);
|
||||
rr_add("=",1);
|
||||
uint32_pack_big(buf, ttl);
|
||||
rr_add(buf,4);
|
||||
rr_add(ttd,8);
|
||||
}
|
||||
|
||||
static void rr_finish(char *owner)
|
||||
{
|
||||
if (byte_equal(owner,2,"\1*")) {
|
||||
owner += 2;
|
||||
result.s[2] = '*';
|
||||
}
|
||||
if (!stralloc_copyb(&key, owner, dns_domain_length(owner))) die_exit(0);
|
||||
case_lowerb(key.s, key.len);
|
||||
if (cdb_make_add(&cdb, key.s, key.len, result.s, result.len) == -1)
|
||||
die_exit("Unable to create 'data.tmp'");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
static void set_datadir(void)
|
||||
{
|
||||
char* ev = getenv("TINYDNSDIR");
|
||||
int len;
|
||||
|
||||
#if defined WITH_TINYDNS
|
||||
tinydns_datafile[0] = 0;
|
||||
tinydns_tempfile[0] = 0;
|
||||
#endif
|
||||
tinydns_textfile[0] = 0;
|
||||
if (ev && (len = strlen(ev))<240) {
|
||||
#if defined WITH_TINYDNS
|
||||
strncpy(tinydns_datafile, ev, 240);
|
||||
strncpy(tinydns_tempfile, ev, 240);
|
||||
#endif
|
||||
strncpy(tinydns_textfile, ev, 240);
|
||||
if (ev[len-1]!='/') {
|
||||
#if defined WITH_TINYDNS
|
||||
tinydns_datafile[len] = '/';
|
||||
tinydns_tempfile[len] = '/';
|
||||
#endif
|
||||
tinydns_textfile[len] = '/';
|
||||
}
|
||||
}
|
||||
#if defined WITH_TINYDNS
|
||||
strcat(tinydns_datafile, "data.cdb");
|
||||
strcat(tinydns_tempfile, "data.tmp");
|
||||
#endif
|
||||
strcat(tinydns_textfile, "data");
|
||||
}
|
||||
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
print_version();
|
||||
printf("usage: ldap2dns[d] [-D binddn] [-b searchbase] [-o 0|1|2|4] [-h host] [-p port] [-w password] [-L[filename]] [-u numsecs] [-v[v]] [-V]\n\n");
|
||||
printf("ldap2dns connects to an LDAP server reads the DNS information stored in objectclasses\n"
|
||||
"\t\tDNSzone and DNSrrset and writes a file to be used by tinydns or named.\n"
|
||||
"\t\tldap2dnsd starts as background-job and continouesly updates DNS information.\n");
|
||||
printf("options:\n");
|
||||
printf(" -D binddn\tUse the distinguished name binddn to bind to the LDAP directory\n");
|
||||
printf(" -w bindpasswd\tUse bindpasswd as the password for simple authentication\n");
|
||||
printf(" -b use searchbase as the starting point for the search instead of the default\n");
|
||||
printf(" -o 1|2|4\toutput format number or any binary or-ed combination. Defaults to 1\n");
|
||||
printf("\t1: generate a binary file named 'data.cdb' to be used directly by tinydns\n");
|
||||
printf("\t2: generate a text file named 'data' to be parsed by tinydns-data\n");
|
||||
printf("\t4: for each zone generate a file named '<zonename>.db' to be used by named\n");
|
||||
printf(" -L[filename] print output in LDIF format for reimport\n");
|
||||
printf(" -h host\thostname of LDAP server, defaults to localhost\n");
|
||||
printf(" -p port\tportnumber to connect to LDAP server, defaults to %d\n", LDAP_PORT);
|
||||
printf(" -u numsecs\tUpdate DNS data after numsecs. Defaults to %d if started as daemon.\n\t\t"
|
||||
"Important notice: data.cdb is rewritten only after DNSserial in DNSzone is increased.\n",
|
||||
UPDATE_INTERVALL);
|
||||
printf(" -v\t\trun in verbose mode\n");
|
||||
printf(" -vv\t\teven more verbose\n");
|
||||
printf(" -V\t\tprint version and exit\n\n");
|
||||
}
|
||||
|
||||
static int parse_options()
|
||||
{
|
||||
extern char* optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
char buf[256], value[128];
|
||||
int c;
|
||||
FILE* ldap_conf;
|
||||
|
||||
strcpy(options.searchbase, "");
|
||||
strcpy(options.hostname, "localhost");
|
||||
options.port = LDAP_PORT;
|
||||
if (ldap_conf = fopen(LDAP_CONF, "r")) {
|
||||
while(fgets(buf, 256, ldap_conf)!=0) {
|
||||
if (sscanf(buf, "BASE %128s", value)==1)
|
||||
strcpy(options.searchbase, value);
|
||||
if (sscanf(buf, "HOST %128s:%d", value, &c)==2) {
|
||||
strcpy(options.hostname, value);
|
||||
options.port = c;
|
||||
} else if (sscanf(buf, "HOST %128s", value)==1)
|
||||
strcpy(options.hostname, value);
|
||||
if (sscanf(buf, "PORT %d", &c)==1)
|
||||
options.port = c;
|
||||
}
|
||||
fclose(ldap_conf);
|
||||
}
|
||||
strcpy(options.binddn, "");
|
||||
options.output = 1;
|
||||
options.verbose = 0;
|
||||
options.ldifname[0] = '\0';
|
||||
c = strlen(main_argv[0]);
|
||||
if (strcmp(main_argv[0]+c-9, "ldap2dnsd")==0)
|
||||
options.is_daemon = 1;
|
||||
else
|
||||
options.is_daemon = 0;
|
||||
options.update_iv = 59;
|
||||
strcpy(options.password, "");
|
||||
while ( (c = getopt(main_argc, main_argv, "b:D:h:o:p:u:Vw:v::L::"))>0 ) {
|
||||
if (optarg && strlen(optarg)>127) {
|
||||
fprintf(stderr, "argument %s too long\n", optarg);
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case 'b':
|
||||
strcpy(options.searchbase, optarg);
|
||||
break;
|
||||
case 'u':
|
||||
if (sscanf(optarg, "%d", &options.update_iv)!=1)
|
||||
options.update_iv = UPDATE_INTERVALL;
|
||||
if (options.update_iv<=0) options.update_iv = 1;
|
||||
if (options.is_daemon==0) options.is_daemon = 2; /* foreground daemon */
|
||||
break;
|
||||
case 'D':
|
||||
strcpy(options.binddn, optarg);
|
||||
break;
|
||||
case 'h':
|
||||
strcpy(options.hostname, optarg);
|
||||
break;
|
||||
case 'L':
|
||||
if (optarg==NULL)
|
||||
strcpy(options.ldifname, "-");
|
||||
else
|
||||
strcpy(options.ldifname, optarg);
|
||||
break;
|
||||
case 'o':
|
||||
if (sscanf(optarg, "%d", &options.output)!=1)
|
||||
options.output = 0;
|
||||
break;
|
||||
case 'p':
|
||||
if (sscanf(optarg, "%d", &options.port)!=1)
|
||||
options.port = LDAP_PORT;
|
||||
break;
|
||||
case 'v':
|
||||
if (optarg && optarg[0]=='v')
|
||||
options.verbose = 3;
|
||||
else
|
||||
options.verbose = 1;
|
||||
break;
|
||||
case 'V':
|
||||
print_version();
|
||||
exit(0);
|
||||
case 'w':
|
||||
strcpy(options.password, optarg);
|
||||
break;
|
||||
default:
|
||||
print_usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int expand_domainname(char target[64], const char* source, int slen)
|
||||
{
|
||||
if (slen>64)
|
||||
return 0;
|
||||
if (source[slen-1]=='.') {
|
||||
strncpy(target, source, slen-1);
|
||||
target[slen-1] = '\0';
|
||||
return 1;
|
||||
}
|
||||
strncpy(target, source, slen);
|
||||
target[slen] = '\0';
|
||||
if (zone.domainname[0]) {
|
||||
if (zone.domainname[0]!='.')
|
||||
strcat(target, ".");
|
||||
strcat(target, zone.domainname);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int expand_reverse(char target[64], const char* source)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void write_rr(struct resourcerecord* rr, int ipdx)
|
||||
{
|
||||
char ip[4];
|
||||
char buf[4];
|
||||
|
||||
if (strcasecmp(rr->class, "IN"))
|
||||
return;
|
||||
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
int dnsdn_len = strlen(rr->dnsdomainname);
|
||||
int cname_len = strlen(rr->cname);
|
||||
if (!dns_domain_fromdot(&dottemp1, rr->dnsdomainname, dnsdn_len)) die_exit(0);
|
||||
if (!dns_domain_fromdot(&dottemp2, rr->cname, cname_len)) die_exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcasecmp(rr->type, "NS")==0) {
|
||||
if (tinyfile)
|
||||
fprintf(tinyfile, "&%s:%s:%s:%d:%s\n", rr->dnsdomainname, (ipdx>=0 ? rr->ipaddr[ipdx] : ""), rr->cname, rr->ttl, rr->timestamp);
|
||||
if (bindfile) {
|
||||
fprintf(bindfile, "%s.\tIN NS\t%s.\n", rr->dnsdomainname, rr->cname);
|
||||
if (ipdx>=0)
|
||||
fprintf(bindfile, "%s.\tIN A\t%s\n", rr->cname, rr->ipaddr[ipdx]);
|
||||
}
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
rr_start(DNS_T_NS, rr->ttl, rr->timestamp);
|
||||
rr_addname(dottemp2);
|
||||
rr_finish(dottemp1);
|
||||
if (ipdx>=0 && ip4_scan(rr->ipaddr[ipdx], ip)) {
|
||||
rr_start(DNS_T_A, rr->ttl, rr->timestamp);
|
||||
rr_add(ip, 4);
|
||||
rr_finish(dottemp2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (strcasecmp(rr->type, "MX")==0) {
|
||||
if (tinyfile)
|
||||
fprintf(tinyfile, "@%s:%s:%s:%d:%d:%s\n", rr->dnsdomainname, (ipdx>=0 ? rr->ipaddr[ipdx] : ""), rr->cname, rr->preference, rr->ttl, rr->timestamp);
|
||||
if (bindfile) {
|
||||
fprintf(bindfile, "%s.\tIN MX\t%d %s.\n", rr->dnsdomainname, rr->preference, rr->cname);
|
||||
if (ipdx>=0)
|
||||
fprintf(bindfile, "%s.\tIN A\t%s\n", rr->cname, rr->ipaddr[ipdx]);
|
||||
}
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
rr_start(DNS_T_MX, rr->ttl, rr->timestamp);
|
||||
uint16_pack_big(buf, rr->preference);
|
||||
rr_add(buf, 2);
|
||||
rr_addname(dottemp2);
|
||||
rr_finish(dottemp1);
|
||||
if (ipdx>=0 && ip4_scan(rr->ipaddr[ipdx], ip)) {
|
||||
rr_start(DNS_T_A, rr->ttl, rr->timestamp);
|
||||
rr_add(ip, 4);
|
||||
rr_finish(dottemp2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if ( strcasecmp(rr->type, "A")==0) {
|
||||
if (tinyfile)
|
||||
fprintf(tinyfile, "%s%s:%s:%d:%s\n", (autoreverse ? "=" : "+"), rr->dnsdomainname, (ipdx>=0 ? rr->ipaddr[ipdx] : ""), rr->ttl, rr->timestamp);
|
||||
if (bindfile && ipdx>=0)
|
||||
fprintf(bindfile, "%s.\tIN A\t%s\n", rr->dnsdomainname, rr->ipaddr[ipdx]);
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
char dptr[DNS_NAME4_DOMAIN];
|
||||
if (ipdx>=0 && ip4_scan(rr->ipaddr[ipdx], ip)) {
|
||||
rr_start(DNS_T_A, rr->ttl, rr->timestamp);
|
||||
rr_add(ip, 4);
|
||||
rr_finish(dottemp1);
|
||||
}
|
||||
if (autoreverse) {
|
||||
dns_name4_domain(dptr, ip);
|
||||
rr_start(DNS_T_PTR, rr->ttl, rr->timestamp);
|
||||
rr_addname(dottemp1);
|
||||
rr_finish(dptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else if (strcasecmp(rr->type, "PTR")==0) {
|
||||
int ip[4] = {0, 0, 0, 0};
|
||||
char buf[64];
|
||||
if (ipdx>0) {
|
||||
/* does not make to have more than one IPaddr for a PTR record */
|
||||
return;
|
||||
}
|
||||
if (ipdx==0 && sscanf(rr->ipaddr[0], "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])==4) {
|
||||
/* lazy user, used DNSipaddr for reverse lookup */
|
||||
sprintf(buf, "%d.%d.%d.%d.in-addr.arpa", ip[3], ip[2], ip[1], ip[0]);
|
||||
} else {
|
||||
strcpy(buf, rr->dnsdomainname);
|
||||
}
|
||||
if (tinyfile)
|
||||
fprintf(tinyfile, "^%s:%s:%d:%s\n", buf, rr->cname, rr->ttl, rr->timestamp);
|
||||
if (bindfile)
|
||||
fprintf(bindfile, "%s.\tIN PTR\t%s.\n", buf, rr->cname);
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
int dnsdn_len = strlen(buf);
|
||||
if (!dns_domain_fromdot(&dottemp1, buf, dnsdn_len)) die_exit(0);
|
||||
rr_start(DNS_T_PTR, rr->ttl, rr->timestamp);
|
||||
rr_addname(dottemp2);
|
||||
rr_finish(dottemp1);
|
||||
}
|
||||
#endif
|
||||
} else if (strcasecmp(rr->type, "CNAME")==0) {
|
||||
if (tinyfile)
|
||||
fprintf(tinyfile, "C%s:%s:%d:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
|
||||
if (bindfile)
|
||||
fprintf(bindfile, "%s.\tIN CNAME\t%s.\n", rr->dnsdomainname, rr->cname);
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
rr_start(DNS_T_CNAME, rr->ttl, rr->timestamp);
|
||||
rr_addname(dottemp2);
|
||||
rr_finish(dottemp1);
|
||||
}
|
||||
#endif
|
||||
} else if (strcasecmp(rr->type, "TXT")==0) {
|
||||
if (tinyfile)
|
||||
fprintf(tinyfile, "'%s:%s:%d:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
|
||||
if (bindfile)
|
||||
fprintf(bindfile, "%s.\tIN TXT\t%s.\n", rr->dnsdomainname, rr->cname);
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
rr_start(DNS_T_TXT, rr->ttl, rr->timestamp);
|
||||
rr_addname(dottemp2);
|
||||
rr_finish(dottemp1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined DRAFT_RFC
|
||||
static void parse_rr(struct resourcerecord* rr)
|
||||
{
|
||||
char word1[64];
|
||||
char word2[64];
|
||||
int ip[4];
|
||||
|
||||
sscanf(rr->rr, "%16s %16s %64s %64s", rr->class, rr->type, word1, word2);
|
||||
if (strcasecmp(rr->type, "NS")==0) {
|
||||
if (sscanf(word1, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])==4) {
|
||||
sprintf(rr->ipaddr[0], "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||
} else {
|
||||
int len = strlen(word1);
|
||||
expand_domainname(rr->cname, word1, len);
|
||||
}
|
||||
} else if (strcasecmp(rr->type, "MX")==0) {
|
||||
if (sscanf(word1, "%d", &rr->preference)!=1)
|
||||
rr->preference = 0;
|
||||
if (sscanf(word2, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])==4) {
|
||||
sprintf(rr->ipaddr[0], "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||
} else {
|
||||
int len = strlen(word2);
|
||||
expand_domainname(rr->cname, word2, len);
|
||||
}
|
||||
} else if (strcasecmp(rr->type, "A")==0) {
|
||||
if (sscanf(word1, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])==4)
|
||||
sprintf(rr->ipaddr[0], "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||
else
|
||||
rr->ipaddr[0][0] = '\0';
|
||||
} else if (strcasecmp(rr->type, "PTR")==0) {
|
||||
expand_reverse(rr->dnsdomainname, word1);
|
||||
} else if (strcasecmp(rr->type, "CNAME")==0) {
|
||||
int len = strlen(word1);
|
||||
expand_reverse(rr->cname, word1);
|
||||
} else if (strcasecmp(rr->type, "TXT")==0) {
|
||||
strncpy(rr->cname, word1, 64);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void read_resourcerecords(char* dn)
|
||||
{
|
||||
LDAPMessage* res = NULL;
|
||||
LDAPMessage* m;
|
||||
int ldaperr;
|
||||
|
||||
if ( (ldaperr = ldap_search_s(ldap_con, dn, LDAP_SCOPE_ONELEVEL, "objectclass=DNSrrset", NULL, 0, &res))!=LDAP_SUCCESS )
|
||||
die_ldap(ldaperr);
|
||||
for (m = ldap_first_entry(ldap_con, res); m; m = ldap_next_entry(ldap_con, m)) {
|
||||
BerElement* ber = NULL;
|
||||
char* attr;
|
||||
char* dn = ldap_get_dn(ldap_con, m);
|
||||
struct resourcerecord rr;
|
||||
int ipaddresses = 0;
|
||||
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "dn: %s\n", dn);
|
||||
rr.cn[0] = '\0';
|
||||
strncpy(rr.dnsdomainname, zone.domainname, 64);
|
||||
strcpy(rr.class, "IN");
|
||||
rr.type[0] = '\0';
|
||||
rr.cname[0] = '\0';
|
||||
rr.ttl = time_now;
|
||||
rr.timestamp[0] = '\0';
|
||||
rr.preference = 10;
|
||||
#if defined DRAFT_RFC
|
||||
rr.aliasedobjectname[0] = '\0';
|
||||
rr.rr[0] = '\0';
|
||||
#endif
|
||||
for (attr = ldap_first_attribute(ldap_con, m, &ber); attr; attr = ldap_next_attribute(ldap_con, m, ber)) {
|
||||
int len = strlen(attr);
|
||||
struct berval** bvals;
|
||||
char* dnsnname = "";
|
||||
|
||||
if ( (bvals = ldap_get_values_len(ldap_con, m, attr))!=NULL ) {
|
||||
if (bvals[0] && bvals[0]->bv_len>0) {
|
||||
if (strcasecmp(attr, "objectclass")==0) {
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
|
||||
} else if (strcasecmp(attr, "cn")==0) {
|
||||
strncpy(rr.cn, bvals[0]->bv_val, 64);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, rr.cn);
|
||||
} else if (strcasecmp(attr, "DNSdomainname")==0) {
|
||||
if (!expand_domainname(rr.dnsdomainname, bvals[0]->bv_val, bvals[0]->bv_len))
|
||||
rr.dnsdomainname[0] = '\0';;
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
|
||||
} else if (strcasecmp(attr, "DNSclass")==0) {
|
||||
if (sscanf(bvals[0]->bv_val, "%16s", &rr.class)!=1)
|
||||
rr.class[0] = '\0';
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, rr.class);
|
||||
} else if (strcasecmp(attr, "DNStype")==0) {
|
||||
if (sscanf(bvals[0]->bv_val, "%16s", &rr.type)!=1)
|
||||
rr.type[0] = '\0';
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, rr.type);
|
||||
} else if (strcasecmp(attr, "DNSipaddr")==0) {
|
||||
int ip[4];
|
||||
for (ipaddresses = 0; bvals[ipaddresses] && ipaddresses<256; ipaddresses++) {
|
||||
rr.ipaddr[ipaddresses][0] = '\0';
|
||||
if (sscanf(bvals[ipaddresses]->bv_val, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])==4)
|
||||
sprintf(rr.ipaddr[ipaddresses], "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, rr.ipaddr[ipaddresses]);
|
||||
}
|
||||
} else if (strcasecmp(attr, "DNScname")==0) {
|
||||
if (!expand_domainname(rr.cname, bvals[0]->bv_val, bvals[0]->bv_len))
|
||||
rr.cname[0] = '\0';
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
|
||||
} else if (strcasecmp(attr, "DNSttl")==0) {
|
||||
if (sscanf(bvals[0]->bv_val, "%d", &rr.ttl)!=1)
|
||||
rr.ttl = time_now;
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %d\n", attr, rr.ttl);
|
||||
} else if (strcasecmp(attr, "DNStimestamp")==0) {
|
||||
if (sscanf(bvals[0]->bv_val, "%16s", &rr.timestamp)!=1)
|
||||
rr.timestamp[0] = '\0';
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, rr.timestamp);
|
||||
} else if (strcasecmp(attr, "DNSpreference")==0) {
|
||||
if (sscanf(bvals[0]->bv_val, "%d", &rr.preference)!=1)
|
||||
rr.preference = 10;
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
|
||||
}
|
||||
#if defined DRAFT_RFC
|
||||
else if (strcasecmp(attr, "DNSrr")==0) {
|
||||
strncpy(rr.rr, bvals[0]->bv_val, 1024);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, rr.rr);
|
||||
} else if (strcasecmp(attr, "DNSaliasedobjectname")==0) {
|
||||
if (sscanf(bvals[0]->bv_val, "%256s", rr.aliasedobjectname)!=1)
|
||||
rr.aliasedobjectname[0] = '\0';
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, rr.aliasedobjectname);
|
||||
} else if (strcasecmp(attr, "DNSmacaddress")==0) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
ldap_value_free_len(bvals);
|
||||
}
|
||||
}
|
||||
#if defined DRAFT_RFC
|
||||
if (rr.rr[0]) {
|
||||
parse_rr(&rr);
|
||||
}
|
||||
#endif
|
||||
do {
|
||||
ipaddresses--;
|
||||
write_rr(&rr, ipaddresses);
|
||||
} while (ipaddresses>0);
|
||||
#if defined DRAFT_RFC
|
||||
if (rr.aliasedobjectname[0])
|
||||
read_resourcerecords(rr.aliasedobjectname);
|
||||
#endif
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "\n");
|
||||
if (options.verbose&2)
|
||||
printf("\trr: %s %s %s\n", rr.class, rr.type, rr.dnsdomainname);
|
||||
free(dn);
|
||||
}
|
||||
ldap_msgfree(res);
|
||||
}
|
||||
|
||||
|
||||
static void write_zone(void)
|
||||
{
|
||||
int len;
|
||||
char soa[20];
|
||||
|
||||
if (tinyfile) {
|
||||
fprintf(tinyfile, "Z%s:%s:%s:%d:%d:%d:%d:%d:%d:%s\n", zone.domainname,
|
||||
zone.zonemaster, zone.adminmailbox, zone.serial, zone.refresh, zone.retry,
|
||||
zone.expire, zone.minimum, zone.ttl, zone.timestamp);
|
||||
}
|
||||
|
||||
if (bindfile) {
|
||||
fprintf(bindfile, "; Automatically generated by ldap2dns - DO NOT EDIT!\n");
|
||||
fprintf(bindfile, "%s. IN SOA %s. %s. ", zone.domainname, zone.zonemaster, zone.adminmailbox);
|
||||
fprintf(bindfile, "(\n\t%d\t; Serial\n\t%d\t; Refresh\n\t%d\t; Retry\n\t%d\t; Expire\n\t%d )\t; Minimum\n", zone.serial, zone.refresh, zone.retry, zone.expire, zone.minimum);
|
||||
}
|
||||
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
byte_zero(zone.timestamp, 8);
|
||||
len = strlen(zone.domainname);
|
||||
if (!dns_domain_fromdot(&dottemp1, zone.domainname, len)) die_exit(0);
|
||||
uint32_pack_big(soa, zone.serial);
|
||||
uint32_pack_big(soa+4, zone.refresh);
|
||||
uint32_pack_big(soa+8, zone.retry);
|
||||
uint32_pack_big(soa+12, zone.expire);
|
||||
uint32_pack_big(soa+16, zone.minimum);
|
||||
rr_start(DNS_T_SOA, zone.ttl, zone.timestamp);
|
||||
len = strlen(zone.zonemaster);
|
||||
if (!dns_domain_fromdot(&dottemp2, zone.zonemaster, len)) die_exit(0);
|
||||
rr_addname(dottemp2);
|
||||
len = strlen(zone.adminmailbox);
|
||||
if (!dns_domain_fromdot(&dottemp2, zone.adminmailbox, len)) die_exit(0);
|
||||
rr_addname(dottemp2);
|
||||
rr_add(soa, 20);
|
||||
rr_finish(dottemp1);
|
||||
}
|
||||
#endif
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "\n");
|
||||
}
|
||||
|
||||
|
||||
static void calc_checksum(int* num, int* sum)
|
||||
{
|
||||
LDAPMessage* res = NULL;
|
||||
LDAPMessage* m;
|
||||
int ldaperr;
|
||||
char* attr_list[2] = { "DNSserial", NULL };
|
||||
|
||||
*num = *sum = 0;
|
||||
if ( ldaperr = ldap_search_s(ldap_con, options.searchbase[0] ? options.searchbase : NULL, LDAP_SCOPE_SUBTREE, "objectclass=DNSzone", attr_list, 0, &res)!=LDAP_SUCCESS )
|
||||
die_ldap(ldaperr);
|
||||
for (m = ldap_first_entry(ldap_con, res); m; m = ldap_next_entry(ldap_con, m)) {
|
||||
BerElement* ber = NULL;
|
||||
char* attr = ldap_first_attribute(ldap_con, m, &ber);
|
||||
if (attr) {
|
||||
struct berval** bvals = ldap_get_values_len(ldap_con, m, attr);
|
||||
if (bvals!=NULL) {
|
||||
unsigned tmp;
|
||||
if (sscanf(bvals[0]->bv_val, "%u", &tmp)==1) {
|
||||
(*num)++;
|
||||
*sum += tmp;
|
||||
}
|
||||
ldap_value_free_len(bvals);
|
||||
}
|
||||
}
|
||||
ber_free(ber, 0);
|
||||
}
|
||||
ldap_msgfree(res);
|
||||
}
|
||||
|
||||
|
||||
static void read_dnszones(void)
|
||||
{
|
||||
LDAPMessage* res = NULL;
|
||||
LDAPMessage* m;
|
||||
int ldaperr;
|
||||
|
||||
if (tinyfile)
|
||||
fprintf(tinyfile, "# Automatically generated by ldap2dns - DO NOT EDIT!\n");
|
||||
if ( (ldaperr = ldap_search_s(ldap_con, options.searchbase[0] ? options.searchbase : NULL, LDAP_SCOPE_SUBTREE, "objectclass=DNSzone", NULL, 0, &res))!=LDAP_SUCCESS )
|
||||
die_ldap(ldaperr);
|
||||
for (m = ldap_first_entry(ldap_con, res); m; m = ldap_next_entry(ldap_con, m)) {
|
||||
BerElement* ber = NULL;
|
||||
char* attr;
|
||||
char* dn;
|
||||
int i, zonenames = 0;
|
||||
char zdn[256][64];
|
||||
char ldif0;
|
||||
|
||||
zone.serial = time_now;
|
||||
zone.refresh = 10800;
|
||||
zone.retry = 3600;
|
||||
zone.expire = 604800;
|
||||
zone.minimum = 86400;
|
||||
zone.ttl = time_now;
|
||||
zone.timestamp[0] = '\0';
|
||||
dn = ldap_get_dn(ldap_con, m);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "dn: %s\n", dn);
|
||||
for (attr = ldap_first_attribute(ldap_con, m, &ber); attr; attr = ldap_next_attribute(ldap_con, m, ber)) {
|
||||
struct berval** bvals = ldap_get_values_len(ldap_con, m, attr);
|
||||
if (bvals!=NULL) {
|
||||
if (bvals[0] && bvals[0]->bv_len>0) {
|
||||
if (strcasecmp(attr, "objectclass")==0
|
||||
|| strcasecmp(attr, "DNSclass")==0
|
||||
|| strcasecmp(attr, "DNStype")==0
|
||||
|| strcasecmp(attr, "cn")==0) {
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
|
||||
} else if (strcasecmp(attr, "DNSzonename")==0) {
|
||||
for (zonenames = 0; bvals[zonenames] && zonenames<256; zonenames++) {
|
||||
if (sscanf(bvals[zonenames]->bv_val, "%64s", &zdn[zonenames])!=1)
|
||||
zdn[zonenames][0] = '\0';
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, zdn[zonenames]);
|
||||
}
|
||||
} else if (strcasecmp(attr, "DNSserial")==0) {
|
||||
sscanf(bvals[0]->bv_val, "%u", &zone.serial);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %d\n", attr, zone.serial);
|
||||
} else if (strcasecmp(attr, "DNSrefresh")==0) {
|
||||
sscanf(bvals[0]->bv_val, "%u", &zone.refresh);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %d\n", attr, zone.refresh);
|
||||
} else if (strcasecmp(attr, "DNSretry")==0) {
|
||||
sscanf(bvals[0]->bv_val, "%u", &zone.retry);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %d\n", attr, zone.retry);
|
||||
} else if (strcasecmp(attr, "DNSexpire")==0) {
|
||||
sscanf(bvals[0]->bv_val, "%u", &zone.expire);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %d\n", attr, zone.expire);
|
||||
} else if (strcasecmp(attr, "DNSminimum")==0) {
|
||||
sscanf(bvals[0]->bv_val, "%u", &zone.minimum);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %d\n", attr, zone.minimum);
|
||||
} else if (strcasecmp(attr, "DNSadminmailbox")==0) {
|
||||
sscanf(bvals[0]->bv_val, "%64s", zone.adminmailbox);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, zone.adminmailbox);
|
||||
} else if (strcasecmp(attr, "DNSzonemaster")==0) {
|
||||
sscanf(bvals[0]->bv_val, "%64s", zone.zonemaster);
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, zone.zonemaster);
|
||||
} else if (strcasecmp(attr, "DNSttl")==0) {
|
||||
if (sscanf(bvals[0]->bv_val, "%d", &zone.ttl)!=1)
|
||||
zone.ttl = time_now;
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %d\n", attr, zone.ttl);
|
||||
} else if (strcasecmp(attr, "DNStimestamp")==0) {
|
||||
if (sscanf(bvals[0]->bv_val, "%16s", &zone.timestamp)!=1)
|
||||
zone.timestamp[0] = '\0';
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "%s: %s\n", attr, zone.timestamp);
|
||||
}
|
||||
}
|
||||
ldap_value_free_len(bvals);
|
||||
}
|
||||
}
|
||||
ldif0 = options.ldifname[0];
|
||||
for (i = 0; i<zonenames; i++) {
|
||||
strncpy(zone.domainname, zdn[i], 64);
|
||||
if (i>0)
|
||||
options.ldifname[0] = '\0';
|
||||
if (options.verbose&1)
|
||||
printf("zonename: %s\n", zone.domainname);
|
||||
if (options.output&4) {
|
||||
char bindfilename[128];
|
||||
sprintf(bindfilename, "%s.db", zone.domainname);
|
||||
if ( !(bindfile = fopen(bindfilename, "w")) )
|
||||
die_exit("Unable to open db-file for writing");
|
||||
}
|
||||
write_zone();
|
||||
read_resourcerecords(dn);
|
||||
if (bindfile)
|
||||
fclose(bindfile);
|
||||
if (options.verbose&2)
|
||||
printf("\n");
|
||||
if (options.ldifname[0])
|
||||
fprintf(ldifout, "\n");
|
||||
}
|
||||
options.ldifname[0] = ldif0;
|
||||
free(dn);
|
||||
}
|
||||
ldap_msgfree(res);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int soa_numzones;
|
||||
int soa_checksum;
|
||||
|
||||
umask(022);
|
||||
main_argc = argc;
|
||||
main_argv = argv;
|
||||
parse_options();
|
||||
if (options.is_daemon) {
|
||||
if (options.is_daemon==1 && fork())
|
||||
exit(0);
|
||||
/* lowest priority */
|
||||
nice(19);
|
||||
}
|
||||
set_datadir();
|
||||
for (;;) {
|
||||
int ldaperr;
|
||||
if ( !(ldap_con = ldap_init(options.hostname, options.port)) )
|
||||
die_exit("Unable to initialize connection to LDAP server");
|
||||
ldaperr = ldap_simple_bind_s(ldap_con, options.binddn, options.password);
|
||||
if (ldaperr!=LDAP_SUCCESS) {
|
||||
fprintf(stderr, "Warning - Could not connect to LDAP server %s:%d as '%s'\n", options.hostname, options.port, options.binddn);
|
||||
sleep(options.update_iv);
|
||||
continue;
|
||||
}
|
||||
if (options.is_daemon) {
|
||||
int num, sum;
|
||||
calc_checksum(&num, &sum);
|
||||
if (num!=soa_numzones || sum!=soa_checksum) {
|
||||
if (options.verbose&1)
|
||||
printf("DNSserial has changed in LDAP zone(s)\n");
|
||||
soa_numzones = num;
|
||||
soa_checksum = sum;
|
||||
} else {
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
fdcdb = open_trunc(tinydns_tempfile);
|
||||
if (fdcdb == -1) die_exit("Unable to create 'data.tmp'");
|
||||
if (cdb_make_start(&cdb, fdcdb) == -1) die_exit("Unable to create 'data.tmp'");
|
||||
}
|
||||
#endif
|
||||
if (options.ldifname[0]) {
|
||||
if (options.ldifname[0]=='-')
|
||||
ldifout = stdout;
|
||||
else
|
||||
ldifout = fopen(options.ldifname, "w");
|
||||
if (!ldifout)
|
||||
die_exit("Unable to open LDIF-file for writing");
|
||||
}
|
||||
time(&time_now);
|
||||
if ( options.output&2 && !(tinyfile = fopen(tinydns_textfile, "w")) )
|
||||
die_exit("Unable to open file 'data' for writing");
|
||||
read_dnszones();
|
||||
if (tinyfile)
|
||||
fclose(tinyfile);
|
||||
if (options.ldifname[0] && ldifout)
|
||||
fclose(ldifout);
|
||||
#if defined WITH_TINYDNS
|
||||
if (options.output&1) {
|
||||
if (cdb_make_finish(&cdb)==-1 || fsync(fdcdb)==-1 || close(fdcdb)==-1)
|
||||
die_exit("Unable to create 'data.tmp'");
|
||||
if (rename(tinydns_tempfile, tinydns_datafile)==-1)
|
||||
die_exit("Unable to move 'data.tmp' to 'data.cdb'");
|
||||
}
|
||||
#endif
|
||||
skip:
|
||||
if ( (ldaperr = ldap_unbind_s(ldap_con))!=LDAP_SUCCESS )
|
||||
die_ldap(ldaperr);
|
||||
if (options.is_daemon==0)
|
||||
break;
|
||||
sleep(options.update_iv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
9
ldap2tinydns-conf
Executable file
9
ldap2tinydns-conf
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
mkdir ldap2tinydns
|
||||
mkdir ldap2tinydns/env
|
||||
echo "#!/bin/sh" > ldap2tinydns/run
|
||||
echo "exec 2>&1" >> ldap2tinydns/run
|
||||
echo "exec envdir ./env softlimit -d250000 /usr/bin/ldap2dns -u 59" >> ldap2tinydns/run
|
||||
chmod 755 ldap2tinydns/run
|
||||
echo "/var/tinydns/root" > ldap2tinydns/env/TINYDNSDIR
|
||||
|
||||
Reference in New Issue
Block a user