diff --git a/Network/DNS/Internal.hs b/Network/DNS/Internal.hs
--- a/Network/DNS/Internal.hs
+++ b/Network/DNS/Internal.hs
@@ -53,14 +53,34 @@
 
 -- | An enumeration of all possible DNS errors that can occur.
 data DNSError =
-  -- | The sequence number of the answer doesn't match our query. This
-  --   could indicate foul play.
-  SequenceNumberMismatch
-  -- | The request simply timed out.
+    -- | The sequence number of the answer doesn't match our query. This
+    --   could indicate foul play.
+    SequenceNumberMismatch
+    -- | The request simply timed out.
   | TimeoutExpired
-  -- | The answer has the correct sequence number, but returned an
-  --   unexpected RDATA format.
+    -- | The answer has the correct sequence number, but returned an
+    --   unexpected RDATA format.
   | UnexpectedRDATA
+    -- | The domain for query is illegal.
+  | IllegalDomain
+    -- | The name server was unable to interpret the query.
+  | FormatError
+    -- | The name server was unable to process this query due to a
+    --   problem with the name server.
+  | ServerFailure
+    -- | Meaningful only for responses from an authoritative name
+    -- server, this code signifies that the
+    -- domain name referenced in the query does not exist.
+  | NameError
+    -- | The name server does not support the requested kind of query.
+  | NotImplemented
+    -- | The name server refuses to perform the specified operation for
+    --   policy reasons.  For example, a name
+    --   server may not wish to provide the
+    --   information to the particular requester,
+    --   or a name server may not wish to perform
+    --   a particular operation (e.g., zone transfer) for particular data.
+  | OperationRefused
   deriving (Eq, Show, Typeable)
 
 instance Exception DNSError
diff --git a/Network/DNS/Resolver.hs b/Network/DNS/Resolver.hs
--- a/Network/DNS/Resolver.hs
+++ b/Network/DNS/Resolver.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP, OverloadedStrings #-}
 
 -- | DNS Resolver and generic (lower-level) lookup functions.
 module Network.DNS.Resolver (
@@ -10,11 +10,16 @@
   -- ** Type and function for resolver
   , Resolver(..), withResolver, withResolvers
   -- ** Looking up functions
-  , lookup, lookupAuth, lookupRaw
+  , lookup
+  , lookupAuth
+  -- ** Raw looking up function
+  , lookupRaw
+  , fromDNSFormat
   ) where
 
 import Control.Applicative
 import Control.Exception
+import qualified Data.ByteString.Char8 as BS
 import Data.Char
 import Data.Int
 import Data.List hiding (find, lookup)
@@ -194,15 +199,31 @@
               -> Domain
               -> TYPE
               -> IO (Either DNSError [RDATA])
-lookupSection section rlv dom typ = (>>= toRDATA) <$> lookupRaw rlv dom typ
+lookupSection section rlv dom typ = do
+    eans <- lookupRaw rlv dom typ
+    case eans of
+        Left  err -> return $ Left err
+        Right ans -> return $ fromDNSFormat ans toRDATA
   where
     {- CNAME hack
     dom' = if "." `isSuffixOf` dom then dom else dom ++ "."
     correct r = rrname r == dom' && rrtype r == typ
     -}
     correct r = rrtype r == typ
-    toRDATA = Right . map rdata . filter correct . section
+    toRDATA = map rdata . filter correct . section
 
+-- | Extract necessary information from 'DNSFormat'
+fromDNSFormat :: DNSFormat -> (DNSFormat -> a) -> Either DNSError a
+fromDNSFormat ans conv = case errcode ans of
+    NoErr     -> Right $ conv ans
+    FormatErr -> Left FormatError
+    ServFail  -> Left ServerFailure
+    NameErr   -> Left NameError
+    NotImpl   -> Left NotImplemented
+    Refused   -> Left OperationRefused
+  where
+    errcode = rcode . flags . header
+
 -- | Look up resource records for a domain, collecting the results
 --   from the ANSWER section of the response.
 --
@@ -264,6 +285,8 @@
 --  @
 --
 lookupRaw :: Resolver -> Domain -> TYPE -> IO (Either DNSError DNSFormat)
+lookupRaw _   dom _
+  | isIllegal dom     = return $ Left IllegalDomain
 lookupRaw rlv dom typ = do
     seqno <- genId rlv
     let query = composeQuery seqno [q]
@@ -299,3 +322,14 @@
 	sent <- send sock (LB.unpack bs)
 	when (sent < fromIntegral (LB.length bs)) $ sendAll sock (LB.drop (fromIntegral sent) bs)
 #endif
+
+isIllegal :: Domain -> Bool
+isIllegal ""                    = True
+isIllegal dom
+  | '.' `BS.notElem` dom        = True
+  | ':' `BS.elem` dom           = True
+  | '/' `BS.elem` dom           = True
+  | BS.length dom > 253         = True
+  | any (\x -> BS.length x > 63)
+        (BS.split '.' dom)      = True
+isIllegal _                     = False
diff --git a/dns.cabal b/dns.cabal
--- a/dns.cabal
+++ b/dns.cabal
@@ -1,5 +1,5 @@
 Name:                   dns
-Version:                1.1.1
+Version:                1.2.0
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
