A única coisa que posso ver aqui é que você diz ao PDO para lançar exceções depois você tentou abrir a conexão. Isso provavelmente é tarde demais.
O que você pode fazer é enviar essa opção para o construtor diretamente usando o 4º parâmetro:
try {
$opts = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
$db = new PDO($dbms . ':host=' . $dbhost . ';port=' . $dbport . ';dbname=' . $dbname,
$dbuser, $dbpasswd, $opts);
} catch(PDOException $e) {
...
Isso provavelmente resolverá seu problema.
Editar: Se o nome do host for fornecido pelo usuário, você poderá validá-lo antes de enviá-lo ao construtor PDO.
Por exemplo usando:
if (filter_var(gethostbyname($user_provided_host_name), FILTER_VALIDATE_IP)) {
// valid hostname / ip address
}
Isso funcionará para nomes de domínio,
localhost
e endereços IP.