diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,9 @@
 # ChangeLog
 
+## 4.1.1
+
+- Adding encoder/decoder for CAA RR.
+
 ## 4.1.0
 
 - Breaking change: GHC 7.x and earlier no longer supported.
diff --git a/dns.cabal b/dns.cabal
--- a/dns.cabal
+++ b/dns.cabal
@@ -1,5 +1,5 @@
 Name:                   dns
-Version:                4.1.0
+Version:                4.1.1
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
@@ -43,6 +43,7 @@
                       , base16-bytestring
                       , base64-bytestring
                       , bytestring
+                      , case-insensitive
                       , containers
                       , cryptonite
                       , hourglass
@@ -113,6 +114,7 @@
                       , QuickCheck >= 2.9
                       , base
                       , bytestring
+                      , case-insensitive
                       , hspec
                       , iproute >= 1.3.2
                       , word8
diff --git a/internal/Network/DNS/Decode/Parsers.hs b/internal/Network/DNS/Decode/Parsers.hs
--- a/internal/Network/DNS/Decode/Parsers.hs
+++ b/internal/Network/DNS/Decode/Parsers.hs
@@ -12,6 +12,7 @@
 
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Char8 as BS
+import qualified Data.CaseInsensitive as CI
 import qualified Data.IP
 import Data.IP (IP(..), toIPv4, toIPv6b, makeAddrRange)
 
@@ -280,6 +281,13 @@
     decodeFlags      = get8
     decodeIterations = get16
     decodeSalt       = getInt8 >>= getNByteString
+--
+getRData CAA len = do
+    dend <- rdataEnd len
+    flags <- get8
+    tag <- getInt8 >>= getNByteString
+    tpos <- getPosition
+    RD_CAA flags (CI.mk tag) <$> getNByteString (dend - tpos)
 --
 getRData _  len = UnknownRData <$> getNByteString len
 
diff --git a/internal/Network/DNS/Encode/Builders.hs b/internal/Network/DNS/Encode/Builders.hs
--- a/internal/Network/DNS/Encode/Builders.hs
+++ b/internal/Network/DNS/Encode/Builders.hs
@@ -19,6 +19,7 @@
 import qualified Data.ByteString.Builder as BB
 import qualified Data.ByteString.Char8 as BS
 import qualified Data.ByteString.Lazy.Char8 as LBS
+import qualified Data.CaseInsensitive as CI
 import qualified Data.IP
 import Data.IP (IP(..), fromIPv4, fromIPv6b, makeAddrRange)
 import GHC.Exts (the, groupWith)
@@ -146,6 +147,7 @@
     RD_NSEC3     a f i s h types -> putNSEC3 a f i s h types
     RD_NSEC3PARAM  a f iter salt -> putNSEC3PARAM a f iter salt
     RD_TLSA           u s m dgst -> putTLSA u s m dgst
+    RD_CAA                 f t v -> putCAA f t v
     UnknownRData           bytes -> putByteString bytes
   where
     putSOA mn mr serial refresh retry expire minttl = mconcat
@@ -211,6 +213,11 @@
         , put8 selector
         , put8 mtype
         , putByteString assocData
+        ]
+    putCAA flags tag value = mconcat
+        [ put8 flags
+        , putByteStringWithLength (CI.original tag)
+        , putByteString value
         ]
 
 -- | Encode DNSSEC NSEC type bits
diff --git a/internal/Network/DNS/Memo.hs b/internal/Network/DNS/Memo.hs
--- a/internal/Network/DNS/Memo.hs
+++ b/internal/Network/DNS/Memo.hs
@@ -4,6 +4,7 @@
 
 import qualified Control.Reaper as R
 import qualified Data.ByteString as B
+import qualified Data.CaseInsensitive as CI
 import Data.Hourglass (Elapsed)
 import Data.OrdPSQ (OrdPSQ)
 import qualified Data.OrdPSQ as PSQ
@@ -82,6 +83,7 @@
     copysig s@RDREP_RRSIG{..} =
         s { rrsigZone = B.copy rrsigZone
           , rrsigValue = B.copy rrsigValue }
+copy (RD_CAA f t v)       = RD_CAA f (CI.mk (B.copy (CI.original t))) (B.copy v)
 copy (UnknownRData is)    = UnknownRData $ B.copy is
 
 copyOData :: OData -> OData
diff --git a/internal/Network/DNS/Types/Internal.hs b/internal/Network/DNS/Types/Internal.hs
--- a/internal/Network/DNS/Types/Internal.hs
+++ b/internal/Network/DNS/Types/Internal.hs
@@ -12,6 +12,8 @@
 import qualified Data.ByteString.Base16 as B16
 import qualified Data.ByteString.Base64 as B64
 import qualified Data.ByteString.Char8 as BS
+import Data.CaseInsensitive (CI)
+import qualified Data.CaseInsensitive as CI
 import Data.Char (intToDigit)
 import qualified Data.Hourglass as H
 import Data.IP (IP(..), IPv4, IPv6)
@@ -998,6 +1000,8 @@
                                  -- ^ Child DS (RFC7344)
            | RD_CDNSKEY Word16 Word8 Word8 ByteString
                                  -- ^ Child DNSKEY (RFC7344)
+           | RD_CAA Word8 (CI ByteString) ByteString
+                                 -- ^ CAA (RFC 6844)
            --RD_CSYNC
            | UnknownRData ByteString   -- ^ Unknown resource data
     deriving (Eq, Ord)
@@ -1026,6 +1030,7 @@
       RD_TLSA               u s m d -> showTLSA u s m d
       RD_CDS         tag alg dalg d -> showDS tag alg dalg d
       RD_CDNSKEY            f p a k -> showDNSKEY f p a k
+      RD_CAA                  f t v -> showCAA f t v
       UnknownRData            bytes -> showOpaque bytes
     where
       showSalt ""    = "-"
@@ -1074,6 +1079,8 @@
       showTLSA usage selector mtype digest =
           show usage ++ " " ++ show selector ++ " " ++
           show mtype ++ " " ++ _b16encode digest
+      showCAA flags tag value =
+          show flags ++ " " ++ BS.unpack (CI.original tag) ++ " " ++ show value
       -- | Opaque RData: <https://tools.ietf.org/html/rfc3597#section-5>
       showOpaque bs = unwords ["\\#", show (BS.length bs), _b16encode bs]
 
diff --git a/test/RoundTripSpec.hs b/test/RoundTripSpec.hs
--- a/test/RoundTripSpec.hs
+++ b/test/RoundTripSpec.hs
@@ -6,6 +6,7 @@
 import Data.IP (Addr, IP(..), IPv4, IPv6, toIPv4, toIPv6, makeAddrRange)
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Char8 as BS
+import qualified Data.CaseInsensitive as CI
 import Test.Hspec
 import Test.Hspec.QuickCheck
 import Test.QuickCheck (Gen, arbitrary, elements, forAll, frequency, listOf, oneof)
@@ -118,6 +119,7 @@
         NSEC -> RD_NSEC <$> genDomain <*> genNsecTypes
         NSEC3 -> genNSEC3
         TLSA -> RD_TLSA <$> genWord8 <*> genWord8 <*> genWord8 <*> genByteString
+        CAA -> RD_CAA <$> genWord8 <*> (CI.mk <$> genByteString) <*> genByteString
 
         _ -> pure . RD_TXT $ "Unhandled type " <> BS.pack (show typ)
   where
