⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 records-lib.pl

📁 BIND 9 dynamic DNS webmin module. This module supports both static and dynamic zones, and IPv4 and I
💻 PL
📖 第 1 页 / 共 4 页
字号:
			if ($1 eq 'in-addr') {				$name = &compress_ip(&arpa_to_ip($name));			}			else {				$name = &ip6arpa_to_net($name);				unless (&is_ip6_subnet($orig_name)) {					$name = &compress_ip6($name);				}			}		}		elsif ($_[0] <= 0) {			if ($name eq $origin) {				$name = '@' unless ($_[3]);			}			elsif ($name =~ /^([\d.:]+)$origin$/) {				#				# Removing the origin in this case would leave				# a name which looks like an IP address. As				# such we let the FQDN be displayed to avoid				# any confusion.				#			}			elsif ($origin eq '.') {				$name =~ s/\.$//o;			}			else {				$name =~ s/\.$origin$//;			}		}	}	return $name;}## This subroutine checks an IPv6 address to see if it is actually a subnet.# We do this by counting the number of colons (:) in the address. If a :: is# seen then we cannot determine if this is a subnet, because we do not know how# many zeros should replace the ::. We also cater for IPv6 reverse addresses.## is_ip6_subnet(IPv6_address)#sub is_ip6_subnet {	my $addr = lc($_[0]);	return 0 unless ($addr);	if ($addr =~ /^(.*\.)ip6\.arpa\.?$/o) {		$addr = $1;		return ($addr !~ /^([\da-f*]\.){32}$/o);	}	return 0 if ($addr =~ /::/o || $addr !~ /^[\da-f:*]+$/o);	return (($addr =~ s/:/:/go) != 7);}## This subroutine is used to check the SOA serial number. It will return# one of two values: a negative number to indicate an error, or a positive# number to indicate the next serial number to use. A value of one is used# to indicate that whatever next serial number the name server uses is# okay. For example, dynamic zones may have their serial number sequentially# incremented automatically.## Returns = 1 if okay to proceed - no serial number needed,#         > 1 serial number is set to what number to use,#	  = -1 serial number unobtainable#	  = -2 invalid serial number format#	  = -3 abort updates## check_soa_serial(dynamic_data_ref, zone, @records, soa_ref)#sub check_soa_serial {	my $dynamic_zone = my $serial = my $nn = 0;	my $sec = my $min = my $hour = my $day = my $mon = my $year = 0;	my $rec = my $today = my $serial_date = my $future = my $soa_ref = '';	my $abort_updates = -3;	$dynamic_zone = $_[0]->[1];	if ($dynamic_zone) {		$serial = $_[0]->[3];		return -1 if ($serial < 0);	# Serial number unobtainable.	}	else {		$serial = &get_soa_rec($_[1], $_[2], $soa_ref);		if ($serial) {			($serial) = ($serial =~ /\sSOA\s+\S+\s+\S+\s+(\d+)/io);		}		if ($serial) {			$_[3] = $soa_ref if (defined($_[3]));		}		else {			return -1;		# Serial number unobtainable.		}	}	#	# No checks needed if we are using a simple sequential number for the	# serial number, or we have requested no serial number updates for	# static zones.	#	unless ($config{'soa_date_style'}) {		return ($dynamic_zone) ? 1 : ++$serial;	}	return 1 if (! $config{'updserial_on'} && ! $dynamic_zone);	if ($serial =~ /^(\d{8})(\d\d)$/o) {		$serial_date = $1;		$nn = $2;	}	else {		return -2;	}	$today = &today();	# Get todays date.	#	# If the serial number date is earlier than today, regardless of the	# current number, then we have no problem :-) Just start afresh with	# todays date.	#	if ($serial_date < $today) {		return $today . '00';	}	#	# If the serial number date is today and the number is less than 99,	# then again we have no problem. Just use the next number.	#	if ($serial_date == $today && $nn < 99) {		return ($dynamic_zone) ? 1 : ++$serial;	}	#	# At this point we have two scenarios left:	#	# 1) The serial number date is in the future	# 2) The date is todays date but the number equals 99	#	# We handle both cases the same by rechecking the config options,	# they may have changed since last time, and acting accordingly.	#	if ($config{'serial_exceed99'} == 0) {		return $abort_updates;	}	elsif ($config{'serial_exceed99'} == 1) {    # Just use the next number.		return ($dynamic_zone) ? 1 : ++$serial;	}	#	# We want to use a future date. Calculate one if necessary and	# return the new serial number. We must, however, check that the	# current value is a valid date, because we may have changed from	# using sequential numbers to the date format.	#	unless (&valid_date($serial)) {		$nn = 500;	# Force a new date to be calculated.	}	if ($nn < 99) {		# This can only be for the future date scenario.		return ($dynamic_zone) ? 1 : ++$serial;	}	#	# For dynamic zones we must be careful with future dates. It is	# possible for the date to become invalid when the serial number is	# automatically incremented. For example, 2003043099 would become	# 2003043100. To resolve this we record the new future date when	# we check if we can increment the serial number (see save_record).	# We then pass that to bump_soa_record to reset the serial number	# after the name server has auto-incremented it.	#	$future = &calc_secs($serial_date);	$future += 86400 unless ($nn == 500);	# Add one day.	($sec, $min, $hour, $day, $mon, $year) = localtime($future);	$future = sprintf('%4.4d%2.2d%2.2d00', $year + 1900, $mon + 1, $day);	return $future;}## Calculate the number of seconds since the epoch.## calc_secs(YYYYMMDD)#sub calc_secs {	use integer;	my $secs = my $day = my $mon = my $year = my $leap_days = my $y = 0;	my @days_in_mon = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);	($year, $mon, $day) = ($_[0] =~ /^(\d{4})(\d\d)(\d\d)$/o);	$mon -= 2;	# Subtract 2 because the array starts at 0 and we only			# need the previous months - excluding this one.	if ($mon >= 0) {	# Add up all the days in the previous months.		foreach (0 .. $mon) {			$day += $days_in_mon[$_];		}	}	$y = $year - 1972;	$leap_days = int($y / 4);	#	# If we are in a leap year and in January or February, then we must	# remove one of the leap days. We will have calculated to include the	# leap day for this year, but we haven't reached that leap day yet!	#	$leap_days-- if ((($y % 4) == 0) && $mon < 1);	$year -= 1970;				# Calculate the number of years.	$day += ($year * 365) + $leap_days;	# Add up all the days.	$secs = $day * 86400;			# Convert to seconds.	return $secs;}## Get a zone's SOA record. If the 'records' argument is present then we have# already read the zone file for the records so we may as well use that rather# than reading the zone again. If 'ref_rec' is present then it means we want the# reference to the SOA record returned to the caller.## get_soa_rec(zone, @records, rec_ref)#sub get_soa_rec {	my $n = my $v = 0;	my $zone = my $zone_conf = my $output = '';	my $file = my $rec = my $rec_ref = '';	my @recs = ();	$zone_conf = $_[0];	$zone = lc($zone_conf->{'value'});	$zone .= '.' unless ($zone =~ /\.$/o);	$rec_ref = undef;	if (defined($_[1])) {		@recs = @{ $_[1] };	}	else {		$file = &find_value('file', $zone_conf->{'members'});		#		# We might as well treat this as a stub zone since we only		# want the SOA record.		#		@recs = &get_zone($zone_conf, $file, $zone, undef, 'stub');	}	for ($n = 0; $n < @recs; $n++) {		$rec = $recs[$n];		if ($rec->{'type'} eq 'SOA') {			$output = $rec->{'fqdn'} . ' ';			$output .= ($rec->{'ttl'}) ? $rec->{'ttl'} : 0;			$output .= ' IN SOA';			for ($v = 0; $rec->{'values'}->[$v]; $v++) {				$output .= ' ' . $rec->{'values'}->[$v];			}			$rec_ref = $rec;			last;		}	}	$_[2] = $rec_ref if (defined($_[2]));	return ($output =~/\sSOA\s+\S+\s+\S+\s+\d/io) ? $output : '';}## check_serial_number(dynamic_zone_ref, zone, @records, soa_ref)#sub check_serial_number {	my $serial_okay = 0;	my $err = '';	$serial_okay = &check_soa_serial($_[0], $_[1], $_[2], $_[3]);	if ($serial_okay < 0) {		$err = ($serial_okay == -1) ? 'soa_serial_unob'					    : ($serial_okay == -2)						? 'soa_serial_invalid'						: 'soa_serial_max';		&terror($err);	}	return $serial_okay;}## valid_date(date_string - YYYYMMDDnn)#sub valid_date {	my $year = my $month = my $day = 0;	my $date_str = '';	my @days_in_mon = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);	$date_str = $_[0];	return 0 unless ($date_str);	if ($date_str =~ /^(\d{4})(\d\d)(\d\d)\d\d$/o) {		$year = $1; $month = $2; $day = $3;	}	else {		return 0;	}	return 0 if ($year < 1970);	#	# If we specify that the next number is to be used then just return.	# The year must still be valid but the days and months may not be.	#	return 1 if ($config{'serial_exceed99'} == 1);	return 0 if ($month < 1 || $month > 12);	#	# Calculate if it is a leap year to see if we need to adjust the	# number of days in February.	#	if (($year % 4) == 0 && (($year % 100) != 0 || ($year % 400) == 0)) {		$days_in_mon[1]++;	}	return 0 if ($day < 1 || $day > $days_in_mon[$month - 1]);	return 1;}## check_update_err(error_string)#sub check_update_err {	my $error = my $status = '';	$error = $_[0];	return unless ($error);	if ($error =~ /\sopcode: UPDATE, status: ([^,]+),/io) {		$status = $1;		if ($status eq 'NXRRSET') {			&terror('update_no_rec');		}		elsif ($status eq 'SERVFAIL') {			&terror('update_servfail');		}		elsif ($status eq 'NOTAUTH') {			&terror('updates_no_allow');		}	}	&error("<pre>$error</pre>");}## See if the given record type, with the specified token number, needs the# value converting to/from FQDN. For example, MX records have as their values:##	the preference/priority, as token 0, is not to be converted;#	the mail server, as token 1, which may be converted.## The returned value will be >=0 in the case of record values which may be# converted. The number indicates its token count. A value of -1 is returned# in all other instances.## convert_value(record_type, token_count)#sub convert_value {	my $token_count = 0;	my $type = '';	$type = $_[0];	$token_count = $_[1];	if ($type eq 'CNAME' || $type eq 'DNAME' || $type eq 'NS') {		return 0;	}	elsif ($type eq 'MX' || $type eq 'RP') {		return (! defined($token_count) || $token_count == 1) ? 1 : -1;	}	elsif ($type eq 'SRV') {		return (! defined($token_count) || $token_count == 3) ? 3 : -1;	}	else {		return -1;	}}## This subroutine will check an IPv4 or IPv6 address to see if it is valid.# Wildcards are catered for, as are subnets. All addresses are assumed to be# in the 'forward' format - e.g. 10.1.2.3. The fact that an address could be# a name, as in a PTR record, or a value, as in an A record, is also taken# into account.## The final argument, must_be_ipv4, can take the value -1, 0 or 1. -1 indicates# that the address can be either IPv4 or IPv6. 1 indicates that it must be an# IPv4 address, and 0 indicates that it must be IPv6.## valipaddr(addr, origin, name_or_value, wild_allowed, subnet_allowed,#	    must_be_ipv4)#sub valipaddr {	my $name = my $wild = my $subnet = my $ipv4 = my $wild_seen = 0;	my $addr = my $origin = '';	($addr, $origin, $name, $wild, $subnet, $ipv4) = @_;	if ($addr =~ /\*/o) {		$wild_seen++;		return 0 unless ($config{'allow_wild'} && $wild);		return 0 unless ($name);	}	#	# We handle the address by looking to see the type of zone we are in,	# and then the type of address it is. The other arguments should then	# simply decide if the address is valid or not.	#	if ($origin =~ /\.(in-addr|ip6)\.arpa\.$/o) {		#		# This is a reverse zone. As a name the address may belong to		# one of several record types, including PTR, RP, TXT, etc.		# As a value it will probably belong to a CNAME record.		#		# Despite this being a reverse zone, we will have presented,		# and received, the addresses in the 'forward' format. As such		# we do not need to convert them from their reverse arpa domain		# name to the forward format. We will, however, need to modify		# the address if it is a subnet.		#		return 1 if ($addr eq '*');		if ($1 eq 'in-addr') {		# IPv4 reverse zone.			if ($wild_seen) {				if ($addr =~ /^(.+)\.\*$/o) {					$addr = $1 . '.0';				}				else {					return 0;				}			}			if ($subnet) {				if ($addr =~ /^\d{1,3}(\.\d{1,3})?(\.\d{1,3})?(\.\d{1,3})?$/o) {					$addr .= '.0' unless (defined($3));					$addr .= '.0' unless (defined($2));					$addr .= '.0' unless (defined($1));				}				else {			# Invalid subnet given.					return 0;				}			}		}		else {				# IPv6 reverse zone.			if ($wild_seen) {				if ($addr =~ /^(.+)\*$/o) {					$addr = $1 . '0';				}				else {					return 0;				}			}			if ($subnet && $addr =~ /^([\da-f]{1,4}:){0,6}[\da-f]{1,4}$/io) {					#					# At this point we have an IPv6					# address as a value. Any subnet will					# be dealt with by expand_ip6.					#					$addr = &expand_ip6($addr, 1);			}		}	}	else {		#		# This is a forward zone. The address will be a value belonging		# to either an A or AAAA/A6 record. Neither subnets nor		# wildcards are allowed. 		#		return 0 if ($name || $wild_seen);	}	#	# Now see if the final address is valid or not.	#	if ($addr =~ /:/o &&			# It's an IPv6 address.	    $addr =~ /^[:\da-f]+$/io) {		if ($ipv4 == 1) {		# But it must be IPv4!			return 0;		}		else {			$addr = expand_ip6($addr, 0);			return ($addr =~ /^([\da-f]{1,4}:){7}[\da-f]{1,4}$/io);		}	}	elsif ($addr =~ /^[\d.]+$/o) {		# It's an IPv4 address.		if ($ipv4 == 0) {		# But it must be IPv6!			return 0;		}		else {			return &check_ipaddress($addr);		}	}	return 0;}## seen_no_recs(file, named_status, zone_type)#sub seen_no_recs {	my $file = $_[0];	printf '<p><center><b><u>%s:</u></b> &nbsp;%s',					$text{'Warning'}, $text{'no_zone_recs'};	if (defined($file)) {		$file = $config{'chroot'} . &absolute_path($file);		if (! -e $file) {			print ' - ', $text{'zone_file_noexist'}, '</center><p>';			return;		}		elsif (! -s $file) {			print ' - ', $text{'zone_file_empty'}, '</center><p>';			return;		}	}	if ($_[1] <= 0) {		print ' - ', $text{'named_pos_no_run'};	}	elsif ($_[2] eq 'master') {		print '.';	}	else {		print ' - ', $text{'xfr_failed2'};	}	print '</center><p>';	return;}1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -