Improements to IP validation (including separate isValidIP() method)