ona  18.1.1
About: OpenNetAdmin provides a database managed inventory of your IP network (with Web and CLI interface).
  Fossies Dox: ona-18.1.1.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

dns_record.inc.php
Go to the documentation of this file.
1 <?php
2 // DON'T put whitespace at the beginning or end of this file!!!
3 
4 
5 
6 
7 
9 // Function: dns_record_add (string $options='')
10 //
11 // Input Options:
12 // $options = key=value pairs of options for this function.
13 // multiple sets of key=value pairs should be separated
14 // by an "&" symbol.
15 //
16 // Output:
17 // Returns a two part list:
18 // 1. The exit status of the function. 0 on success, non-zero on
19 // error. All errors messages are stored in $self['error'].
20 // 2. A textual message for display on the console or web interface.
21 //
22 // Example: list($status, $result) = dns_record_add('host=test&type=something');
24 function dns_record_add($options="") {
25  global $conf, $self, $onadb;
26 
27  // Version - UPDATE on every edit!
28  $version = '1.12';
29 
30  printmsg("DEBUG => dns_record_add({$options}) called", 3);
31 
32  // Parse incoming options string to an array
33  $options = parse_options($options);
34 
35  // Return the usage summary if we need to
36  if ($options['help'] or !($options['name'] and $options['type']) ) {
37  // NOTE: Help message lines should not exceed 80 characters for proper display on a console
38  $self['error'] = 'ERROR => Insufficient parameters';
39  return(array(1,
40 <<<EOM
41 
43 Add a new DNS record
44 
45  Synopsis: dns_record_add [KEY=VALUE] ...
46 
47  Required:
48  name=NAME[.DOMAIN] hostname for new DNS record
49  type=TYPE record type (A,CNAME,PTR...)
50 
51  Optional:
52  notes=NOTES textual notes
53  ip=ADDRESS ip address (numeric or dotted)
54  ttl=NUMBER time in seconds, defaults to ttl from domain
55  pointsto=NAME[.DOMAIN] hostname that a CNAME,NS,MX etc points to
56  addptr auto add a PTR record when adding A records
57  mx_preference=NUMBER preference for the MX record
58  txt=STRING text value of a TXT record
59  srv_pri=NUMBER SRV Priority
60  srv_weight=NUMBER SRV Weight
61  srv_port=NUMBER SRV Port
62  ebegin=date Set the begin date for record, 0 disables, default now
63  domain=DOMAIN use only if you need to explicitly set a parent domain
64  view=STRING DNS view identifier. AKA Split horizon.
65 
66  Examples:
67  dns_record_add name=newhost.something.com type=A ip=10.1.1.2 addptr
68  dns_record_add name=somedomain.com type=NS pointsto=ns.somedomain.com
69  dns_record_add name=cname.domain.com type=CNAME pointsto=host.domain.com
70  dns_record_add name=host.something.com type=TXT txt="my text value"
71  dns_record_add name=domain.com type=MX pointsto=mxhost.domain.com mx_preference=10
72  dns_record_add name=_foo._tcp.example.com type=SRV pointsto=host.domain.com srv_port=80
73  dns_record_add name=newhost.something.com type=PTR ip=10.1.1.10
74 
75  DOMAIN will default to {$conf['dns_defaultdomain']} if not specified.
76 
77 
78 EOM
79  ));
80  }
81 
82 
83 /*
84 thoughts on the flow of things:
85 
86 a records:
87  check if there is an A record with that name/domain and IP already.
88  check that name/domain does not match a CNAME entry
89  will not have a dns_id value.. blank it out
90  if autoptr is set, create a ptr record too
91 cname records:
92  check that name/domain does not match an A entry
93  check that name/domain does not match an CNAME entry
94  name/domain and dns_id columns must be unique---< implied by the previous check of no cnames using this name
95  do I need interface_id??????, yes its used to assoicate it with the host. this will come via the A record it points to via a lookup
96 ptr records:
97  must be unique in interface_id column, ie. one PTR per interface/ip
98 
99 
100 
101 
102 FIXME: do some validation of the different options, pointsto only with cname type etc etc
103 
104 FIXME: what about when you add an entry with a name that matches a primary dns record that already exists. while adding
105 multiple A records that have the same name is ok, its not really a good thing to have the primary name for a host be duplicated. the
106 primary name for a host should be unique in all cases I'm aware of
107 
108 */
109 
110  // Sanitize addptr.. set it to Y if it is not set
111  $options['addptr'] = sanitize_YN($options['addptr'], 'Y');
112 
113  // clean up what is passed in
114  $options['ip'] = trim($options['ip']);
115  $options['pointsto'] = trim($options['pointsto']);
116  $options['name'] = trim($options['name']);
117  $options['domain'] = trim($options['domain']);
118  $options['txt'] = trim($options['txt']);
119  $options['view'] = trim($options['view']);
120 
121  // Check the date formatting etc
122  if (isset($options['ebegin'])) {
123  // format the time that was passed in for the database, leave it as 0 if they pass it as 0
124  $options['ebegin']=($options['ebegin'] == '0' ? 0 : date('Y-m-j G:i:s',strtotime($options['ebegin'])) );
125  } else {
126  // If I got no date, use right now as the date/time
127  $options['ebegin'] = date('Y-m-j G:i:s');
128  }
129 
130  // Switch the type setting to uppercase
131  $options['type'] = strtoupper($options['type']);
132  $add_txt = '';
133  $add_mx_preference = 0;
134  $add_srv_pri = 0;
135  $add_srv_weight = 0;
136  $add_srv_port = 0;
137 
138  // force AAAA to A to keep it consistant.. we'll display it properly as needed
139  if ($options['type'] == 'AAAA') $options['type'] = 'A';
140 
141  // If the name we were passed has a leading or trailing . in it then remove the dot.
142  $options['name'] = preg_replace("/^\./", '', $options['name']);
143  $options['name'] = preg_replace("/\.$/", '', $options['name']);
144 
145  // Determine the real hostname and domain name to be used --
146  // i.e. add .something.com, or find the part of the name provided
147  // that will be used as the "domain". This means testing many
148  // domain names against the DB to see what's valid.
149  //
150 
151  // If we are specifically passing in a domain, use its value. If we dont have a domain
152  // then try to find it in the name that we are setting.
153  if($options['domain']) {
154  // Find the domain name piece of $search
155  list($status, $rows, $domain) = ona_find_domain($options['domain'],0);
156  } else {
157  list($status, $rows, $domain) = ona_find_domain($options['name'],0);
158  }
159 
160  // Find the domain name piece of $search.
161  if (!isset($domain['id'])) {
162  printmsg("ERROR => Unable to determine domain name portion of ({$options['name']})!", 3);
163  $self['error'] = "ERROR => Unable to determine domain name portion of ({$options['name']})!";
164  return(array(3, $self['error'] . "\n"));
165  }
166 
167  printmsg("DEBUG => ona_find_domain({$options['name']}) returned: {$domain['fqdn']}", 3);
168 
169  // Now find what the host part of $search is
170  $hostname = str_replace(".{$domain['fqdn']}", '', $options['name']);
171 
172  // Validate that the DNS name has only valid characters in it
173  $hostname = sanitize_hostname($hostname);
174  if (!$hostname) {
175  printmsg("ERROR => Invalid host name ({$options['name']})!", 3);
176  $self['error'] = "ERROR => Invalid host name ({$options['name']})!";
177  return(array(4, $self['error'] . "\n"));
178  }
179 
180  // If the hostname we came up with and the domain name are the same, then assume this is
181  // meant to be a domain specific record, like A, MX, NS type records.
182  if ($hostname == $domain['fqdn']) $hostname = '';
183 
184  // Debugging
185  printmsg("DEBUG => Using hostname: {$hostname} Domainname: {$domain['fqdn']}, Domain ID: {$domain['id']}", 3);
186 
187 
188  // If we are using anything but in-addr.arpa for PTR or NS records, fail out!
189  if ((strpos($domain['fqdn'], "ip6.arpa") or strpos($domain['fqdn'], "in-addr.arpa")) and $options['type'] != 'PTR' and $options['type'] != 'NS') {
190  printmsg("ERROR => Only PTR and NS records should use in-addr.arpa or ip6.arpa domains!", 3);
191  $self['error'] = "ERROR => Only PTR and NS records should use in-addr.arpa or ip6.arpa domains!";
192  return(array(4, $self['error'] . "\n"));
193  }
194 
195 
196 
197  // Gather DNS view information
198  $add_pointsto_viewid = $add_viewid = 0;
199  if ($options['view']) {
200  if (is_numeric($options['view'])) {
201  $viewsearch = array('id' => $options['view']);
202  } else {
203  $viewsearch = array('name' => strtoupper($options['view']));
204  }
205  // find the view record,
206  list($status, $rows, $dnsview) = ona_get_dns_view_record($viewsearch);
207  if (!$rows) {
208  printmsg("ERROR => dns_record_add() Unable to find DNS view: {$options['view']}",3);
209  $self['error'] = "ERROR => dns_record_add() Unable to find DNS view: {$options['view']}.";
210  return(array(4, $self['error'] . "\n"));
211  }
212 
213  $add_pointsto_viewid = $add_viewid = $dnsview['id'];
214  }
215 
216  // lets test out if it has a / in it to strip the view name portion
217  if (strstr($options['pointsto'],'/')) {
218  list($dnsview,$options['pointsto']) = explode('/', $options['pointsto']);
219  list($status, $rows, $view) = db_get_record($onadb, 'dns_views', array('name' => strtoupper($dnsview)));
220  if($rows) $add_pointsto_viewid = $view['id'];
221  }
222 
223  // Set a message to display when using dns views
224  if ($conf['dns_views']) $viewmsg = ' Ensure you are selecting the proper DNS view for this record.';
225 
226  // Process A or AAAA record types
227  if ($options['type'] == 'A' or $options['type'] == 'AAAA') {
228  // find the IP interface record,
229  list($status, $rows, $interface) = ona_find_interface($options['ip']);
230  if (!$rows) {
231  printmsg("ERROR => dns_record_add() Unable to find existing IP interface: {$options['ip']}",3);
232  $self['error'] = "ERROR => dns_record_add() Unable to find IP interface: {$options['ip']}. A records must point to existing IP addresses. Please add an interface with this IP address first.";
233  return(array(4, $self['error'] . "\n"));
234  }
235 
236  // Validate that there isn't already any dns record named $hostname in the domain $domain_id.
237  list($d_status, $d_rows, $d_record) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'interface_id' => $interface['id'],'type' => 'A', 'dns_view_id' => $add_viewid));
238  if ($d_status or $d_rows) {
239  printmsg("ERROR => Another DNS A record named {$hostname}.{$domain['fqdn']} with IP {$interface['ip_addr_text']} already exists!{$viewmsg}",3);
240  $self['error'] = "ERROR => Another DNS A record named {$hostname}.{$domain['fqdn']} with IP {$interface['ip_addr_text']} already exists!{$viewmsg}";
241  return(array(5, $self['error'] . "\n"));
242  }
243 
244  // Validate that there are no CNAMES already with this fqdn
245  list($c_status, $c_rows, $c_record) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'type' => 'CNAME','dns_view_id' => $add_viewid));
246  if ($c_rows or $c_status) {
247  printmsg("ERROR => Another DNS CNAME record named {$hostname}.{$domain['fqdn']} already exists!{$viewmsg}",3);
248  $self['error'] = "ERROR => Another DNS CNAME record named {$hostname}.{$domain['fqdn']} already exists!{$viewmsg}";
249  return(array(5, $self['error'] . "\n"));
250  }
251 
252 
253  $add_name = $hostname;
254  $add_domainid = $domain['id'];
255  $add_interfaceid = $interface['id'];
256  // A records should not have parent dns records
257  $add_dnsid = 0;
258 
259  // Dont print a dot unless hostname has a value
260  if ($hostname) $hostname = $hostname.'.';
261 
262  $info_msg = "{$hostname}{$domain['fqdn']} -> " . ip_mangle($interface['ip_addr'],'dotted');
263 
264  // Just to be paranoid, I'm doing the ptr checks here as well if addptr is set
265  if ($options['addptr'] == 'Y') {
266  // Check that no other PTR records are set up for this IP
267  list($status, $rows, $record) = ona_get_dns_record(array('interface_id' => $interface['id'], 'type' => 'PTR','dns_view_id' => $add_viewid));
268  if ($rows) {
269  printmsg("ERROR => Another DNS PTR record already exists for this IP interface!{$viewmsg}",3);
270  $self['error'] = "ERROR => Another DNS PTR record already exists for this IP interface!{$viewmsg}";
271  return(array(5, $self['error'] . "\n"));
272  }
273  }
274 
275  }
276 
277 // I think I fixed this.. more testing needed.. no GUI option yet either.
278  // MP: FIXME: there is an issue that you cant have just a ptr record with no A record. so you cant add something like:
279 /*
280 router.example.com A 10.1.1.1
281 
282 10.1.2.1 PTR router.example.com
283 10.1.3.1 PTR router.example.com
284 10.1.4.1 PTR router.example.com
285 
286 This is a senario where you want just the loopback interface of a router to respond as the A record,
287 but you still want to reverse lookup all the other interfaces to know they are on router.example.com
288 
289 --- I think if I add a "build A record" flag so that the A record wont build in DNS but the PTR could.. doesnt work since multiple a record entries will exist and they are not really tied together.??
290 */
291  // Process PTR record types
292  else if ($options['type'] == 'PTR') {
293  // find the IP interface record,
294  list($status, $rows, $interface) = ona_find_interface($options['ip']);
295  if (!$rows) {
296  printmsg("ERROR => dns_record_add() Unable to find IP interface: {$options['ip']}",3);
297  $self['error'] = "ERROR => dns_record_add() Unable to find IP interface: {$options['ip']}. PTR records must point to existing IP addresses. Please add an interface with this IP address first.";
298  return(array(4, $self['error'] . "\n"));
299  }
300 
301 
302  // Check that no other PTR records are set up for this IP
303  list($status, $rows, $record) = ona_get_dns_record(array('interface_id' => $interface['id'], 'type' => 'PTR','dns_view_id' => $add_viewid));
304  if ($rows) {
305  printmsg("ERROR => Another DNS PTR record already exists for this IP interface!{$viewmsg}",3);
306  $self['error'] = "ERROR => Another DNS PTR record already exists for this IP interface!{$viewmsg}";
307  return(array(5, $self['error'] . "\n"));
308  }
309 
310  // Find the dns record that it will point to
311 
312  list($status, $rows, $arecord) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'interface_id' => $interface['id'], 'type' => 'A','dns_view_id' => $add_viewid));
313  if ($status or !$rows) {
314  printmsg("ERROR => Unable to find DNS A record to point PTR entry to! Check that the IP you chose is associated with the name you chose.{$viewmsg}",3);
315  $self['error'] = "ERROR => Unable to find DNS A record to point PTR entry to! Check that the IP you chose is associated with the name you chose.{$viewmsg}";
316 
317  // As a last resort just find a matching A record no matter the IP.
318  // This is for PTRs that point to an A record that uses a different IP (loopback example)
319 
320  // MP: since there could be multiple A records, I'm going to fail out if there is not JUST ONE A record.
321  // this is limiting in a way but allows cleaner data.
322  list($status, $rows, $arecord) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'], 'type' => 'A','dns_view_id' => $add_viewid));
323  if (($rows > 1)) {
324  printmsg("ERROR => Unable to find a SINGLE DNS A record to point PTR entry to! In this case, you are only allowed to do this if there is one A record using this name.{$viewmsg}",3);
325  $self['error'] = "ERROR => Unable to find a SINGLE DNS A record to point PTR entry to! In this case, you are only allowed to do this if there is one A record using this name.{$viewmsg}";
326  }
327 
328  if ($rows != 1)
329  return(array(66, $self['error'] . "\n"));
330  }
331 
332 
333  $ipflip = ip_mangle($interface['ip_addr'],'flip');
334  $octets = explode(".",$ipflip);
335  if (count($octets) > 4) {
336  $arpa = '.ip6.arpa';
337  $octcount = 31;
338  } else {
339  $arpa = '.in-addr.arpa';
340  $octcount = 3;
341  }
342  // Find a pointer zone for this record to associate with.
343  list($status, $rows, $ptrdomain) = ona_find_domain($ipflip.$arpa);
344 // if (!$ptrdomain['id']) {
345 // printmsg("ERROR => Unable to find a reverse pointer domain for this IP! Add at least the following DNS domain: {$octets[3]}.in-addr.arpa",3);
346 // $self['error'] = "ERROR => Unable to find a reverse pointer domain for this IP! Add at least the following DNS domain: {$octets[3]}.in-addr.arpa";
347 // return(array(5, $self['error'] . "\n"));
348 // }
349  if (!$ptrdomain['id']) {
350  printmsg("ERROR => This operation tried to create a PTR record that is the first in this address space. You must first create at least the following DNS domain: {$octets[$octcount]}{$arpa}",3);
351  $self['error'] = "ERROR => This operation tried to create a PTR record that is the first in this address space. You must first create at least the following DNS domain: {$octets[$octcount]}{$arpa}. You could also create domains for deeper level reverse zones.";
352  return(array(9, $self['error'] . "\n"));
353  }
354 
355  // PTR records dont need a name set.
356  $add_name = '';
357  // PTR records should not have domain_ids
358  $add_domainid = $ptrdomain['id'];
359  $add_interfaceid = $interface['id'];
360  $add_dnsid = $arecord['id'];
361 
362  // Dont print a dot unless hostname has a value
363  if ($hostname) $hostname = $hostname.'.';
364 
365  $info_msg = "{$ipflip}{$arpa} -> {$hostname}{$domain['fqdn']}";
366 
367  }
368 
369 
370 /*
371 FIXME: MP
372 So there is this fun problem with CNAMES. I can associate them with a single A record
373 such that if that A record is changed, or gets removed then I can cleanup/update the CNAME entry.
374 
375 The problem comes when there are multiple A records that use the same name but different IP addresses.
376 I can only assoicate the CNAME with one of those A records. This also means I need to provided
377 the IP address as well when adding a CNAME so I can choose the correct A record.
378 
379 The same sort of issue applies to PTR records as well.
380 
381 In a similar (reverse) issue. If I have those same multiple A records, the assumption is that
382 they are all the same name and thus "tied" together in that if I was to change the name to something else
383 all the A records should all change at once. Currently I'd have to change ALL the A record entries with the same name manually
384 
385 
386 Its almost like I'd need a dns_record to name many to one type table. that would be very annoying!
387 
388 
389 For now, I'm going to keep going forward as is and hope that even though it is allowed, most people will not create such
390 complex DNS messes for themselves.
391 
392 
393 */
394 
395 
396 
397  // Process CNAME record types
398  else if ($options['type'] == 'CNAME') {
399  // Determine the host and domain name portions of the pointsto option
400  // Find the domain name piece of $search
401  list($status, $rows, $pdomain) = ona_find_domain($options['pointsto']);
402  printmsg("DEBUG => ona_find_domain({$options['pointsto']}) returned: {$domain['fqdn']} for pointsto.", 3);
403 
404  // Now find what the host part of $search is
405  $phostname = str_replace(".{$pdomain['fqdn']}", '', $options['pointsto']);
406 
407  // Validate that the DNS name has only valid characters in it
408  $phostname = sanitize_hostname($phostname);
409  if (!$phostname) {
410  printmsg("ERROR => Invalid pointsto host name ({$options['pointsto']})!", 3);
411  $self['error'] = "ERROR => Invalid pointsto host name ({$options['pointsto']})!";
412  return(array(4, $self['error'] . "\n"));
413  }
414  // Debugging
415  printmsg("DEBUG => Using 'pointsto' hostname: {$phostname}.{$pdomain['fqdn']}, Domain ID: {$pdomain['id']}", 3);
416 
417  // Validate that the CNAME I'm adding doesnt match an existing A record.
418  list($d_status, $d_rows, $d_record) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'type' => 'A','dns_view_id' => $add_viewid));
419  if ($d_status or $d_rows) {
420  printmsg("ERROR => Another DNS A record named {$hostname}.{$domain['fqdn']} already exists!{$viewmsg}",3);
421  $self['error'] = "ERROR => Another DNS A record named {$hostname}.{$domain['fqdn']} already exists!{$viewmsg}";
422  return(array(5, $self['error'] . "\n"));
423  }
424 
425 
426  // Validate that there are no CNAMES already with this fqdn
427  list($c_status, $c_rows, $c_record) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'type' => 'CNAME','dns_view_id' => $add_viewid));
428  if ($c_rows or $c_status) {
429  printmsg("ERROR => Another DNS CNAME record named {$hostname}.{$domain['fqdn']} already exists!{$viewmsg}",3);
430  $self['error'] = "ERROR => Another DNS CNAME record named {$hostname}.{$domain['fqdn']} already exists!{$viewmsg}";
431  return(array(5, $self['error'] . "\n"));
432  }
433 
434  // Find the dns record that it will point to
435  list($status, $rows, $pointsto_record) = ona_get_dns_record(array('name' => $phostname, 'domain_id' => $pdomain['id'], 'type' => 'A','dns_view_id' => $add_viewid));
436  if ($status or !$rows) {
437  printmsg("ERROR => Unable to find DNS A record to point CNAME entry to!{$viewmsg}",3);
438  $self['error'] = "ERROR => Unable to find DNS A record to point CNAME entry to!{$viewmsg}";
439  return(array(5, $self['error'] . "\n"));
440  }
441 
442 
443 
444  $add_name = $hostname;
445  $add_domainid = $domain['id'];
446  $add_interfaceid = $pointsto_record['interface_id'];
447  $add_dnsid = $pointsto_record['id'];
448 
449  // Dont print a dot unless hostname has a value
450  if ($hostname) $hostname = $hostname.'.';
451 
452  $info_msg = "{$hostname}{$domain['fqdn']} -> {$phostname}.{$pdomain['fqdn']}";
453 
454  }
455 
456 
457 
458  // Process NS record types
459  // NS is a domain_id that points to another dns_id A record
460  // this will give you "mydomain.com IN NS server.somedomain.com"
461  else if ($options['type'] == 'NS') {
462  // find the domain
463  list($status, $rows, $domain) = ona_find_domain($options['name'],0);
464  if (!$domain['id']) {
465  printmsg("ERROR => Invalid domain name ({$options['name']})!", 3);
466  $self['error'] = "ERROR => Invalid domain name ({$options['name']})!";
467  return(array(4, $self['error'] . "\n"));
468  }
469  // Determine the host and domain name portions of the pointsto option
470  // Find the domain name piece of $search
471  list($status, $rows, $pdomain) = ona_find_domain($options['pointsto']);
472  printmsg("DEBUG => ona_find_domain({$options['pointsto']}) returned: {$pdomain['fqdn']} for pointsto.", 3);
473 
474  // Now find what the host part of $search is
475  $phostname = str_replace(".{$pdomain['fqdn']}", '', $options['pointsto']);
476 
477  // lets test out if it has a / in it to strip the view name portion
478 // if (strstr($phostname,'/')) {
479 // list($dnsview,$phostname) = explode('/', $phostname);
480 // list($status, $rows, $view) = db_get_record($onadb, 'dns_views', array('name' => strtoupper($dnsview)));
481 // if($rows) $add_pointsto_viewid = $view['id'];
482 // }
483 
484  // Validate that the DNS name has only valid characters in it
485  $phostname = sanitize_hostname($phostname);
486  if (!$phostname) {
487  printmsg("ERROR => Invalid pointsto host name ({$options['pointsto']})!", 3);
488  $self['error'] = "ERROR => Invalid pointsto host name ({$options['pointsto']})!";
489  return(array(4, $self['error'] . "\n"));
490  }
491  // Debugging
492  printmsg("DEBUG => Using 'pointsto' hostname: {$phostname}.{$pdomain['fqdn']}, Domain ID: {$pdomain['id']}", 3);
493 
494  // Find the dns record that it will point to
495  list($status, $rows, $pointsto_record) = ona_get_dns_record(array('name' => $phostname, 'domain_id' => $pdomain['id'], 'type' => 'A','dns_view_id' => $add_pointsto_viewid));
496  if ($status or !$rows) {
497  printmsg("ERROR => Unable to find DNS A record to point NS entry to!{$viewmsg}",3);
498  $self['error'] = "ERROR => Unable to find DNS A record to point NS entry to!{$viewmsg}";
499  return(array(5, $self['error'] . "\n"));
500  }
501 
502  // Validate that there are no NS already with this domain and host
503  list($status, $rows, $record) = ona_get_dns_record(array('dns_id' => $pointsto_record['id'], 'domain_id' => $domain['id'],'type' => 'NS','dns_view_id' => $add_viewid));
504  if ($rows or $status) {
505  printmsg("ERROR => Another DNS NS record for {$domain['fqdn']} pointing to {$options['pointsto']} already exists!{$viewmsg}",3);
506  $self['error'] = "ERROR => Another DNS NS record for {$domain['fqdn']} pointing to {$options['pointsto']} already exists!{$viewmsg}";
507  return(array(5, $self['error'] . "\n"));
508  }
509 
510 
511  $add_name = ''; //$options['name'];
512  $add_domainid = $domain['id'];
513  $add_interfaceid = $pointsto_record['interface_id'];
514  $add_dnsid = $pointsto_record['id'];
515 
516  $info_msg = "{$options['name']} -> {$phostname}.{$pdomain['fqdn']}";
517 
518  }
519  // Process MX record types
520  // MX is a domain_id or host/domain_id that points to another dns_id A record
521  else if ($options['type'] == 'MX') {
522  // If there is no mx_preference set then stop
523  if (!isset($options['mx_preference']) or ($options['mx_preference'] < 0 or $options['mx_preference'] > 65536)) {
524  printmsg("ERROR => You must provide an MX preference value when creating MX records!", 3);
525  $self['error'] = "ERROR => You must provide an MX preference value when creating MX records!";
526  return(array(4, $self['error'] . "\n"));
527  }
528  // Lets try to find the name as a domain first.. if it matches a domain use that, othewise search for an A record
529  $hostname = '';
530  list($status, $rows, $domain) = ona_get_domain_record(array('name' => $options['name']));
531  if (!$domain['id']) {
532  // Determine the host and domain name portions of the pointsto option
533  // Find the domain name piece of $search
534  list($status, $rows, $domain) = ona_find_domain($options['name']);
535  printmsg("DEBUG => ona_find_domain({$options['name']}) returned: {$domain['fqdn']}.", 3);
536 
537  // Now find what the host part of $search is
538  $hostname = str_replace(".{$domain['fqdn']}", '', $options['name']);
539 
540  // Validate that the DNS name has only valid characters in it
541  $hostname = sanitize_hostname($hostname);
542  if (!$hostname) {
543  printmsg("ERROR => Invalid host name ({$options['name']})!", 3);
544  $self['error'] = "ERROR => Invalid host name ({$options['name']})!";
545  return(array(4, $self['error'] . "\n"));
546  }
547  // Debugging
548  printmsg("DEBUG => Using hostname: {$hostname}.{$domain['fqdn']}, Domain ID: {$domain['id']}", 3);
549  }
550 
551  // Determine the host and domain name portions of the pointsto option
552  // Find the domain name piece of $search
553  list($status, $rows, $pdomain) = ona_find_domain($options['pointsto']);
554  printmsg("DEBUG => ona_find_domain({$options['pointsto']}) returned: {$pdomain['fqdn']} for pointsto.", 3);
555 
556  // Now find what the host part of $search is
557  $phostname = str_replace(".{$pdomain['fqdn']}", '', $options['pointsto']);
558 
559  // Validate that the DNS name has only valid characters in it
560  $phostname = sanitize_hostname($phostname);
561  if (!$phostname) {
562  printmsg("ERROR => Invalid pointsto host name ({$options['pointsto']})!", 3);
563  $self['error'] = "ERROR => Invalid pointsto host name ({$options['pointsto']})!";
564  return(array(4, $self['error'] . "\n"));
565  }
566  // Debugging
567  printmsg("DEBUG => Using 'pointsto' hostname: {$phostname}.{$pdomain['fqdn']}, Domain ID: {$pdomain['id']}", 3);
568 
569  // Find the dns record that it will point to
570  list($status, $rows, $pointsto_record) = ona_get_dns_record(array('name' => $phostname, 'domain_id' => $pdomain['id'], 'type' => 'A','dns_view_id' => $add_viewid));
571  if ($status or !$rows) {
572  printmsg("ERROR => Unable to find DNS A record to point NS entry to!{$viewmsg}",3);
573  $self['error'] = "ERROR => Unable to find DNS A record to point NS entry to!{$viewmsg}";
574  return(array(5, $self['error'] . "\n"));
575  }
576 
577 
578  $add_name = $hostname;
579  $add_domainid = $domain['id'];
580  $add_interfaceid = $pointsto_record['interface_id'];
581  $add_dnsid = $pointsto_record['id'];
582  $add_mx_preference = $options['mx_preference'];
583 
584  // Dont print a dot unless hostname has a value
585  if ($hostname) $hostname = $hostname.'.';
586 
587  $info_msg = "{$hostname}{$domain['fqdn']} -> {$phostname}.{$pdomain['fqdn']}";
588 
589 
590  }
591 
592  // Process SRV record types
593  // SRV is a domain_id that points to another dns_id A record
594  // this will give you "_crap._tcp.mydomain.com IN SRV 0 2 80 server.somedomain.com"
595  else if ($options['type'] == 'SRV') {
596 
597  // If there is no srv_pri set then stop
598  if (!isset($options['srv_pri']) or ($options['srv_pri'] < 0 or $options['srv_pri'] > 65536)) {
599  printmsg("ERROR => You must provide an SRV priority value between 0-65535 when creating SRV records!", 3);
600  $self['error'] = "ERROR => You must provide an SRV priority value between 0-65535 when creating SRV records!";
601  return(array(4, $self['error'] . "\n"));
602  }
603 
604  // If there is no srv_weight set then stop
605  if (!isset($options['srv_weight']) or ($options['srv_weight'] < 0 or $options['srv_weight'] > 65536)) {
606  printmsg("ERROR => You must provide an SRV weight value between 0-65535 when creating SRV records!", 3);
607  $self['error'] = "ERROR => You must provide an SRV weight value between 0-65535 when creating SRV records!";
608  return(array(4, $self['error'] . "\n"));
609  }
610 
611  // If there is no srv_port set then stop
612  if (!isset($options['srv_port']) or ($options['srv_port'] < 0 or $options['srv_port'] > 65536)) {
613  printmsg("ERROR => You must provide an SRV port value between 0-65535 when creating SRV records!", 3);
614  $self['error'] = "ERROR => You must provide an SRV port value between 0-65535 when creating SRV records!";
615  return(array(4, $self['error'] . "\n"));
616  }
617 
618  // find the domain
619  list($status, $rows, $domain) = ona_find_domain($options['name'],0);
620  if (!$domain['id']) {
621  printmsg("ERROR => Invalid domain name ({$options['name']})!", 3);
622  $self['error'] = "ERROR => Invalid domain name ({$options['name']})!";
623  return(array(4, $self['error'] . "\n"));
624  }
625  // Determine the host and domain name portions of the pointsto option
626  // Find the domain name piece of $search
627  list($status, $rows, $pdomain) = ona_find_domain($options['pointsto']);
628  printmsg("DEBUG => ona_find_domain({$options['pointsto']}) returned: {$pdomain['fqdn']} for pointsto.", 3);
629 
630  // Now find what the host part of $search is
631  $phostname = str_replace(".{$pdomain['fqdn']}", '', $options['pointsto']);
632 
633  // Validate that the DNS name has only valid characters in it
634  $phostname = sanitize_hostname($phostname);
635  if (!$phostname) {
636  printmsg("ERROR => Invalid pointsto host name ({$options['pointsto']})!", 3);
637  $self['error'] = "ERROR => Invalid pointsto host name ({$options['pointsto']})!";
638  return(array(4, $self['error'] . "\n"));
639  }
640  // Debugging
641  printmsg("DEBUG => Using 'pointsto' hostname: {$phostname}.{$pdomain['fqdn']}, Domain ID: {$pdomain['id']}", 3);
642 
643  // Find the dns record that it will point to
644  list($status, $rows, $pointsto_record) = ona_get_dns_record(array('name' => $phostname, 'domain_id' => $pdomain['id'], 'type' => 'A','dns_view_id' => $add_viewid));
645  if ($status or !$rows) {
646  printmsg("ERROR => Unable to find DNS A record to point SRV entry to!{$viewmsg}",3);
647  $self['error'] = "ERROR => Unable to find DNS A record to point SRV entry to!{$viewmsg}";
648  return(array(5, $self['error'] . "\n"));
649  }
650 
651  // Validate that there are no records already with this domain and host
652  list($status, $rows, $record) = ona_get_dns_record(array('dns_id' => $pointsto_record['id'], 'name' => $hostname, 'domain_id' => $domain['id'],'type' => 'SRV','dns_view_id' => $add_viewid));
653  if ($rows or $status) {
654  printmsg("ERROR => Another DNS SRV record for {$hostname}.{$domain['fqdn']} pointing to {$options['pointsto']} already exists!{$viewmsg}",3);
655  $self['error'] = "ERROR => Another DNS SRV record for {$hostname}.{$domain['fqdn']} pointing to {$options['pointsto']} already exists!{$viewmsg}";
656  return(array(5, $self['error'] . "\n"));
657  }
658 
659 
660  $add_name = $hostname;
661  $add_domainid = $domain['id'];
662  $add_interfaceid = $pointsto_record['interface_id'];
663  $add_dnsid = $pointsto_record['id'];
664  $add_srv_pri = $options['srv_pri'];
665  $add_srv_weight = $options['srv_weight'];
666  $add_srv_port = $options['srv_port'];
667 
668  // Dont print a dot unless hostname has a value
669  if ($hostname) $hostname = $hostname.'.';
670 
671  $info_msg = "{$hostname}{$domain['fqdn']} -> {$phostname}.{$pdomain['fqdn']}";
672 
673  }
674 
675 
676  // Process TXT record types
677  else if ($options['type'] == 'TXT') {
678  // There are 3 types of txt record storage
679  // 1. txt that is associated to another A record. So when that A name gets changed so does this TXT
680  // 2. txt associated to just a domain. I.e. no hostname only a domain_id
681  // 3. txt that is arbitrary and not associated with another A record. has name, domain_id but no dns_id
682 
683  // Set interface id to zero by default, only needed if associating with an IP address
684  $add_interfaceid = 0;
685 
686  // Blank dnsid first.. normally it wont get set, unless it does match up to another record
687  $add_dnsid = 0;
688 
689  // lets try and determine the interface record using the name passed in. Only works if we get one record back
690  // this is all to help associate if it can so that when the A record is removed, so is this TXT record.
691  if ($hostname != '') {
692  list($status, $rows, $hostint) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'type' => 'A','dns_view_id' => $add_viewid));
693  if ($rows == 1) {
694  $add_interfaceid = $hostint['interface_id'];
695  $add_dnsid = $hostint['id'];
696  }
697  }
698 
699 
700  // If you want to associate a TXT record with a host you need to provide an IP.. otherwise it will just be associated with the domain its in.
701  // I might also check here that if there is no $hostname, then dont use the IP address value even if it is passed
702  if ($options['ip']) {
703  // find the IP interface record,
704  list($status, $rows, $interface) = ona_find_interface($options['ip']);
705  if (!$rows) {
706  printmsg("ERROR => dns_record_add() Unable to find IP interface: {$options['ip']}",3);
707  $self['error'] = "ERROR => dns_record_add() Unable to find IP interface: {$options['ip']}. TXT records must point to existing IP addresses. Please add an interface with this IP address first.";
708  return(array(4, $self['error'] . "\n"));
709  }
710 
711  $add_interfaceid = $interface['id'];
712  }
713 
714 
715 
716  // Validate that there are no TXT already with this domain and host
717  list($status, $rows, $record) = ona_get_dns_record(array('txt' => $options['txt'], 'name' => $hostname, 'domain_id' => $domain['id'],'type' => 'TXT','dns_view_id' => $add_viewid));
718  if ($rows or $status) {
719  printmsg("ERROR => Another DNS TXT record for {$options['name']} with that text value already exists!{$viewmsg}",3);
720  $self['error'] = "ERROR => Another DNS TXT record for {$options['name']} with that text value already exists!{$viewmsg}";
721  return(array(5, $self['error'] . "\n"));
722  }
723 
724 
725 
726  $add_name = $hostname;
727  $add_domainid = $domain['id'];
728 
729  $options['txt'] = str_replace('\\=','=',$options['txt']);
730  $options['txt'] = str_replace('\\&','&',$options['txt']);
731  $add_txt = $options['txt'];
732 
733  // Dont print a dot unless hostname has a value
734  if ($hostname) $hostname = $hostname.'.';
735 
736  $info_msg = "{$hostname}{$domain['fqdn']}";
737 
738  }
739  // If it is not a recognized record type, bail out!
740  else {
741  printmsg("ERROR => Invalid DNS record type: {$options['type']}!",3);
742  $self['error'] = "ERROR => Invalid DNS record type: {$options['type']}!";
743  return(array(5, $self['error'] . "\n"));
744  }
745 
746 
747 
748 
749 
750  //FIXME: MP, will this use its own dns_record_add permission? or use host_add?
751  // Check permissions
752  if (!auth('host_add')) {
753  $self['error'] = "Permission denied!";
754  printmsg($self['error'], 0);
755  return(array(10, $self['error'] . "\n"));
756  }
757 
758  // Get the next ID for the new dns record
759  $id = ona_get_next_id('dns');
760  if (!$id) {
761  $self['error'] = "ERROR => The ona_get_next_id('dns') call failed!";
762  printmsg($self['error'], 0);
763  return(array(7, $self['error'] . "\n"));
764  }
765  printmsg("DEBUG => ID for new dns record: $id", 3);
766 
767  // If a ttl was passed use it, otherwise use what was in the domain minimum
768  if ($options['ttl']) { $add_ttl = $options['ttl']; } else { $add_ttl = 0; }
769 
770  // There is an issue with escaping '=' and '&'. We need to avoid adding escape characters
771  $options['notes'] = str_replace('\\=','=',$options['notes']);
772  $options['notes'] = str_replace('\\&','&',$options['notes']);
773 
774  // Add the dns record
775  list($status, $rows) = db_insert_record(
776  $onadb,
777  'dns',
778  array(
779  'id' => $id,
780  'domain_id' => $add_domainid,
781  'interface_id' => $add_interfaceid,
782  'dns_id' => $add_dnsid,
783  'type' => $options['type'],
784  'ttl' => $add_ttl,
785  'name' => $add_name,
786  'mx_preference' => $add_mx_preference,
787  'txt' => $add_txt,
788  'srv_pri' => $add_srv_pri,
789  'srv_weight' => $add_srv_weight,
790  'srv_port' => $add_srv_port,
791  'ebegin' => $options['ebegin'],
792  'notes' => $options['notes'],
793  'dns_view_id' => $add_viewid
794  )
795  );
796  if ($status or !$rows) {
797  $self['error'] = "ERROR => dns_record_add() SQL Query failed adding dns record: " . $self['error'];
798  printmsg($self['error'], 1);
799  return(array(6, $self['error'] . "\n"));
800  }
801 
802  $text = '';
803 
804  // If it is an A record and they have specified to auto add the PTR record for it.
805  if ($options['addptr'] == 'Y' and $options['type'] == 'A') {
806  printmsg("DEBUG => Auto adding a PTR record for {$options['name']}.", 4);
807  // Run dns_record_add as a PTR type
808  list($status, $output) = run_module('dns_record_add', array('name' => $options['name'],'domain' => $domain['fqdn'],'ip' => $options['ip'],'ebegin' => $options['ebegin'],'type' => 'PTR','view' => $add_viewid));
809  if ($status) {
810  return(array($status, $output));
811  printmsg($output,3);
812  }
813  }
814 
815  // TRIGGER: Since we are adding a new record, lets mark the domain for rebuild on its servers
816  list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $add_domainid), array('rebuild_flag' => 1));
817  if ($status) {
818  $self['error'] = "ERROR => dns_record_add() Unable to update rebuild flags for domain.: {$self['error']}";
819  printmsg($self['error'],0);
820  return(array(7, $self['error'] . "\n"));
821  }
822 
823  // Else start an output message
824  $text .= "INFO => DNS {$options['type']} record ADDED: {$info_msg}";
825  printmsg($text,0);
826  $text .= "\n";
827 
828  // Return the success notice
829  return(array(0, $text));
830 }
831 
832 
833 
834 
835 
836 
837 
838 
839 
840 
841 
843 // Function: dns_record_modify (string $options='')
844 //
845 // Input Options:
846 // $options = key=value pairs of options for this function.
847 // multiple sets of key=value pairs should be separated
848 // by an "&" symbol.
849 //
850 // Output:
851 // Returns a two part list:
852 // 1. The exit status of the function. 0 on success, non-zero on
853 // error. All errors messages are stored in $self['error'].
854 // 2. A textual message for display on the console or web interface.
855 //
856 // Example: list($status, $result) = dns_record_modify('FIXME: blah blah blah');
858 function dns_record_modify($options="") {
859  global $conf, $self, $onadb;
860 
861  // Version - UPDATE on every edit!
862  $version = '1.13';
863 
864  printmsg("DEBUG => dns_record_modify({$options}) called", 3);
865 
866  // Parse incoming options string to an array
867  $options = parse_options($options);
868 
869  // Return the usage summary if we need to
870  if ($options['help'] or
871  (!$options['set_name'] and
872  !$options['set_ip'] and
873  !$options['set_ttl'] and
874  !$options['set_pointsto'] and
875  !$options['set_srv_pri'] and
876  !$options['set_srv_weight'] and
877  !$options['set_srv_port'] and
878  !$options['set_mx_preference'] and
879  !$options['set_notes'] and
880  !$options['set_view']
881  ) ) {
882  // NOTE: Help message lines should not exceed 80 characters for proper display on a console
883  $self['error'] = 'ERROR => Insufficient parameters';
884  return(array(1,
885 <<<EOM
886 
888 Modify a DNS record
889 
890  Synopsis: dns_record_modify [KEY=VALUE] ...
891 
892  Where:
893  name=NAME[.DOMAIN] or ID select dns record by name or ID
894 
895  Update:
896  set_name=NAME[.DOMAIN] change name and/or domain
897  set_ip=ADDRESS change IP the record points to
898  set_ttl=NUMBER change the TTL value, 0 = use domains TTL value
899  set_pointsto=NAME[.DOMAIN] change where a CNAME points
900  set_notes=NOTES change the textual notes
901  set_mx_preference=NUMBER change the MX record preference value
902  set_txt=STRING change the value of the TXT record
903  set_srv_pri=NUMBER change SRV Priority
904  set_srv_weight=NUMBER change SRV Weight
905  set_srv_port=NUMBER change SRV Port
906  set_ebegin change the begin date for record, 0 disables
907  set_domain=DOMAIN use if you need to explicitly set domain
908  set_view=STRING change DNS view identifier. AKA Split horizon.
909 
910  Note:
911  * You are not allowed to change the type of the DNS record, to do that
912  you must delete and re-add the record with the new type.
913  * DOMAIN will default to {$conf['dns_defaultdomain']} if not specified
914 \n
915 EOM
916  ));
917  }
918 
919 
920 /* Modify logic
921 
922 1. find the dns record we are editing
923 2. If it is an A, check that the name we are changing to does not already match an existing A/ip or CNAME
924 3. if its a CNAME, check that it is not the same as any other records.
925 
926 */
927 
928  // Check permissions
929  if (!auth('host_modify')) {
930  $self['error'] = "Permission denied!";
931  printmsg($self['error'], 0);
932  return(array(10, $self['error'] . "\n"));
933  }
934 
935 
936  // Sanitize addptr.. set it to Y if it is not set
937  $options['set_addptr'] = sanitize_YN($options['set_addptr'], 'Y');
938 
939  // clean up what is passed in
940  $options['set_ip'] = trim($options['set_ip']);
941  $options['set_pointsto'] = trim($options['set_pointsto']);
942  $options['set_name'] = trim($options['set_name']);
943  $options['set_domain'] = trim($options['set_domain']);
944  $options['set_txt'] = trim($options['set_txt']);
945  //$options['set_view'] = trim($options['set_view']);
946  //
947  // Find the dns record we're modifying
948  //
949 
950  // If the name we were passed has a leading . in it then remove the dot.
951  $options['set_name'] = preg_replace("/^\./", '', $options['set_name']);
952 
953  // Find the DNS record from $options['name']
954  list($status, $rows, $dns) = ona_find_dns_record($options['name']);
955  printmsg("DEBUG => dns_record_modify() DNS record: {$dns['fqdn']}", 3);
956  if ($rows > 1) {
957  printmsg("DEBUG => Found more than one DNS record for: {$options['name']}",3);
958  $self['error'] = "ERROR => Found more than one DNS record for: {$options['name']}";
959  return(array(2, $self['error'] . "\n"));
960  }
961 
962 
963  // If we didn't get a record then exit
964  if (!$dns['id']) {
965  printmsg("DEBUG => DNS record not found ({$options['name']})!",3);
966  $self['error'] = "ERROR => DNS record not found ({$options['name']})!";
967  return(array(4, $self['error'] . "\n"));
968  }
969 
970  // Set the current_name variable with the records current name
971  // Used by the add pointer function below since it runs before any names are updated
972  $current_name = $dns['fqdn'];
973  $current_int_id = $dns['interface_id'];
974  $check_dns_view_id = $dns['dns_view_id'];
975  $current_dns_view_id = $dns['dns_view_id'];
976 
977  // Set status on if we are chaning IP addresses
978  $changingint = 0;
979  $changingview = 0;
980 
981  // Set a message to display when using dns views
982  if ($conf['dns_views']) $viewmsg = ' Ensure you are selecting the proper DNS view for this record.';
983 
984  //
985  // Define the records we're updating
986  //
987 
988  // This variable will contain the updated info we'll insert into the DB
989  $SET = array();
990 
991  // Gather DNS view information
992  if (array_key_exists('set_view',$options)) {
993  if (is_numeric($options['set_view'])) {
994  $viewsearch = array('id' => $options['set_view']);
995  } else {
996  $viewsearch = array('name' => strtoupper($options['set_view']));
997  }
998  // find the IP interface record,
999  list($status, $rows, $dnsview) = ona_get_dns_view_record($viewsearch);
1000  if (!$rows) {
1001  printmsg("ERROR => dns_record_modify() Unable to find DNS view: {$options['set_view']}",3);
1002  $self['error'] = "ERROR => dns_record_modify() Unable to find DNS view: {$options['set_view']}.";
1003  return(array(4, $self['error'] . "\n"));
1004  }
1005 
1006  // If we have a new dns view, add it to the SET array and update the check view variable used in all the checks.
1007  if($dns['dns_view_id'] != $dnsview['id']) {
1008 
1009  // You can only change the view on parent records.. if this record has a dns_id, you must change the parent
1010  if ($dns['dns_id']) {
1011  printmsg("ERROR => You must change the parent DNS A record to the new view. This record will follow.",3);
1012  $self['error'] = "ERROR => You must change the parent DNS A record to the new view. This record will follow.";
1013  return(array(5, $self['error'] . "\n"));
1014  }
1015 
1016  $SET['dns_view_id'] = $dnsview['id'];
1017  $check_dns_view_id = $dnsview['id'];
1018  $changingview = 1;
1019  }
1020  }
1021 
1022  // Checking the IP setting first to estabilish if we are changing the IP so I can check the new combo of A/ip later
1023  if ($options['set_ip'] and ($options['set_ip'] != '0.0.0.0')) {
1024  // find the IP interface record, to ensure it is valid
1025  list($status, $rows, $interface) = ona_find_interface($options['set_ip']);
1026  if (!$rows) {
1027  printmsg("ERROR => dns_record_modify() Unable to find IP interface: {$options['set_ip']}",3);
1028  $self['error'] = "ERROR => dns_record_modify() Unable to find IP interface: {$options['set_ip']}\n";
1029  return(array(4, $self['error']));
1030  }
1031 
1032  // If they actually changed the ip address
1033  if ($interface['id'] != $dns['interface_id']) {
1034  // check for child records that would match our new values
1035  // I think they will always be just PTR records so I am only selecting that type for now?
1036  list($status, $rows, $dnschild) = ona_get_dns_record(array('dns_id' => $dns['id'], 'interface_id' => $interface['id'], 'type' => 'PTR'));
1037  if ($rows) {
1038  printmsg("ERROR => dns_record_modify() This change results in a duplicate child DNS record: PTR {$options['set_ip']}. Delete existing PTR record first.",3);
1039  $self['error'] = "<br>ERROR => dns_record_modify() This change results in a duplicate child DNS record: PTR {$options['set_ip']}.<br> Delete existing PTR record first.\n";
1040  return(array(4, $self['error']));
1041  }
1042 
1043  $changingint = 1;
1044  $SET['interface_id'] = $interface['id'];
1045 
1046  // get the info on the original interface
1047  list($status, $rows, $origint) = ona_get_interface_record(array('id' => $dns['interface_id']));
1048  }
1049  }
1050 
1051  // Set options['set_name']?
1052  // Validate that the DNS name has only valid characters in it
1053  if ($options['set_name']) {
1054 
1055  // If we are specifically passing in a domain, use its value. If we dont have a domain
1056  // then try to find it in the name that we are setting.
1057  if($options['set_domain']) {
1058  // Find the domain name piece of $search
1059  list($status, $rows, $domain) = ona_find_domain($options['set_domain'],0);
1060  } else {
1061  list($status, $rows, $domain) = ona_find_domain($options['set_name'],0);
1062  }
1063 
1064  // Find the domain name piece of $search
1065  if (!isset($domain['id'])) {
1066  printmsg("ERROR => Unable to determine domain name portion of ({$options['set_name']})!", 3);
1067  $self['error'] = "ERROR => Unable to determine domain name portion of ({$options['set_name']})!";
1068  return(array(3, $self['error'] . "\n"));
1069  }
1070  printmsg("DEBUG => ona_find_domain({$options['set_name']}) returned: {$domain['fqdn']} for new name.", 3);
1071 
1072  // Now find what the host part of $search is
1073  $hostname = str_replace(".{$domain['fqdn']}", '', $options['set_name']);
1074 
1075  // Validate that the DNS name has only valid characters in it
1076  $hostname = sanitize_hostname($hostname);
1077  if (!$hostname) {
1078  printmsg("DEBUG => Invalid host name ({$options['set_name']})!", 3);
1079  $self['error'] = "ERROR => Invalid host name ({$options['set_name']})!";
1080  return(array(4, $self['error'] . "\n"));
1081  }
1082 
1083  // If the hostname we came up with and the domain name are the same, then assume this is
1084  // meant to be a domain specific record, like A, MX, NS type records.
1085  if ($hostname == $domain['fqdn']) $hostname = '';
1086 
1087  // Debugging
1088  printmsg("DEBUG => Using hostname: {$hostname}.{$domain['fqdn']}, Domain ID: {$domain['id']}", 3);
1089 
1090 
1091  // if it is an a record and we are changing the name.. make sure there is not already an A with that name/ip combo
1092  if ($dns['type'] == 'A') {
1093  // If we are changing the interface id as determined above, check using that value
1094  if ($changingint) $dns['interface_id'] = $SET['interface_id'];
1095  list($status, $rows, $tmp) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'], 'interface_id' => $dns['interface_id'], 'type' => 'A','dns_view_id' => $check_dns_view_id));
1096  if ($rows) {
1097  if ($tmp['id'] != $dns['id'] or $rows > 1) {
1098  printmsg("ERROR => There is already an A record with that name and IP address!{$viewmsg}",3);
1099  $self['error'] = "ERROR => There is already an A record with that name and IP address!{$viewmsg}";
1100  return(array(5, $self['error'] . "\n"));
1101  }
1102  }
1103  }
1104 
1105  // make sure that name/pointsto combo doesnt already exist
1106  if ($dns['type'] == 'CNAME' or $dns['type'] == 'MX' or $dns['type'] == 'NS' or $dns['type'] == 'SRV') {
1107  list($status, $rows, $tmp) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'], 'dns_id' => $dns['dns_id'], 'type' => $dns['type'],'dns_view_id' => $check_dns_view_id));
1108  if ($rows) {
1109  if ($tmp['id'] != $dns['id'] or $rows > 1) {
1110  printmsg("ERROR => There is already a {$dns['type']} with that name pointing to that A record!{$viewmsg}",3);
1111  $self['error'] = "ERROR => There is already a {$dns['type']} with that name pointing to that A record!{$viewmsg}";
1112  return(array(6, $self['error'] . "\n"));
1113  }
1114  }
1115  }
1116 
1117  if ($dns['type'] == 'CNAME') {
1118  // if it is a CNAME, make sure the new name is not an A record name already
1119  list($status, $rows, $tmp) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'], 'type' => 'A','dns_view_id' => $check_dns_view_id));
1120  if ($status or $rows) {
1121  printmsg("ERROR => There is already an A record with that name!{$viewmsg}",3);
1122  $self['error'] = "ERROR => There is already an A record with that name!{$viewmsg}";
1123  return(array(7, $self['error'] . "\n"));
1124  }
1125  }
1126 
1127  // lets try and determine the interface record using the name passed in. Only works if we get one record back
1128  // this is all to help associate if it can so that when the A record is removed, so is this TXT record.
1129  if ($dns['type'] == 'TXT') {
1130  // if we are dealing with a change to a domain only.. then blank the interface id and dns_id
1131  if ($hostname == '') {
1132  $SET['interface_id'] = '';
1133  $SET['dns_id'] = '';
1134  } else {
1135  list($status, $rows, $hostint) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'type' => 'A','dns_view_id' => $check_dns_view_id));
1136  if ($rows == 1) {
1137  $SET['interface_id'] = $hostint['interface_id'];
1138  $SET['dns_id'] = $hostint['id'];
1139  $SET['name'] = $hostname;
1140  }
1141  }
1142  }
1143 
1144 
1145  // If you have actually changed the name from what it was, set the new variable $SET
1146  if($dns['name'] != $hostname)
1147  $SET['name'] = $hostname;
1148  if($dns['domain_id'] != $domain['id'])
1149  $SET['domain_id'] = $domain['id'];
1150  }
1151 
1152 
1153 
1154 
1155  // If we are modifying a pointsto option
1156  if (array_key_exists('set_pointsto', $options) and ($options['set_type'] == 'CNAME' or $options['set_type'] == 'MX' or $options['set_type'] == 'NS' or $options['set_type'] == 'SRV')) {
1157  // Determine the host and domain name portions of the pointsto option
1158  // Find the domain name piece of $search
1159  list($status, $rows, $pdomain) = ona_find_domain($options['set_pointsto']);
1160  printmsg("DEBUG => ona_find_domain({$options['set_pointsto']}) returned: {$domain['fqdn']} for pointsto.", 3);
1161 
1162  // Now find what the host part of $search is
1163  $phostname = str_replace(".{$pdomain['fqdn']}", '', $options['set_pointsto']);
1164 
1165  // Validate that the DNS name has only valid characters in it
1166  $phostname = sanitize_hostname($phostname);
1167  if (!$phostname) {
1168  printmsg("DEBUG => Invalid pointsto host name ({$options['set_pointsto']})!", 3);
1169  $self['error'] = "ERROR => Invalid pointsto host name ({$options['set_pointsto']})!";
1170  return(array(4, $self['error'] . "\n"));
1171  }
1172  // Debugging
1173  printmsg("DEBUG => Using 'pointsto' hostname: {$phostname}.{$pdomain['fqdn']}, Domain ID: {$pdomain['id']}", 3);
1174 
1175 
1176  // Find the dns record that it will point to
1177  list($status, $rows, $pointsto_record) = ona_get_dns_record(array('name' => $phostname, 'domain_id' => $pdomain['id'], 'type' => 'A','dns_view_id' => $check_dns_view_id));
1178  if ($status or !$rows) {
1179  printmsg("ERROR => Unable to find DNS A record to point {$options['set_type']} entry to!{$viewmsg}",3);
1180  $self['error'] = "ERROR => Unable to find DNS A record to point {$options['set_type']} entry to!{$viewmsg}";
1181  return(array(5, $self['error'] . "\n"));
1182  }
1183 
1184 
1185  // Validate that there are no entries already pointed to the new A record
1186  list($c_status, $c_rows, $c_record) = ona_get_dns_record(array('name' => $dns['name'], 'domain_id' => $dns['domain_id'], 'dns_id' => $pointsto_record['id'], 'type' => $options['set_type'],'dns_view_id' => $check_dns_view_id));
1187  if ($c_record['id'] != $dns['id'] and $c_rows) {
1188  printmsg("ERROR => Another DNS {$options['set_type']} record exists with the values you've selected!{$viewmsg}",3);
1189  $self['error'] = "ERROR => Another DNS {$options['set_type']} record exists with the values you've selected!{$viewmsg}";
1190  return(array(5, $self['error'] . "\n"));
1191  }
1192 
1193 
1194 
1195  $SET['dns_id'] = $pointsto_record['id'];
1196  $SET['interface_id'] = $pointsto_record['interface_id'];
1197 
1198 
1199  }
1200 
1201 
1202 
1203  // Set options['set_notes'] (it can be a null string!)
1204  if (array_key_exists('set_notes', $options)) {
1205  // There is an issue with escaping '=' and '&'. We need to avoid adding escape characters
1206  $options['set_notes'] = str_replace('\\=','=',$options['set_notes']);
1207  $options['set_notes'] = str_replace('\\&','&',$options['set_notes']);
1208  // If it changed...
1209  if ($dns['notes'] != $options['set_notes'])
1210  $SET['notes'] = $options['set_notes'];
1211  }
1212 
1213  // Check the date formatting etc
1214  if (isset($options['set_ebegin']) and $options['set_ebegin'] != $dns['ebegin']) {
1215  // format the time that was passed in for the database, leave it as 0 if they pass it as 0
1216  $options['set_ebegin'] = ($options['set_ebegin'] == '0' ? 0 : date('Y-m-j G:i:s',strtotime($options['set_ebegin'])) );
1217  // Force the SET variable if its ont 0 and the current record is not 0000:00:00 00:00
1218  if (!(($options['set_ebegin'] == '0') and ($dns['ebegin'] == '0000-00-00 00:00:00')))
1219  $SET['ebegin'] = $options['set_ebegin'];
1220  } else {
1221  // If I got no date, use right now as the date/time
1222  $options['set_ebegin'] = date('Y-m-j G:i:s');
1223  }
1224 
1225  // Add the remaining items to the $SET variable
1226  // if there is a ttl setting and it is not the same as the existing record
1227  if (array_key_exists('set_ttl', $options) and $options['set_ttl'] != $dns['ttl'])
1228  $SET['ttl'] = $options['set_ttl'];
1229 
1230  if (array_key_exists('set_mx_preference', $options) and $options['set_mx_preference'] != $dns['mx_preference'])
1231  $SET['mx_preference'] = $options['set_mx_preference'];
1232 
1233  if (array_key_exists('set_srv_pri', $options) and $options['set_srv_pri'] != $dns['srv_pri'])
1234  $SET['srv_pri'] = $options['set_srv_pri'];
1235  if (array_key_exists('set_srv_weight', $options) and $options['set_srv_weight'] != $dns['srv_weight'])
1236  $SET['srv_weight'] = $options['set_srv_weight'];
1237  if (array_key_exists('set_srv_port', $options) and $options['set_srv_port'] != $dns['srv_port'])
1238  $SET['srv_port'] = $options['set_srv_port'];
1239 
1240  if (array_key_exists('set_txt', $options)) {
1241  // There is an issue with escaping '=' and '&'. We need to avoid adding escape characters
1242  $options['set_txt'] = str_replace('\\=','=',$options['set_txt']);
1243  $options['set_txt'] = str_replace('\\&','&',$options['set_txt']);
1244  // If it changed...
1245  if ($dns['txt'] != $options['set_txt'])
1246  $SET['txt'] = $options['set_txt'];
1247  }
1248 
1249 
1250 
1251  // If it is an A record and they have specified to auto add the PTR record for it.
1252  if ($options['set_addptr'] == 'Y' and $options['set_type'] == 'A') {
1253  printmsg("DEBUG => Auto adding a PTR record for {$options['set_name']}.", 0);
1254  // Run dns_record_add as a PTR type
1255  // Always use the $current_name variable as the name might change during the update
1256  list($status, $output) = run_module('dns_record_add', array('name' => $current_name, 'domain' => $domain['fqdn'], 'ip' => $options['set_ip'],'ebegin' => $options['set_ebegin'],'type' => 'PTR','view' => $check_dns_view_id));
1257  if ($status)
1258  return(array($status, $output));
1259  printmsg($text);
1260  }
1261 
1262 
1263  // Get the dns record before updating (logging)
1264  $original_record = $dns;
1265 
1266 
1267  // Update the host record if necessary
1268  //if(count($SET) > 0 and $options['set_ebegin'] != $dns['ebegin']) {
1269  if(count($SET) > 0) {
1270 
1271  // Use the ebegin value set above
1272  $SET['ebegin'] = $options['set_ebegin'];
1273 
1274  // If we are changing the interface id as determined above, check using that value
1275  if ($changingint) {
1276  // If the interface id has changed, make sure any child records are updated first
1277  if ($SET['interface_id'] != $current_int_id) {
1278  printmsg("DEBUG = > dns_record_modify() Updating child interfaces to new interface.", 2);
1279  list($status, $rows) = db_update_record($onadb, 'dns', array('dns_id' => $dns['id'], 'interface_id' => $current_int_id), array('interface_id' => $SET['interface_id']));
1280  if ($status) {
1281  $self['error'] = "ERROR => dns_record_modify() SQL Query failed for dns record: " . $self['error'];
1282  printmsg($self['error'], 0);
1283  return(array(11, $self['error'] . "\n"));
1284  }
1285  // TODO: may need set rebuild flag on each of the domains related to these child records that just changed
1286  }
1287 
1288  // Check the PTR record has the proper domain still
1289  $ipflip = ip_mangle($interface['ip_addr_text'],'flip');
1290  $octets = explode(".",$ipflip);
1291  if (count($octets) > 4) {
1292  $arpa = '.ip6.arpa';
1293  $octcount = 31;
1294  } else {
1295  $arpa = '.in-addr.arpa';
1296  $octcount = 3;
1297  }
1298  // Find a pointer zone for this record to associate with.
1299  list($status, $prows, $ptrdomain) = ona_find_domain($ipflip.$arpa);
1300  list($status, $drrows, $dnsrec) = ona_get_dns_record(array('type' => 'PTR','interface_id' => $SET['interface_id'],'dns_view_id' => $check_dns_view_id));
1301 
1302  // TRIGGER: we made a change and need to update the CURRENT PTR record as well, only sets it if the ptrdomain changes
1303  list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $dnsrec['domain_id']), array('rebuild_flag' => 1));
1304  if ($status) {
1305  $self['error'] = "ERROR => dns_record_add() Unable to update rebuild flags for domain.: {$self['error']}";
1306  printmsg($self['error'],0);
1307  return(array(7, $self['error'] . "\n"));
1308  }
1309 
1310  // if we find any PTR records and the domain has chaned, make sure the child PTR records have the updated PTR domain info.
1311  if (isset($ptrdomain['id']) and $drrows>0 and $dnsrec['domain_id'] != $ptrdomain['id']) {
1312  list($status, $rows) = db_update_record($onadb, 'dns', array('id' => $dnsrec['id']), array('domain_id' => $ptrdomain['id'], 'ebegin' => $SET['ebegin']));
1313  if ($status or !$rows) {
1314  $self['error'] = "ERROR => dns_record_modify() Child PTR record domain update failed: " . $self['error'];
1315  printmsg($self['error'], 0);
1316  return(array(14, $self['error'] . "\n"));
1317  }
1318 
1319 
1320 
1321  // TRIGGER: we made a change and need to update the NEW PTR record as well, only sets it if the ptrdomain changes
1322  list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $ptrdomain['id']), array('rebuild_flag' => 1));
1323  if ($status) {
1324  $self['error'] = "ERROR => dns_record_add() Unable to update rebuild flags for domain.: {$self['error']}";
1325  printmsg($self['error'],0);
1326  return(array(7, $self['error'] . "\n"));
1327  }
1328  }
1329  }
1330 
1331  // If we are changing the view, we must change all other DNS records that point to this one to the same view.
1332  if ($changingview) {
1333  if ($SET['dns_view_id'] != $current_dns_view_id) {
1334  printmsg("DEBUG = > dns_record_modify() Updating child DNS records to new dns view.", 2);
1335  list($status, $rows) = db_update_record($onadb, 'dns', array('dns_id' => $dns['id']), array('dns_view_id' => $SET['dns_view_id']));
1336  if ($status) {
1337  $self['error'] = "ERROR => dns_record_modify() SQL Query failed for dns record child view updates: " . $self['error'];
1338  printmsg($self['error'], 0);
1339  return(array(11, $self['error'] . "\n"));
1340  }
1341  }
1342 
1343  // TRIGGER: yep I probably need one here FIXME
1344 
1345  }
1346 
1347 
1348  // Make sure we us A type for both A and AAAA
1349  if ($SET['type'] == 'AAAA') $SET['type'] = 'A';
1350 
1351  // Change the actual DNS record
1352  list($status, $rows) = db_update_record($onadb, 'dns', array('id' => $dns['id']), $SET);
1353  if ($status or !$rows) {
1354  $self['error'] = "ERROR => dns_record_modify() SQL Query failed for dns record: " . $self['error'];
1355  printmsg($self['error'], 0);
1356  return(array(12, $self['error'] . "\n"));
1357  }
1358 
1359  // TRIGGER: we made a change, lets mark the domain for rebuild on its servers
1360  list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $dns['domain_id']), array('rebuild_flag' => 1));
1361  if ($status) {
1362  $self['error'] = "ERROR => dns_record_add() Unable to update rebuild flags for domain.: {$self['error']}";
1363  printmsg($self['error'],0);
1364  return(array(7, $self['error'] . "\n"));
1365  }
1366 
1367  // TRIGGER: If we are changing domains, lets flag the new domain as well, lets mark the domain for rebuild on its servers
1368  if($SET['domain_id']) {
1369  list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $SET['domain_id']), array('rebuild_flag' => 1));
1370  if ($status) {
1371  $self['error'] = "ERROR => dns_record_add() Unable to update rebuild flags for domain.: {$self['error']}";
1372  printmsg($self['error'],0);
1373  return(array(7, $self['error'] . "\n"));
1374  }
1375  }
1376 
1377 
1378  }
1379 
1380  // Get the host record after updating (logging)
1381  list($status, $rows, $new_record) = ona_get_dns_record(array('id' => $dns['id']));
1382 
1383  // Return the success notice
1384  $self['error'] = "INFO => DNS record UPDATED:{$dns['id']}: {$new_record['fqdn']}";
1385 
1386  $log_msg = "INFO => DNS record UPDATED:{$dns['id']}: ";
1387  $more='';
1388  foreach(array_keys($original_record) as $key) {
1389  if($original_record[$key] != $new_record[$key]) {
1390  $log_msg .= $more . $key . "[" .$original_record[$key] . "=>" . $new_record[$key] . "]";
1391  $more= "; ";
1392  }
1393  }
1394 
1395  // only print to logfile if a change has been made to the record
1396  if($more != '') printmsg($log_msg, 0);
1397 
1398  return(array(0, $self['error'] . "\n"));
1399 }
1400 
1401 
1402 
1403 
1404 
1405 
1406 
1407 
1408 
1409 
1411 // Function: dns_record_del (string $options='')
1412 //
1413 // Input Options:
1414 // $options = key=value pairs of options for this function.
1415 // multiple sets of key=value pairs should be separated
1416 // by an "&" symbol.
1417 //
1418 // Output:
1419 // Returns a two part list:
1420 // 1. The exit status of the function. 0 on success, non-zero on
1421 // error. All errors messages are stored in $self['error'].
1422 // 2. A textual message for display on the console or web interface.
1423 //
1424 // Example: list($status, $result) = dns_record_del('name=test');
1426 function dns_record_del($options="") {
1427  global $conf, $self, $onadb;
1428  printmsg("DEBUG => dns_record_del({$options}) called", 3);
1429 
1430  // Version - UPDATE on every edit!
1431  $version = '1.03';
1432 
1433  // Parse incoming options string to an array
1434  $options = parse_options($options);
1435 
1436  // Sanitize options[commit] (default is no)
1437  $options['commit'] = sanitize_YN($options['commit'], 'N');
1438 
1439  // Return the usage summary if we need to
1440  if ($options['help'] or !$options['name']) {
1441  // NOTE: Help message lines should not exceed 80 characters for proper display on a console
1442  $self['error'] = 'ERROR => Insufficient parameters';
1443  return(array(1,
1444 <<<EOM
1445 
1447 Deletes a DNS record from the database
1448 
1449  Synopsis: dns_record_del [KEY=VALUE] ...
1450 
1451  Required:
1452  name=NAME[.DOMAIN] or ID hostname or ID of the record to delete
1453  type=TYPE record type (A,CNAME,PTR...)
1454 
1455  Optional:
1456  ip=ADDRESS ip address (numeric or dotted)
1457  commit=[yes|no] commit db transaction (no)
1458 
1459 \n
1460 EOM
1461  ));
1462  }
1463 /*
1464 thoughts on the flow of things:
1465 
1466 A records:
1467  remove any CNAMES using this A record
1468  remove any PTR records using this A record
1469  test that it is not a primary_dns_id, if it is, it must be reassigned
1470 
1471 
1472 should make a find_dns_record(s) function. a find by host option would be good.
1473 
1474 need to do a better delete of DNS records when deleting a host.. currently its a problem.
1475 
1476 MP: TODO: this delete will not handle DNS views unless you use the ID of the record to delete. add a view option at some point.
1477 
1478 */
1479 
1480  // If the name we were passed has a leading . in it then remove the dot.
1481  $options['name'] = preg_replace("/^\./", '', $options['name']);
1482 
1483  // FIXME: MP Fix this to use a find_dns_record function ID only for now
1484  // Find the DNS record from $options['name']
1485  list($status, $rows, $dns) = ona_find_dns_record($options['name'], $options['type']);
1486  printmsg("DEBUG => dns_record_del() DNS record: {$options['name']}", 3);
1487  if (!$dns['id']) {
1488  printmsg("DEBUG => Unknown DNS record: {$options['name']} ({$options['type']})",3);
1489  $self['error'] = "ERROR => Unknown DNS record: {$options['name']} ({$options['type']})";
1490  return(array(2, $self['error'] . "\n"));
1491  }
1492 
1493 
1494  // Check permissions
1495  if (!auth('host_del') or !authlvl($host['LVL'])) {
1496  $self['error'] = "Permission denied!";
1497  printmsg($self['error'], 0);
1498  return(array(10, $self['error'] . "\n"));
1499  }
1500 
1501  // If "commit" is yes, delete the host
1502  if ($options['commit'] == 'Y') {
1503  $text = "";
1504  $add_to_error = "";
1505 
1506  // SUMMARY:
1507  // Display any associated PTR records for an A record
1508  // Display any associated CNAMEs for an A record
1509 
1510 
1511  // Test if it is used as a primary_dns_id unless it is the host_del module calling
1512  if (!isset($options['delete_by_module'])) {
1513  list($status, $rows, $srecord) = db_get_record($onadb, 'hosts', array('primary_dns_id' => $dns['id']));
1514  if ($rows) {
1515  $self['error'] = "ERROR => dns_record_del() The DNS record, {$dns['name']}.{$dns['domain_fqdn']}[{$dns['id']}], is a primary A record for a host! You can not delete it until you associate a new primary record, or delete the host.";
1516  printmsg($self['error'],0);
1517  return(array(5, $self['error'] . "\n"));
1518  }
1519  }
1520 
1521 
1522  // Delete related Points to records
1523  // get list for logging
1524  list($status, $rows, $records) = db_get_records($onadb, 'dns', array('dns_id' => $dns['id']));
1525  // do the delete
1526  list($status, $rows) = db_delete_records($onadb, 'dns', array('dns_id' => $dns['id']));
1527  if ($status) {
1528  $self['error'] = "ERROR => dns_record_del() Child record delete SQL Query failed: {$self['error']}";
1529  printmsg($self['error'],0);
1530  return(array(5, $self['error'] . "\n"));
1531  }
1532  if ($rows) {
1533  // log deletions
1534  // FIXME: do better logging here
1535  printmsg("INFO => {$rows} child DNS record(s) DELETED from {$dns['fqdn']}",0);
1536  $add_to_error .= "INFO => {$rows} child record(s) DELETED from {$dns['fqdn']}\n";
1537  }
1538 
1539  // TRIGGER: flag the domains for rebuild
1540  foreach($records as $record) {
1541  list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $record['domain_id']), array('rebuild_flag' => 1));
1542  if ($status) {
1543  $self['error'] = "ERROR => dns_record_del() Unable to update rebuild flags for domain.: {$self['error']}";
1544  printmsg($self['error'],0);
1545  return(array(7, $self['error'] . "\n"));
1546  }
1547  }
1548 
1549 
1550  // Delete the DNS record
1551  list($status, $rows) = db_delete_records($onadb, 'dns', array('id' => $dns['id']));
1552  if ($status) {
1553  $self['error'] = "ERROR => dns_record_del() DNS record delete SQL Query failed: {$self['error']}";
1554  printmsg($self['error'],0);
1555  return(array(5, $add_to_error . $self['error'] . "\n"));
1556  }
1557 
1558  // TRIGGER: flag the current dnsrecords domain for rebuild
1559  list($status, $rows) = db_update_record($onadb, 'dns_server_domains', array('domain_id' => $dns['domain_id']), array('rebuild_flag' => 1));
1560  if ($status) {
1561  $self['error'] = "ERROR => dns_record_del() Unable to update rebuild flags for domain.: {$self['error']}";
1562  printmsg($self['error'],0);
1563  return(array(7, $self['error'] . "\n"));
1564  }
1565 
1566  // FIXME: if it is a NS or something display a proper FQDN message here
1567  // Display proper PTR information
1568  if ($dns['type'] == 'PTR') {
1569  list($status, $rows, $pointsto) = ona_get_dns_record(array('id' => $dns['dns_id']), '');
1570  list($status, $rows, $ptrint) = ona_get_interface_record(array('id' => $dns['interface_id']), '');
1571 
1572  $ipflip = ip_mangle($ptrint['ip_addr'],'flip');
1573  $octets = explode(".",$ipflip);
1574  if (count($octets) > 4) {
1575  $arpa = '.ip6.arpa';
1576  $octcount = 31;
1577  } else {
1578  $arpa = '.in-addr.arpa';
1579  $octcount = 3;
1580  }
1581  $dns['fqdn'] = "{$ipflip}{$arpa} -> {$pointsto['fqdn']}";
1582  }
1583 
1584  // Return the success notice
1585  $self['error'] = "INFO => DNS {$dns['type']} record DELETED: {$dns['fqdn']}";
1586  printmsg($self['error'], 0);
1587  return(array(0, $add_to_error . $self['error'] . "\n"));
1588  }
1589 
1590 
1591  //
1592  // We are just displaying records that would have been deleted
1593  //
1594 
1595  // SUMMARY:
1596  // Display any associated PTR records for an A record
1597  // Display any associated CNAMEs for an A record
1598 
1599 
1600  // Otherwise just display the host record for the host we would have deleted
1601  $text = "Record(s) NOT DELETED (see \"commit\" option)\n" .
1602  "Displaying record(s) that would have been deleted:\n";
1603 
1604  // Test if it is used as a primary_dns_id
1605  list($status, $rows, $srecord) = db_get_record($onadb, 'hosts', array('primary_dns_id' => $dns['id']));
1606  if ($rows) {
1607  $text .= "\nWARNING! This DNS record is a primary A record for a host\n";
1608  }
1609  // Display the complete dns record
1610  list($status, $tmp) = dns_record_display("name={$dns['id']}&verbose=N");
1611  $text .= "\n" . $tmp;
1612 
1613  // Display associated Child records
1614  list($status, $rows, $records) = db_get_records($onadb, 'dns', array('dns_id' => $dns['id']));
1615  if ($rows) $text .= "\nASSOCIATED POINTS-TO RECORDS ({$rows}):\n";
1616  foreach ($records as $record) {
1617  if ($record['type'] == 'NS') $record['name'] = '';
1618  // FIXME:I could fix this but I'm lazy
1619  if ($record['type'] == 'PTR') $record['name'] = '??';
1620  list($status, $rows, $domain) = ona_get_domain_record(array('id' => $record['domain_id']), '');
1621  $text .= " {$record['type']}: {$record['name']}.{$domain['fqdn']} -> {$dns['fqdn']}\n";
1622  }
1623 
1624 
1625 
1626  return(array(7, $text));
1627 }
1628 
1629 
1630 
1631 
1632 
1633 
1634 
1635 
1636 
1637 
1638 
1640 // Function: dns_record_display (string $options='')
1641 //
1642 // $options = key=value pairs of options for this function.
1643 // multiple sets of key=value pairs should be separated
1644 // by an "&" symbol.
1645 //
1646 // Input Options:
1647 // name=HOSTNAME[.DOMAIN] or ID
1648 //
1649 // Output:
1650 // Returns a two part list:
1651 // 1. The exit status of the function. 0 on success, non-zero on
1652 // error. All errors messages are stored in $self['error'].
1653 // 2. A textual message for display on the console or web interface.
1654 //
1655 // Example: list($status, $result) = dns_record_display('name=test');
1657 function dns_record_display($options="") {
1658  global $conf, $self, $onadb;
1659 
1660  // Version - UPDATE on every edit!
1661  $version = '1.00';
1662 
1663  printmsg("DEBUG => dns_record_display({$options}) called", 3);
1664 
1665  // Parse incoming options string to an array
1666  $options = parse_options($options);
1667 
1668  // Sanitize options[verbose] (default is yes)
1669  $options['verbose'] = sanitize_YN($options['verbose'], 'Y');
1670 
1671  // Return the usage summary if we need to
1672  if ($options['help'] or !$options['name'] ) {
1673  // NOTE: Help message lines should not exceed 80 characters for proper display on a console
1674  $self['error'] = 'ERROR => Insufficient parameters';
1675  return(array(1,
1676 <<<EOM
1677 
1679 Displays a DNS record from the database
1680 
1681  Synopsis: dns_record_display [KEY=VALUE] ...
1682 
1683  Required:
1684  name=NAME[.DOMAIN] or ID hostname or ID of the dns record to display
1685 
1686  Optional:
1687  verbose=[yes|no] display additional info (yes)
1688 
1689 \n
1690 EOM
1691 
1692  ));
1693  }
1694 
1695 
1696  // If the name we were passed has a leading . in it then remove the dot.
1697  $options['name'] = preg_replace("/^\./", '', $options['name']);
1698 
1699  // Find the DNS record from $options['name']
1700  list($status, $rows, $record) = ona_find_dns_record($options['name']);
1701  printmsg("DEBUG => dns_record_del() DNS record: {$record['name']}", 3);
1702  if (!$record['id']) {
1703  printmsg("DEBUG => Unknown DNS record: {$options['name']}",3);
1704  $self['error'] = "ERROR => Unknown DNS record: {$options['name']}";
1705  return(array(2, $self['error'] . "\n"));
1706  }
1707 
1708  // Build text to return
1709  $text = "DNS {$record['type']} RECORD ({$record['fqdn']})\n";
1711 
1712  // If 'verbose' is enabled, grab some additional info to display
1713  if ($options['verbose'] == 'Y') {
1714 
1715  // PTR record(s)
1716  $i = 0;
1717  do {
1718  list($status, $rows, $ptr) = ona_get_dns_record(array('dns_id' => $record['id'],'type' => 'PTR'));
1719  if ($rows == 0) { break; }
1720  $i++;
1721  $text .= "\nASSOCIATED PTR RECORD ({$i} of {$rows})\n";
1722  $text .= format_array($ptr);
1723  } while ($i < $rows);
1724 
1725  // CNAME record(s)
1726  $i = 0;
1727  do {
1728  list($status, $rows, $cname) = ona_get_dns_record(array('dns_id' => $record['id'],'type' => 'CNAME'));
1729  if ($rows == 0) { break; }
1730  $i++;
1731  $text .= "\nASSOCIATED CNAME RECORD ({$i} of {$rows})\n";
1732  $text .= format_array($cname);
1733  } while ($i < $rows);
1734 
1735 
1736 // FIXME: MP display other types of records like NS,MX,SRV etc etc, also support dns views better
1737 
1738 
1739  }
1740 
1741  // Return the success notice
1742  return(array(0, $text));
1743 
1744 }
1745 
1746 
1747 
1748 
1749 
1750 
1751 
1752 
1753 
1754 
1755 
1756 
1757 // DON'T put whitespace at the beginning or end of this file!!!
1758 ?>
db_insert_record
db_insert_record($dbh=0, $table="", $insert="")
Definition: functions_db.inc.php:375
sanitize_YN
sanitize_YN($string="", $default="Y")
Definition: functions_general.inc.php:1637
ona_get_next_id
ona_get_next_id($tablename)
Definition: functions_db.inc.php:1369
ona_find_domain
ona_find_domain($fqdn="", $returndefault=0)
Definition: functions_db.inc.php:1609
ip_mangle
ip_mangle($ip="", $format="default")
Definition: functions_general.inc.php:308
ona_get_interface_record
ona_get_interface_record($array='', $order='')
Definition: functions_db.inc.php:1126
$record
$record['display_name']
Definition: app_advanced_search.inc.php:12
db_get_records
db_get_records($dbh=0, $table="", $where="", $order="", $rows=-1, $offset=-1)
Definition: functions_db.inc.php:891
$status
$status
Definition: install.php:12
$onadb
global $onadb
Definition: 2-to-3.php:15
db_delete_records
db_delete_records($dbh=0, $table="", $where="")
Definition: functions_db.inc.php:582
ona_get_dns_view_record
ona_get_dns_view_record($array='', $order='')
Definition: functions_db.inc.php:1156
dns_record_modify
dns_record_modify($options="")
Definition: dns_record.inc.php:858
dns_record_add
dns_record_add($options="")
Definition: dns_record.inc.php:24
printmsg
if(6<=$conf['debug']) printmsg($msg="", $debugLevel=0)
Definition: functions_general.inc.php:48
format_array
format_array($array=array())
Definition: functions_general.inc.php:1745
ona_find_interface
ona_find_interface($search="")
Definition: functions_db.inc.php:1910
authlvl
authlvl($level)
Definition: functions_general.inc.php:1349
$host
$host
Definition: collate-convert.php:19
db_update_record
db_update_record($dbh=0, $table="", $where="", $insert="")
Definition: functions_db.inc.php:474
run_module
run_module($module='', $options='', $transaction=1)
Definition: functions_general.inc.php:1468
sanitize_hostname
sanitize_hostname($string="")
Definition: functions_general.inc.php:900
$conf
global $conf
Definition: 2-to-3.php:15
dns_record_display
dns_record_display($options="")
Definition: dns_record.inc.php:1657
ona_get_domain_record
ona_get_domain_record($array='', $order='')
Definition: functions_db.inc.php:1134
$output
$output
Definition: dcm.php:16
ona_find_dns_record
ona_find_dns_record($search="", $type='', $int_id=0)
Definition: functions_db.inc.php:1703
dns_record_del
dns_record_del($options="")
Definition: dns_record.inc.php:1426
$text
$text
Definition: install.php:11
$self
global $self
Definition: 2-to-3.php:15
db_get_record
db_get_record($dbh=0, $table="", $where="", $order="")
Definition: functions_db.inc.php:708
auth
auth($resource, $msg_level=1)
Definition: functions_general.inc.php:1330
parse_options
parse_options($options="")
Definition: functions_general.inc.php:1579
$version
$version
Definition: main.inc.php:22
ona_get_dns_record
ona_get_dns_record($array='', $order='')
Definition: functions_db.inc.php:1142