!str_ends_with($elements[0], $filter_domain), false => $elements[0] !== $filter_domain, }) continue; // Ignore records for other domains if (!in_array($elements[2], $types, true)) continue; // Ignore records generated by Knot array_push($parsed_zone_content, $elements); } return $parsed_zone_content; } function knotc(array $cmds, array &$output = NULL, int &$return_code = NULL): void { exescape([ CONF['dns']['knotc_path'], '--blocking', '--timeout', '20', '--', ...$cmds, ], $output, $return_code); } function knotcConfExec(array $cmds): void { knotc(['conf-begin'], $output['begin'], $code['begin']); if ($code['begin'] !== 0) output(500, 'knotcConfExec: knotc failed with exit code ' . $code['begin'] . ': ' . $output['begin'][0] . '.'); foreach ($cmds as $cmd) { knotc($cmd, $output['op'], $code['op']); if ($code['op'] !== 0) { knotc(['conf-abort']); output(500, 'knotcConfExec: knotc failed with exit code ' . $code['op'] . ': ' . $output['op'][0] . '.'); } } knotc(['conf-commit'], $output['commit'], $code['commit']); if ($code['commit'] !== 0) { knotc(['conf-abort']); output(500, 'knotcConfExec: knotc failed with exit code ' . $code['commit'] . ': ' . $output['commit'][0] . '.'); } } function knotcZoneExec(string $zone, array $cmd, string $action = NULL): void { $action = checkAction($action ?? $_POST['action']); knotc(['zone-begin', $zone], $output['begin'], $code['begin']); if ($code['begin'] !== 0) output(500, 'knotcZoneExec: knotc failed with exit code ' . $code['begin'] . ': ' . $output['begin'][0] . '.'); knotc(['zone-' . $action . 'set', $zone, ...$cmd], $output['op'], $code['op']); if ($code['op'] !== 0) { knotc(['zone-abort', $zone]); output(500, 'knotcZoneExec: knotc failed with exit code ' . $code['op'] . ': ' . $output['op'][0] . '.'); } knotc(['zone-commit', $zone], $output['commit'], $code['commit']); if ($code['commit'] !== 0) { knotc(['zone-abort', $zone]); output(500, 'knotcZoneExec: knotc failed with exit code ' . $code['commit'] . ': ' . $output['commit'][0] . '.'); } } function checkIpFormat(string $ip): string { return match ($ip) { filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) => 'AAAA', filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) => 'A', default => output(403, _('IP address malformed.')), }; } function checkAbsoluteDomainFormat(string $domain): void { // If the domain must end with a dot if (!filter_var($domain, FILTER_VALIDATE_DOMAIN) OR preg_match('/^(?=^.{1,254}$)([a-z0-9_-]{1,63}\.){2,127}$/D', $domain) !== 1) output(403, _('Domain malformed.')); } function formatEndWithDot(string $str): string { if (!str_ends_with($str, '.')) $str .= '.'; return $str; } function formatAbsoluteDomain(string $domain): string { $domain = formatEndWithDot(strtolower($domain)); checkAbsoluteDomainFormat($domain); return $domain; } function checkAction(string $action): string { return match ($action) { 'add' => '', 'delete' => 'un', default => output(403, 'Wrong value for action.'), }; }