#pragma implementation #include #include #include "dnsconf.h" #include "internal.h" #include #include "dnsconf.m" #include #include #include #include DNSCONF_HELP_FILE help_dnsconf ("intro"); static DNSCONF_HELP_FILE help_forward ("forwarders"); static DNS *loaded_dns = NULL; static int loaded_count = 0; bool dnsconf_bindnewer (const char *version) { PACKAGE_API *api = package_api_init("dnsconf"); bool ret = true; if (api != NULL && !api->is_newer(api,"bind",version)) ret = false; package_api_end(api); return ret; } DNS *dns_load() { if (loaded_dns == NULL) loaded_dns = new DNS; loaded_count++; return loaded_dns; } void dns_unload() { loaded_count--; if (loaded_count==0){ delete loaded_dns; loaded_dns = NULL; } } /* Edit the forwarders IP number. */ PUBLIC void DNS::editforwarders() { DIALOG dia; // Add empty slots for (int i=forwarders.getnb(); i= 8.2 needed zones_forward.edit(*this); }else if (key == t_forwarders){ editforwarders(); }else if (key == t_features){ editfeatures(); }else if (key == t_ipmap){ ipmap_edit(); }else if (key == t_editbydom){ primarys.editbydom(*this); }else if (key == t_editrecs){ editrecs(""); }else if (key == t_acl){ acls.edit(*this); }else if (key == t_access){ editaccess(); } } } return 0; } /* Find out if any part of the DNS was modified during the session */ PUBLIC int DNS::was_modified() { int ret = 0; if (ARRAY_OBJ::was_modified() || primarys.was_modified() || secondarys.was_modified() || zones_forward.was_modified()) { ret = 1; } return ret; } void dnsconf_edit() { CONTEXT_LOCK lk ("dnsconf"); if (lk.isok()){ DNS *dns = dns_load(); if (!dns->empty()){ dns->basiccheck(); dns->edit(); }else if (dialog_yesno(MSG_U(Q_NODNS,"No DNS configured") ,MSG_U(I_NODNS ,"There is no DNS configuration\n" "We can create one from scratch\n" "\n" "Do you want to create one ?") ,help_dnsconf)==MENU_YES){ dns->basiccheck(); dns->bind8 = dnsconf_bindnewer ("8.0"); dns->write(); xconf_notice (MSG_U(N_DNSCREATED ,"A basic DNS (caching DNS) has been created.\n" "You can add domain to it as needed.")); dns->edit(); } dns_unload(); } } /* Obtain all IP associated with a host name (fqdn) in the DNS Return the number of IPs added to tbip. */ PUBLIC int DNS::geta (const char *host, IP_ADDRS &tbip) { PRIMARY *pri = findprimary (host); int ret = 0; if (pri != NULL){ SSTRING s (host); SSTRINGS ttls; ret = pri->geta (s,tbip,ttls); } return ret; } /* Update the DNS with a host definition. Return true if the DNS was updated (because something was changed). */ PUBLIC bool DNS::condset ( const char *hostname, const char *tbip[], int nbip, bool test) // Do not modify, test only { bool ret = false; if (findprimary(hostname)!=NULL){ IP_ADDRS ips; int n = geta (hostname,ips); if (n != nbip){ ret = true; }else{ int found = 0; for (int i=0; iget(); for (int j=0; jcondset (hostname,tbip,nbip,test); if (ret && !test) dns->write(); dns_unload(); } return ret; } static void usage () { xconf_error (MSG_U(N_DNSUSAGE ,"Module dnsconf\n" "dnsconf [specific options]\n" "\n" " --deldomain domain\n" " --delsecondary domain\n" " --newdomain domain [ template_domain ]\n" " --newsecondary domain primary ...\n" " --set host ip_number [ip_number ...]\n" " --set host --fromrange range\n" " --setchroot dir\n" " --setcname host real-host\n" " --setfromip host ip_number\n" " --setmx host/domain mailserver ...\n" " --setns host/domain dns_server [ secondary_dns ... ]\n" " --unset host\n" " --unsetchroot\n" " --unsetcname host\n" " --unsetmx host/domain\n" " --unsetns host/domain\n" "\n" " without argument start the interactive mode\n" "\n") ); } /* Update the DNS files if there were not errors */ static void dnsconf_writeif (int ret, DNS &dns) { if (ret != -1){ dns.write(); }else{ fprintf (stderr,MSG_R(E_NODOMAINS)); } } int dnsconf_main (int argc, char *argv[]) { int ret = 0; if (netconf_mainaccess()){ if (argc == 1){ while (1){ dnsconf_edit(); if (netconf_checkupdate(true)!=2) break; } }else if (!dns_configured()){ xconf_error (MSG_U(E_NODNS,"No DNS currently configured")); }else{ error_setmode (true); DNS *dns = dns_load(); if (dns->empty()){ xconf_error (MSG_R(E_NODNS)); }else if (argc == 3 && strcmp(argv[1],"--deldomain")==0){ ret = dns->deldomain (argv[2]); dnsconf_writeif (ret,*dns); }else if (argc == 3 && strcmp(argv[1],"--delsecondary")==0){ ret = dns->delsecondary (argv[2]); dnsconf_writeif (ret,*dns); }else if (argc >= 3 && strcmp(argv[1],"--newsecondary")==0){ ret = dns->newsecondary (argv[2],(const char **)argv+3,argc-3); dnsconf_writeif (ret,*dns); }else if ((argc == 3 || argc == 4) && strcmp(argv[1],"--newdomain")==0){ /* #Specification: dnsconf / --newdomain option The --newdomain option creates a new domain in the DNS with default values for the various parameter of the SOA. The first argument to the --newdomain option is the name of the domain to create. A second optionnal argument is the name of an existing domain in that DNS. This will be used as a template for the SOA, the default ttl, the MX and NS records and the access control. */ const char *dom = argv[2]; const char *templ = argc == 4 ? argv[3] : (const char *)NULL; ret = dns->newdomain (dom,templ); dnsconf_writeif (ret,*dns); }else if (argc == 5 && strcmp(argv[1],"--set")==0 && strcmp(argv[3],"--fromrange")==0){ /* #Specification: dnsconf / --set --fromrange option The dnsconf options "--set" has a special mode. You can specify an allocation range and linuxconf will compute the first available IP number and allocate it to this host. dnsconf --set newhost.mydomain --fromrange "IP aliases" */ const char *range = argv[4]; char ip[16]; int errcod = ipmap_allocateip(range,ip,*dns); if (errcod == -2){ xconf_error (MSG_U(E_NORANGE,"No range \"%s\" defined") ,range); }else if (errcod == -1){ xconf_error (MSG_U(E_NOIPAVAIL ,"No IP number available in the range \"%s\"") ,range); ret = -1; }else{ char *tb[1]; tb[0] = ip; ret = dns->set (argv[2],(const char**)tb,1); if (ret != -1){ dns->write(); }else{ fprintf (stderr,MSG_U(E_NODOMAINS ,"Not applicable to any domain in the DNS\n")); } } }else if (argc >= 4 && strcmp(argv[1],"--set")==0){ /* #Specification: dnsconf / --set option The dnsconf options "--set" allows you to set or update the specification of a host. You must specify the name (fully qualified or not) followed by the IP number. dnsconf --set newhost.mydomain 192.68.210.2 */ ret = 0; for (int i=3; iset (argv[2],(const char**)&argv[3],argc - 3); if (ret != -1){ dns->write(); }else{ fprintf (stderr,MSG_R(E_NODOMAINS)); } } }else if (argc == 3 && strcmp(argv[1],"--unset")==0){ /* #Specification: dnsconf / --unset option The dnsconf options "--unset" allows you to remove a host specification from your DNS. dnsconf --unset newhost.mydomain */ dns->unset (argv[2]); dns->write(); }else if (argc == 4 && strcmp(argv[1],"--setfromip")==0){ /* #Specification: dnsconf / --setfromip option The dnsconf option "--setfromip" works like the "--set" option except that the key to do the cleanup is the IP, not the host name. With --set, all IPs associated with the name are removed and the new IPs are put in place. With --setfromip, all name associated with the IP are removed and then the new name is put in place with the IP. This is normally used when updating a DNS from a DHCP server. We know for sure that only one host may point to the IP allocated and we want to get rid of all names previously allocated to the IP. */ const char *host = argv[2]; const char *ip = argv[3]; dns->setfromip(host,ip); dnsconf_writeif (ret,*dns); }else if (argc >= 4 && strcmp(argv[1],"--setmx")==0){ /* #Specification: dnsconf / --setmx The dnsconf options "--setmx" allows you to define the MX records associated with the host or domain All previous MX record associated with that host are removed. dnsconf --setmx host.mydomain one_MX_host ... */ SSTRING host (argv[2]); SSTRINGS tb; for (int i=3; isetmx (host,tb,ttls); dnsconf_writeif (ret,*dns); }else if (argc == 3 && strcmp(argv[1],"--unsetmx")==0){ /* #Specification: dnsconf / --unsetmx The dnsconf options "--unsetmx" allows you to unset all MX records associated with the host or domain. dnsconf --unsetmx host.mydomain */ SSTRING host (argv[2]); ret = dns->unsetmx (host); dnsconf_writeif (ret,*dns); }else if (argc >= 4 && strcmp(argv[1],"--setns")==0){ /* #Specification: dnsconf / --setns The dnsconf options "--setns" allows you to define the NS records associated with the host or domain All previous NS records associated with that host are removed. dnsconf --setns host.mydomain one_name_server ... */ SSTRING host (argv[2]); SSTRINGS tb; for (int i=3; isetns (host,tb,ttls); dnsconf_writeif (ret,*dns); }else if (argc == 3 && strcmp(argv[1],"--unsetns")==0){ /* #Specification: dnsconf / --unsetns The dnsconf options "--unsetns" allows you to unset all NS records associated with the host or domain dnsconf --unsetns host.mydomain */ SSTRING host (argv[2]); ret = dns->unsetns (host); dnsconf_writeif (ret,*dns); }else if (argc == 4 && strcmp(argv[1],"--setcname")==0){ /* #Specification: dnsconf / --setcname The dnsconf options "--setcname" allows you to define a nick name for a host. The first name will point to the second. dnsconf --setcname newname.mydomain oldname.somedomain. */ SSTRING host (argv[2]); SSTRING cname (argv[3]); ret = dns->setcname (host,cname); dnsconf_writeif (ret,*dns); }else if (argc == 3 && strcmp(argv[1],"--unsetcname")==0){ /* #Specification: dnsconf / --unsetcname The dnsconf options "--unsetcname" allows you to unset a nick name for a host. dnsconf --unsetcname newname.mydomain */ SSTRING host (argv[2]); ret = dns->unsetcname (host); dnsconf_writeif (ret,*dns); }else if (argc == 3 && strcmp(argv[1],"--setchroot")==0){ /* #Specification: dnsconf / --setchroot The dnsconf option "--setchroot" allows you to inform dnsconf that bind is running in a chroot environment. This information is stored in /etc/conf.linuxconf. dnsconf --setchroot /my/bind/chroot/dir */ SSTRING root(argv[2]); if (features_chkchroot(root)!=-1){ linuxconf_replace(K_DNSCONF,K_CHROOT,root); linuxconf_save(); } }else if (argc == 2 && strcmp(argv[1],"--unsetchroot")==0){ /* #Specification: dnsconf / --unsetchroot The dnsconf option "--setchroot" allows you to unset the chroot environment in dnsconf. dnsconf --unsetchroot */ linuxconf_removeall(K_DNSCONF,K_CHROOT); linuxconf_save(); }else{ usage(); } dns_unload(); } } return ret; } static REGISTER_USERACCT_COMNG xxx (dnsconf_newcomng); static int dnsconf_api_set(const char *host, const char *tbip[], int nbip) { return loaded_dns->set (host,tbip,nbip); } static int dnsconf_api_setfromip (const char *host, const char *ip) { return loaded_dns->setfromip (host,ip); } static int dnsconf_api_setfromrange (const char *host, const char *range) { char ip[16]; int errcod = ipmap_allocateip(range,ip,*loaded_dns); int ret = -1; if (errcod == 0){ const char *tb[]={ip}; ret = loaded_dns->set (host,tb,1); } return ret; } static void dnsconf_filltb (SSTRINGS &tb, const char *tbstr[], int nbstr) { for (int i=0; isetmx (host,tb,ttls); } static int dnsconf_api_setns( const char *host, const char *tbns[], int nbns) { SSTRINGS tb; dnsconf_filltb(tb,tbns,nbns); SSTRINGS ttls; return loaded_dns->setns (host,tb,ttls); } static int dnsconf_api_setcname( const char *host, const char *nickname) { return loaded_dns->setcname (host,nickname); } static int dnsconf_api_unset(const char *host) { loaded_dns->unset (host); return 0; } static int dnsconf_api_geta(const char *host, IP_ADDRS &tbip) { return loaded_dns->geta (host,tbip); } static int dnsconf_api_getns(const char *host, SSTRINGS &tbns) { PRIMARY *pri = loaded_dns->findprimary (host); int ret = 0; if (pri != NULL){ SSTRING s (host); SSTRINGS ttls; ret = pri->getns (s,tbns,ttls); } return ret; } static int dnsconf_api_getmx(const char *host, SSTRINGS &tbmx) { PRIMARY *pri = loaded_dns->findprimary (host); int ret = 0; if (pri != NULL){ SSTRING s (host); SSTRINGS ttls; ret = pri->getmx (s,tbmx,ttls); } return ret; } static int dnsconf_api_write () { return loaded_dns->write(); } static int dnsconf_newdomain (const char *newdomain, const char *templ) { return loaded_dns->newdomain (newdomain,templ); } static int dnsconf_deldomain(const char *domain) { return loaded_dns->deldomain (domain); } static int dnsconf_delsecondary(const char *domain) { return loaded_dns->delsecondary (domain); } static int dnsconf_newsecondary(const char *domain, const char *primaries[], int nbprim) { return loaded_dns->newsecondary (domain,primaries,nbprim); } void *dnsconf_api_get () { DNSCONF_API *api = new DNSCONF_API; api->set = dnsconf_api_set; api->setfromip = dnsconf_api_setfromip; api->setfromrange = dnsconf_api_setfromrange; api->setmx = dnsconf_api_setmx; api->setns = dnsconf_api_setns; api->setcname = dnsconf_api_setcname; api->unset = dnsconf_api_unset; api->geta = dnsconf_api_geta; api->getns = dnsconf_api_getns; api->getmx = dnsconf_api_getmx; api->write = dnsconf_api_write; api->newdomain = dnsconf_newdomain; api->deldomain = dnsconf_deldomain; api->delsecondary = dnsconf_delsecondary; api->newsecondary = dnsconf_newsecondary; dns_load(); return api; } void dnsconf_api_release (void *api) { delete (DNSCONF_API*)api; dns_unload(); }