#include #include #include #include #include #include #include #include #include "internal.h" #include "dnsconf.h" #include "dnsconf.m" #include #include static DNSCONF_HELP_FILE help_secondary("secondary"); static DNSCONF_HELP_FILE help_update ("zferzone"); static const char *tbargs[]={"generic-service-name","operation",NULL}; static MESSAGE_DEF msg_servicectl ("servicectl",tbargs); /* Read the content of the zone file and update the transfered flag Return -1 if the read was not successful. */ PRIVATE int SECONDARY::readzone( const char *named_dir, bool extract) { origins.remove_all(); // This may be called when triggering // a zone transfer so we must forget what // we know yet int ret = origins.read (named_dir,file.get(),domain.get(),false); if (ret==-1) { transfered=false; } else { transfered=true; } return ret; } PUBLIC SECONDARY::SECONDARY( const char *_domain, const char *_file, const char *named_dir, bool extract, const char **_ip_addr, int nb_ip) { domain.setfrom (_domain); file.setfrom (_file); for (int i=0; iget(); if (s[0] != '\0') fprintf (fout,"\t\t%s;\n",s); } fputs ("\t};\n",fout); writeaccess (fout); fputs ("};\n",fout); }else{ fprintf (fout,"secondary\t%s",domain.get()); for (int i=0; iget()); } fprintf (fout,"\t%s\n",file2.get()); } } PROTECTED void ZONE::remove_empty() { allowtrans.remove_empty(); allowquery.remove_empty(); allowrecursion.remove_empty(); allowupdate.remove_empty(); alsonotify.remove_empty(); for (int i=0; iis_empty()){ addrs.remove_del(i); i--; } } } static char sec_ip[10]; static const char ID_SECONDARY[]="secondary"; /* Edit the minimal spec so this dns will act as a secondary for another Return -1 if the user escaped away. Return 0 if the changes are accepted Return 1 if the user wish to delete this entry */ PUBLIC int SECONDARY::edit (SECONDARYS &secs, DNS &dns, bool isnew) { DIALOG dia; dia.set_registry_id (ID_SECONDARY); dia.newf_str (MSG_R(F_DOMAIN),domain); dia.newf_title (MSG_U(F_SECLIST,"Master server(s)"),1,"",MSG_R(F_SECLIST)); int field_ip = dia.getnb(); for (int i=0; i<3; i++) addrs.add (new IP_ADDR); { FIELD *f = dia.newf_ipnum (MSG_U(F_IPSERV,"IP address of the server"),*addrs.getitem(0)); f->set_registry_key (&sec_ip[0]); for (int i=1; iset_registry_key (&sec_ip[i]); } } if (dns.bind8) setupzoneaccess (dia,1); int ret = -1; int nof = 0; dia.setbutinfo (MENU_USR1,MSG_U(B_PREVIEW,"Preview"),MSG_R(B_PREVIEW)); dia.setbutinfo (MENU_USR2,MSG_U(B_UPDATE,"Update"),MSG_R(B_UPDATE)); while (1){ MENU_STATUS status = dia.edit ( MSG_R(T_SECSPEC) ,MSG_U(I_SECSPEC ,"You must enter a domain and at least IP address\n" "of one DNS server of that domain\n") ,help_secondary ,nof ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_DEL|MENUBUT_USR1|MENUBUT_USR2); if (status == MENU_CANCEL || status == MENU_ESCAPE){ break; }else if (status == MENU_DEL){ if (xconf_areyousure(MSG_U(Q_DELSECONDARY ,"Confirm deletion of a secondary spec"))){ ret = 1; break; } }else if (status == MENU_USR1){ if (transfered){ show (dns); }else{ xconf_notice (MSG_U(N_NOTTRANSYET ,"The zone information has not been transfered\n" "from the primary server yet!")); } }else if (status == MENU_USR2){ if (dialog_yesno(MSG_U(Q_UPDATESLAVE,"Update secondary zone") ,MSG_U(I_UPDATESLAVE ,"Do you want to update this zone from the primary server(s)") ,help_update)==MENU_YES){ dia.save(); if (isnew) secs.add (this); remove_empty(); dns.write(); char args[PATH_MAX]; const char *named_dir = dns.getcfgdir(); SSTRING file2,abspath; setzonefile(file2,dns.getcfgdir()); const char *path = file2.get(); if (path[0] == '/'){ abspath.setfrom (file2); }else{ abspath.setfromf ("%s/%s",named_dir,path); } static const char *argv[]={"nameserver","reload"}; module_sendmessage (msg_servicectl,2,argv); // Find out how to force the zone transfer based // on bind version const char *cmd; if (dnsconf_bindnewer("9.0")){ cmd = "rndc"; snprintf (args,sizeof(args)-1,"reload %s",domain.get()); }else{ cmd = "named-xfer"; snprintf (args,sizeof(args)-1,"-z %s -f %s -s 0" ,domain.get(),abspath.get()); for (int i=0; iget()); } } if (netconf_system_if (cmd,args)!=-1){ readzone (named_dir,false); } ret = 0; break; } }else{ const char *domname = domain.get(); SECONDARY *sec = dns.findsecond (domname); PRIMARY *dom = dns.finddomain (domname); if (domain.is_empty() || addrs.getitem(0)->is_empty()){ xconf_error(MSG_U(E_FILLDOM ,"Fill at least the domain\n" "and the first IP address")); }else if (sec != NULL && sec != this){ xconf_error (MSG_R(E_DOMEXIST)); }else if (dom != NULL){ xconf_error (MSG_U(E_ISAPRIMARY ,"This DNS is already a primary for this domain.\n" "It can't be both at the same time")); }else{ // Make sure all IP are valid bool error = false; for (int i=0; iis_filled() && !ipnum_validip(ip->get(),true)){ nof = field_ip + i; error = true; xconf_error (MSG_R(E_IVLDIP),ip->get()); break; } } if (!error){ remove_empty(); if (isnew) secs.add (this); dns.write(); ret = 0; break; } } } } if (ret != 0) dia.restore(); remove_empty(); return ret; } PUBLIC SECONDARY *SECONDARYS::getitem (int no) const { return (SECONDARY*)ARRAY::getitem(no); } PUBLIC SECONDARY *SECONDARYS::getitem (const char *name) const { SECONDARY *ret = NULL; int n = getnb(); for (int i=0; idomain.cmp(name)==0){ ret = s; break; } } return ret; } PUBLIC void SECONDARYS::write (bool bind8, FILE_CFG *fout, const char *named_dir) const { for (int i=0; iwrite(bind8,fout,named_dir); } static int cmp_secondary_by_name (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2) { SECONDARY *s1 = (SECONDARY*)o1; SECONDARY *s2 = (SECONDARY*)o2; return s1->domainv.cmp(s2->domainv); } PUBLIC void SECONDARYS::edit(DNS &dns) { int choice=0; DIALOG_LISTE dia; dia.newf_head ("",MSG_U(H_SECONDARIES,"domain\tprimarys\tRevision date\tRevision count")); dia.addwhat (MSG_U(I_ADDSEC,"Select [Add] to add one secondary spec")); while (1){ int nb = getnb(); SECONDARYS sorted; sorted.neverdelete(); for (int i=0; iaddrs.getnb(); a++){ if (!s->addrs.getitem(a)->is_empty()){ pt += sprintf (pt,ctl,s->addrs.getitem(a)->get()); ctl = ",%s"; } } *pt++ = '\t'; *pt = '\0'; s->format_revision(pt); dia.set_menuitem (i,s->domain.get(),buf); } dia.remove_last (nb+1); MENU_STATUS code = dia.editmenu (MSG_U(T_SECONDARYS,"Secondaries") ,MSG_U(I_SECONDARYS ,"You are allowed to edit/add/remove secondaries\n") ,help_secondary ,choice,0); if (code == MENU_QUIT || code == MENU_ESCAPE){ break; }else if (code == MENU_ADD){ SECONDARY *sec = new SECONDARY; if (sec->edit(*this,dns,true)!=0){ delete sec; } }else{ SECONDARY *sec = sorted.getitem(choice); if (sec != NULL){ int ok = sec->edit(*this,dns,false); if (ok != -1){ if (ok == 1) remove_del (sec); dns.write(); } } } } } /* Locate a secondary in the DNS Return NULL if not found. */ PUBLIC SECONDARY *DNS::locate_secondary(const char *domain) { SECONDARY *ret = NULL; for (int d=0; ddomain.icmp(domain)==0){ ret = p; break; } } return ret; } /* Delete one secondary from the DNS. Return -1 if not found. */ PUBLIC int DNS::delsecondary (const char *domain) { int ret = -1; SECONDARY *sec = locate_secondary (domain); if (sec != NULL){ secondarys.remove_del(sec); ret = 0; } return ret; } static bool sec_validip (const char *primaries[], int nbprim) { bool ret = true; for (int i=0; idomain.setfrom (domain); sec->file.setfromf ("sec/%s",domain); for (int i=0; iaddrs.add (new IP_ADDR(primaries[i])); } secondarys.add (sec); ret = 0; } return ret; } PUBLIC int DNS::newsecondary ( const char *domain, const char *primaries[], // IP number of the primaries int nbprim) // Number of IP in the table { int ret = -1; if (nbprim <= 0 || nbprim > 4 || !sec_validip(primaries,nbprim)){ fprintf (stderr,MSG_U(E_NBPRIM ,"You must supply between 1 and 4 primary servers\n" "One IP number for each\n")); }else{ ret = newsecondary_common (domain,primaries,nbprim); } return ret; } PRIVATE int DNS::newsecondary ( const char *domain) { return newsecondary_common (domain,NULL,0); } /* Extract the list of secondaries */ PUBLIC void DNS::listslaves(SSTRINGS &tb) { for (int i=0; idomain)); } } static void secondary_listdomains(SSTRINGS &tb) { DNS *dns = dns_load(); dns->listslaves(tb); dns_unload(); } PUBLIC void DNS::editsecondary (const char *key, bool force) { SECONDARY *sec = locate_secondary (key); if (sec == NULL){ if (force && newsecondary(key)!=-1){ sec = locate_secondary (key); if (sec->edit(secondarys,*this,false)!=0){ delsecondary(key); } } }else{ sec->edit(secondarys,*this,false); } } static void secondary_editdomain(const char *key, bool force) { DNS *dns = dns_load(); dns->editsecondary (key,force); dns_unload(); } #include static PUBLISH_VARIABLES_MSG secondary_list1[]={ {"domain",P_MSG_R(F_DOMAIN)}, { NULL, NULL } }; static PUBLISH_VARIABLES_STR secondary_list2[]={ {"ip1", &sec_ip[0]}, {"ip2", &sec_ip[1]}, {"ip3", &sec_ip[2]}, { NULL, NULL } }; static REGISTER_VARIABLES secondary_registry1("secondary","domains" ,secondary_list1 ,ID_SECONDARY,secondary_editdomain,secondary_listdomains); static REGISTER_VARIABLES secondary_registry2("secondary","domains" ,secondary_list2 ,ID_SECONDARY,secondary_editdomain,secondary_listdomains); extern PUBLISH_VARIABLES_STR zone_variables[]; static REGISTER_VARIABLES secondary_registry3("secondary","domains" ,zone_variables ,ID_SECONDARY,secondary_editdomain,secondary_listdomains);