{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleInstances #-}

module Propellor.Types.Dns where

import Propellor.Types.OS (HostName)
import Propellor.Types.Empty
import Propellor.Types.Info
import Propellor.Types.ConfigurableValue
import Utility.Split

import Data.Word
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Semigroup as Sem
import Data.List
import Data.Monoid
import Prelude

type Domain = String

data IPAddr = IPv4 String | IPv6 String
	deriving (ReadPrec [IPAddr]
ReadPrec IPAddr
Int -> ReadS IPAddr
ReadS [IPAddr]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [IPAddr]
$creadListPrec :: ReadPrec [IPAddr]
readPrec :: ReadPrec IPAddr
$creadPrec :: ReadPrec IPAddr
readList :: ReadS [IPAddr]
$creadList :: ReadS [IPAddr]
readsPrec :: Int -> ReadS IPAddr
$creadsPrec :: Int -> ReadS IPAddr
Read, Int -> IPAddr -> ShowS
[IPAddr] -> ShowS
IPAddr -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [IPAddr] -> ShowS
$cshowList :: [IPAddr] -> ShowS
show :: IPAddr -> HostName
$cshow :: IPAddr -> HostName
showsPrec :: Int -> IPAddr -> ShowS
$cshowsPrec :: Int -> IPAddr -> ShowS
Show, IPAddr -> IPAddr -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IPAddr -> IPAddr -> Bool
$c/= :: IPAddr -> IPAddr -> Bool
== :: IPAddr -> IPAddr -> Bool
$c== :: IPAddr -> IPAddr -> Bool
Eq, Eq IPAddr
IPAddr -> IPAddr -> Bool
IPAddr -> IPAddr -> Ordering
IPAddr -> IPAddr -> IPAddr
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: IPAddr -> IPAddr -> IPAddr
$cmin :: IPAddr -> IPAddr -> IPAddr
max :: IPAddr -> IPAddr -> IPAddr
$cmax :: IPAddr -> IPAddr -> IPAddr
>= :: IPAddr -> IPAddr -> Bool
$c>= :: IPAddr -> IPAddr -> Bool
> :: IPAddr -> IPAddr -> Bool
$c> :: IPAddr -> IPAddr -> Bool
<= :: IPAddr -> IPAddr -> Bool
$c<= :: IPAddr -> IPAddr -> Bool
< :: IPAddr -> IPAddr -> Bool
$c< :: IPAddr -> IPAddr -> Bool
compare :: IPAddr -> IPAddr -> Ordering
$ccompare :: IPAddr -> IPAddr -> Ordering
Ord)

instance ConfigurableValue IPAddr where
	val :: IPAddr -> HostName
val (IPv4 HostName
addr) = HostName
addr
	val (IPv6 HostName
addr) = HostName
addr

newtype AliasesInfo = AliasesInfo (S.Set HostName)
	deriving (Int -> AliasesInfo -> ShowS
[AliasesInfo] -> ShowS
AliasesInfo -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [AliasesInfo] -> ShowS
$cshowList :: [AliasesInfo] -> ShowS
show :: AliasesInfo -> HostName
$cshow :: AliasesInfo -> HostName
showsPrec :: Int -> AliasesInfo -> ShowS
$cshowsPrec :: Int -> AliasesInfo -> ShowS
Show, AliasesInfo -> AliasesInfo -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AliasesInfo -> AliasesInfo -> Bool
$c/= :: AliasesInfo -> AliasesInfo -> Bool
== :: AliasesInfo -> AliasesInfo -> Bool
$c== :: AliasesInfo -> AliasesInfo -> Bool
Eq, Eq AliasesInfo
AliasesInfo -> AliasesInfo -> Bool
AliasesInfo -> AliasesInfo -> Ordering
AliasesInfo -> AliasesInfo -> AliasesInfo
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: AliasesInfo -> AliasesInfo -> AliasesInfo
$cmin :: AliasesInfo -> AliasesInfo -> AliasesInfo
max :: AliasesInfo -> AliasesInfo -> AliasesInfo
$cmax :: AliasesInfo -> AliasesInfo -> AliasesInfo
>= :: AliasesInfo -> AliasesInfo -> Bool
$c>= :: AliasesInfo -> AliasesInfo -> Bool
> :: AliasesInfo -> AliasesInfo -> Bool
$c> :: AliasesInfo -> AliasesInfo -> Bool
<= :: AliasesInfo -> AliasesInfo -> Bool
$c<= :: AliasesInfo -> AliasesInfo -> Bool
< :: AliasesInfo -> AliasesInfo -> Bool
$c< :: AliasesInfo -> AliasesInfo -> Bool
compare :: AliasesInfo -> AliasesInfo -> Ordering
$ccompare :: AliasesInfo -> AliasesInfo -> Ordering
Ord, NonEmpty AliasesInfo -> AliasesInfo
AliasesInfo -> AliasesInfo -> AliasesInfo
forall b. Integral b => b -> AliasesInfo -> AliasesInfo
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> AliasesInfo -> AliasesInfo
$cstimes :: forall b. Integral b => b -> AliasesInfo -> AliasesInfo
sconcat :: NonEmpty AliasesInfo -> AliasesInfo
$csconcat :: NonEmpty AliasesInfo -> AliasesInfo
<> :: AliasesInfo -> AliasesInfo -> AliasesInfo
$c<> :: AliasesInfo -> AliasesInfo -> AliasesInfo
Sem.Semigroup, Semigroup AliasesInfo
AliasesInfo
[AliasesInfo] -> AliasesInfo
AliasesInfo -> AliasesInfo -> AliasesInfo
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [AliasesInfo] -> AliasesInfo
$cmconcat :: [AliasesInfo] -> AliasesInfo
mappend :: AliasesInfo -> AliasesInfo -> AliasesInfo
$cmappend :: AliasesInfo -> AliasesInfo -> AliasesInfo
mempty :: AliasesInfo
$cmempty :: AliasesInfo
Monoid, Typeable)

instance IsInfo AliasesInfo where
	propagateInfo :: AliasesInfo -> PropagateInfo
propagateInfo AliasesInfo
_ = Bool -> PropagateInfo
PropagateInfo Bool
False

toAliasesInfo :: [HostName] -> AliasesInfo
toAliasesInfo :: [HostName] -> AliasesInfo
toAliasesInfo [HostName]
l = Set HostName -> AliasesInfo
AliasesInfo (forall a. Ord a => [a] -> Set a
S.fromList [HostName]
l)

fromAliasesInfo :: AliasesInfo -> [HostName]
fromAliasesInfo :: AliasesInfo -> [HostName]
fromAliasesInfo (AliasesInfo Set HostName
s) = forall a. Set a -> [a]
S.toList Set HostName
s

-- | Use this for DNS Info that should propagate from a container to a
-- host. For example, this can be used for CNAME to make aliases
-- of the containers in the host be reflected in the DNS.
newtype DnsInfoPropagated = DnsInfoPropagated
	{ DnsInfoPropagated -> Set Record
fromDnsInfoPropagated :: S.Set Record }
	deriving (Int -> DnsInfoPropagated -> ShowS
[DnsInfoPropagated] -> ShowS
DnsInfoPropagated -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [DnsInfoPropagated] -> ShowS
$cshowList :: [DnsInfoPropagated] -> ShowS
show :: DnsInfoPropagated -> HostName
$cshow :: DnsInfoPropagated -> HostName
showsPrec :: Int -> DnsInfoPropagated -> ShowS
$cshowsPrec :: Int -> DnsInfoPropagated -> ShowS
Show, DnsInfoPropagated -> DnsInfoPropagated -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
$c/= :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
== :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
$c== :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
Eq, Eq DnsInfoPropagated
DnsInfoPropagated -> DnsInfoPropagated -> Bool
DnsInfoPropagated -> DnsInfoPropagated -> Ordering
DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
$cmin :: DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
max :: DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
$cmax :: DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
>= :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
$c>= :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
> :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
$c> :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
<= :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
$c<= :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
< :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
$c< :: DnsInfoPropagated -> DnsInfoPropagated -> Bool
compare :: DnsInfoPropagated -> DnsInfoPropagated -> Ordering
$ccompare :: DnsInfoPropagated -> DnsInfoPropagated -> Ordering
Ord, NonEmpty DnsInfoPropagated -> DnsInfoPropagated
DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
forall b. Integral b => b -> DnsInfoPropagated -> DnsInfoPropagated
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> DnsInfoPropagated -> DnsInfoPropagated
$cstimes :: forall b. Integral b => b -> DnsInfoPropagated -> DnsInfoPropagated
sconcat :: NonEmpty DnsInfoPropagated -> DnsInfoPropagated
$csconcat :: NonEmpty DnsInfoPropagated -> DnsInfoPropagated
<> :: DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
$c<> :: DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
Sem.Semigroup, Semigroup DnsInfoPropagated
DnsInfoPropagated
[DnsInfoPropagated] -> DnsInfoPropagated
DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [DnsInfoPropagated] -> DnsInfoPropagated
$cmconcat :: [DnsInfoPropagated] -> DnsInfoPropagated
mappend :: DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
$cmappend :: DnsInfoPropagated -> DnsInfoPropagated -> DnsInfoPropagated
mempty :: DnsInfoPropagated
$cmempty :: DnsInfoPropagated
Monoid, Typeable)

toDnsInfoPropagated :: S.Set Record -> DnsInfoPropagated
toDnsInfoPropagated :: Set Record -> DnsInfoPropagated
toDnsInfoPropagated = Set Record -> DnsInfoPropagated
DnsInfoPropagated

instance IsInfo DnsInfoPropagated where
	propagateInfo :: DnsInfoPropagated -> PropagateInfo
propagateInfo DnsInfoPropagated
_ = Bool -> PropagateInfo
PropagateInfo Bool
True

-- | Use this for DNS Info that should not propagate from a container to a
-- host. For example, an IP address of a container should not influence
-- the host.
newtype DnsInfoUnpropagated = DnsInfoUnpropagated
	{ DnsInfoUnpropagated -> Set Record
fromDnsInfoUnpropagated :: S.Set Record }
	deriving (Int -> DnsInfoUnpropagated -> ShowS
[DnsInfoUnpropagated] -> ShowS
DnsInfoUnpropagated -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [DnsInfoUnpropagated] -> ShowS
$cshowList :: [DnsInfoUnpropagated] -> ShowS
show :: DnsInfoUnpropagated -> HostName
$cshow :: DnsInfoUnpropagated -> HostName
showsPrec :: Int -> DnsInfoUnpropagated -> ShowS
$cshowsPrec :: Int -> DnsInfoUnpropagated -> ShowS
Show, DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
$c/= :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
== :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
$c== :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
Eq, Eq DnsInfoUnpropagated
DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
DnsInfoUnpropagated -> DnsInfoUnpropagated -> Ordering
DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
$cmin :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
max :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
$cmax :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
>= :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
$c>= :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
> :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
$c> :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
<= :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
$c<= :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
< :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
$c< :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Bool
compare :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Ordering
$ccompare :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> Ordering
Ord, NonEmpty DnsInfoUnpropagated -> DnsInfoUnpropagated
DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
forall b.
Integral b =>
b -> DnsInfoUnpropagated -> DnsInfoUnpropagated
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b.
Integral b =>
b -> DnsInfoUnpropagated -> DnsInfoUnpropagated
$cstimes :: forall b.
Integral b =>
b -> DnsInfoUnpropagated -> DnsInfoUnpropagated
sconcat :: NonEmpty DnsInfoUnpropagated -> DnsInfoUnpropagated
$csconcat :: NonEmpty DnsInfoUnpropagated -> DnsInfoUnpropagated
<> :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
$c<> :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
Sem.Semigroup, Semigroup DnsInfoUnpropagated
DnsInfoUnpropagated
[DnsInfoUnpropagated] -> DnsInfoUnpropagated
DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [DnsInfoUnpropagated] -> DnsInfoUnpropagated
$cmconcat :: [DnsInfoUnpropagated] -> DnsInfoUnpropagated
mappend :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
$cmappend :: DnsInfoUnpropagated -> DnsInfoUnpropagated -> DnsInfoUnpropagated
mempty :: DnsInfoUnpropagated
$cmempty :: DnsInfoUnpropagated
Monoid, Typeable)

toDnsInfoUnpropagated :: S.Set Record -> DnsInfoUnpropagated
toDnsInfoUnpropagated :: Set Record -> DnsInfoUnpropagated
toDnsInfoUnpropagated = Set Record -> DnsInfoUnpropagated
DnsInfoUnpropagated

-- | Get all DNS Info.
getDnsInfo :: Info -> S.Set Record
getDnsInfo :: Info -> Set Record
getDnsInfo Info
i = DnsInfoUnpropagated -> Set Record
fromDnsInfoUnpropagated (forall v. IsInfo v => Info -> v
fromInfo Info
i)
	forall a. Ord a => Set a -> Set a -> Set a
`S.union` DnsInfoPropagated -> Set Record
fromDnsInfoPropagated (forall v. IsInfo v => Info -> v
fromInfo Info
i)

instance IsInfo DnsInfoUnpropagated where
	propagateInfo :: DnsInfoUnpropagated -> PropagateInfo
propagateInfo DnsInfoUnpropagated
_ = Bool -> PropagateInfo
PropagateInfo Bool
False

-- | Represents a bind 9 named.conf file.
data NamedConf = NamedConf
	{ NamedConf -> HostName
confDomain :: Domain
	, NamedConf -> DnsServerType
confDnsServerType :: DnsServerType
	, NamedConf -> HostName
confFile :: FilePath
	, NamedConf -> [IPAddr]
confMasters :: [IPAddr]
	, NamedConf -> [IPAddr]
confAllowTransfer :: [IPAddr]
	, NamedConf -> [HostName]
confLines :: [String]
	}
	deriving (Int -> NamedConf -> ShowS
[NamedConf] -> ShowS
NamedConf -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [NamedConf] -> ShowS
$cshowList :: [NamedConf] -> ShowS
show :: NamedConf -> HostName
$cshow :: NamedConf -> HostName
showsPrec :: Int -> NamedConf -> ShowS
$cshowsPrec :: Int -> NamedConf -> ShowS
Show, NamedConf -> NamedConf -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NamedConf -> NamedConf -> Bool
$c/= :: NamedConf -> NamedConf -> Bool
== :: NamedConf -> NamedConf -> Bool
$c== :: NamedConf -> NamedConf -> Bool
Eq, Eq NamedConf
NamedConf -> NamedConf -> Bool
NamedConf -> NamedConf -> Ordering
NamedConf -> NamedConf -> NamedConf
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NamedConf -> NamedConf -> NamedConf
$cmin :: NamedConf -> NamedConf -> NamedConf
max :: NamedConf -> NamedConf -> NamedConf
$cmax :: NamedConf -> NamedConf -> NamedConf
>= :: NamedConf -> NamedConf -> Bool
$c>= :: NamedConf -> NamedConf -> Bool
> :: NamedConf -> NamedConf -> Bool
$c> :: NamedConf -> NamedConf -> Bool
<= :: NamedConf -> NamedConf -> Bool
$c<= :: NamedConf -> NamedConf -> Bool
< :: NamedConf -> NamedConf -> Bool
$c< :: NamedConf -> NamedConf -> Bool
compare :: NamedConf -> NamedConf -> Ordering
$ccompare :: NamedConf -> NamedConf -> Ordering
Ord)

data DnsServerType = Master | Secondary
	deriving (Int -> DnsServerType -> ShowS
[DnsServerType] -> ShowS
DnsServerType -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [DnsServerType] -> ShowS
$cshowList :: [DnsServerType] -> ShowS
show :: DnsServerType -> HostName
$cshow :: DnsServerType -> HostName
showsPrec :: Int -> DnsServerType -> ShowS
$cshowsPrec :: Int -> DnsServerType -> ShowS
Show, DnsServerType -> DnsServerType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DnsServerType -> DnsServerType -> Bool
$c/= :: DnsServerType -> DnsServerType -> Bool
== :: DnsServerType -> DnsServerType -> Bool
$c== :: DnsServerType -> DnsServerType -> Bool
Eq, Eq DnsServerType
DnsServerType -> DnsServerType -> Bool
DnsServerType -> DnsServerType -> Ordering
DnsServerType -> DnsServerType -> DnsServerType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: DnsServerType -> DnsServerType -> DnsServerType
$cmin :: DnsServerType -> DnsServerType -> DnsServerType
max :: DnsServerType -> DnsServerType -> DnsServerType
$cmax :: DnsServerType -> DnsServerType -> DnsServerType
>= :: DnsServerType -> DnsServerType -> Bool
$c>= :: DnsServerType -> DnsServerType -> Bool
> :: DnsServerType -> DnsServerType -> Bool
$c> :: DnsServerType -> DnsServerType -> Bool
<= :: DnsServerType -> DnsServerType -> Bool
$c<= :: DnsServerType -> DnsServerType -> Bool
< :: DnsServerType -> DnsServerType -> Bool
$c< :: DnsServerType -> DnsServerType -> Bool
compare :: DnsServerType -> DnsServerType -> Ordering
$ccompare :: DnsServerType -> DnsServerType -> Ordering
Ord)

-- | Represents a bind 9 zone file.
data Zone = Zone
	{ Zone -> HostName
zDomain :: Domain
	, Zone -> SOA
zSOA :: SOA
	, Zone -> [(BindDomain, Record)]
zHosts :: [(BindDomain, Record)]
	}
	deriving (ReadPrec [Zone]
ReadPrec Zone
Int -> ReadS Zone
ReadS [Zone]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Zone]
$creadListPrec :: ReadPrec [Zone]
readPrec :: ReadPrec Zone
$creadPrec :: ReadPrec Zone
readList :: ReadS [Zone]
$creadList :: ReadS [Zone]
readsPrec :: Int -> ReadS Zone
$creadsPrec :: Int -> ReadS Zone
Read, Int -> Zone -> ShowS
[Zone] -> ShowS
Zone -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [Zone] -> ShowS
$cshowList :: [Zone] -> ShowS
show :: Zone -> HostName
$cshow :: Zone -> HostName
showsPrec :: Int -> Zone -> ShowS
$cshowsPrec :: Int -> Zone -> ShowS
Show, Zone -> Zone -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Zone -> Zone -> Bool
$c/= :: Zone -> Zone -> Bool
== :: Zone -> Zone -> Bool
$c== :: Zone -> Zone -> Bool
Eq)

-- | Every domain has a SOA record, which is big and complicated.
data SOA = SOA
	{ SOA -> BindDomain
sDomain :: BindDomain
	-- ^ Typically ns1.your.domain
	, SOA -> SerialNumber
sSerial :: SerialNumber
	-- ^ The most important parameter is the serial number,
	-- which must increase after each change.
	, SOA -> Integer
sRefresh :: Integer
	, SOA -> Integer
sRetry :: Integer
	, SOA -> Integer
sExpire :: Integer
	, SOA -> Integer
sNegativeCacheTTL :: Integer
	}
	deriving (ReadPrec [SOA]
ReadPrec SOA
Int -> ReadS SOA
ReadS [SOA]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [SOA]
$creadListPrec :: ReadPrec [SOA]
readPrec :: ReadPrec SOA
$creadPrec :: ReadPrec SOA
readList :: ReadS [SOA]
$creadList :: ReadS [SOA]
readsPrec :: Int -> ReadS SOA
$creadsPrec :: Int -> ReadS SOA
Read, Int -> SOA -> ShowS
[SOA] -> ShowS
SOA -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [SOA] -> ShowS
$cshowList :: [SOA] -> ShowS
show :: SOA -> HostName
$cshow :: SOA -> HostName
showsPrec :: Int -> SOA -> ShowS
$cshowsPrec :: Int -> SOA -> ShowS
Show, SOA -> SOA -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SOA -> SOA -> Bool
$c/= :: SOA -> SOA -> Bool
== :: SOA -> SOA -> Bool
$c== :: SOA -> SOA -> Bool
Eq)

-- | Types of DNS records.
--
-- This is not a complete list, more can be added.
data Record
	= Address IPAddr
	| CNAME BindDomain
	| MX Int BindDomain
	| NS BindDomain
	| TXT String
	| SRV Word16 Word16 Word16 BindDomain
	| SSHFP Int Int String
	| INCLUDE FilePath
	| PTR ReverseIP
	deriving (ReadPrec [Record]
ReadPrec Record
Int -> ReadS Record
ReadS [Record]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Record]
$creadListPrec :: ReadPrec [Record]
readPrec :: ReadPrec Record
$creadPrec :: ReadPrec Record
readList :: ReadS [Record]
$creadList :: ReadS [Record]
readsPrec :: Int -> ReadS Record
$creadsPrec :: Int -> ReadS Record
Read, Int -> Record -> ShowS
[Record] -> ShowS
Record -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [Record] -> ShowS
$cshowList :: [Record] -> ShowS
show :: Record -> HostName
$cshow :: Record -> HostName
showsPrec :: Int -> Record -> ShowS
$cshowsPrec :: Int -> Record -> ShowS
Show, Record -> Record -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Record -> Record -> Bool
$c/= :: Record -> Record -> Bool
== :: Record -> Record -> Bool
$c== :: Record -> Record -> Bool
Eq, Eq Record
Record -> Record -> Bool
Record -> Record -> Ordering
Record -> Record -> Record
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Record -> Record -> Record
$cmin :: Record -> Record -> Record
max :: Record -> Record -> Record
$cmax :: Record -> Record -> Record
>= :: Record -> Record -> Bool
$c>= :: Record -> Record -> Bool
> :: Record -> Record -> Bool
$c> :: Record -> Record -> Bool
<= :: Record -> Record -> Bool
$c<= :: Record -> Record -> Bool
< :: Record -> Record -> Bool
$c< :: Record -> Record -> Bool
compare :: Record -> Record -> Ordering
$ccompare :: Record -> Record -> Ordering
Ord, Typeable)

-- | An in-addr.arpa record corresponding to an IPAddr.
type ReverseIP = String

reverseIP :: IPAddr -> ReverseIP
reverseIP :: IPAddr -> HostName
reverseIP (IPv4 HostName
addr) = forall a. [a] -> [[a]] -> [a]
intercalate HostName
"." (forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ forall c. Eq c => c -> [c] -> [[c]]
splitc Char
'.' HostName
addr) forall a. [a] -> [a] -> [a]
++ HostName
".in-addr.arpa"
reverseIP addr :: IPAddr
addr@(IPv6 HostName
_) = forall a. [a] -> [a]
reverse (forall a. a -> [a] -> [a]
intersperse Char
'.' forall a b. (a -> b) -> a -> b
$ forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace HostName
":" HostName
"" forall a b. (a -> b) -> a -> b
$ forall t. ConfigurableValue t => t -> HostName
val forall a b. (a -> b) -> a -> b
$ IPAddr -> IPAddr
canonicalIP IPAddr
addr) forall a. [a] -> [a] -> [a]
++ HostName
".ip6.arpa"

-- | Converts an IP address (particularly IPv6) to canonical, fully
-- expanded form.
canonicalIP :: IPAddr -> IPAddr
canonicalIP :: IPAddr -> IPAddr
canonicalIP (IPv4 HostName
addr) = HostName -> IPAddr
IPv4 HostName
addr
canonicalIP (IPv6 HostName
addr) = HostName -> IPAddr
IPv6 forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [[a]] -> [a]
intercalate HostName
":" forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map ShowS
canonicalGroup forall a b. (a -> b) -> a -> b
$ forall c. Eq c => c -> [c] -> [[c]]
splitc Char
':' forall a b. (a -> b) -> a -> b
$ ShowS
replaceImplicitGroups HostName
addr
  where
	canonicalGroup :: ShowS
canonicalGroup HostName
g
		| Int
l forall a. Ord a => a -> a -> Bool
<= Int
4    = forall a. Int -> a -> [a]
replicate (Int
4 forall a. Num a => a -> a -> a
- Int
l) Char
'0' forall a. [a] -> [a] -> [a]
++ HostName
g
		| Bool
otherwise = forall a. HasCallStack => HostName -> a
error forall a b. (a -> b) -> a -> b
$ HostName
"IPv6 group " forall a. [a] -> [a] -> [a]
++ HostName
g forall a. [a] -> [a] -> [a]
++ HostName
"as more than 4 hex digits"
	  where
		l :: Int
l = forall (t :: * -> *) a. Foldable t => t a -> Int
length HostName
g
	emptyGroups :: Int -> HostName
emptyGroups Int
n = forall a. (a -> a) -> a -> [a]
iterate (forall a. [a] -> [a] -> [a]
++ HostName
":") HostName
"" forall a. [a] -> Int -> a
!! Int
n
	numberOfImplicitGroups :: HostName -> Int
numberOfImplicitGroups HostName
a = Int
8 forall a. Num a => a -> a -> a
- forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall c. Eq c => c -> [c] -> [[c]]
splitc Char
':' forall a b. (a -> b) -> a -> b
$ forall a. Eq a => [a] -> [a] -> [a] -> [a]
replace HostName
"::" HostName
"" HostName
a)
	replaceImplicitGroups :: ShowS
replaceImplicitGroups HostName
a = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall a b. (a -> b) -> a -> b
$ [HostName] -> [HostName]
aux forall a b. (a -> b) -> a -> b
$ forall a. Eq a => [a] -> [a] -> [[a]]
split HostName
"::" HostName
a
	  where
		aux :: [HostName] -> [HostName]
aux [] = []
		aux (HostName
x : [HostName]
xs) = HostName
x forall a. a -> [a] -> [a]
: Int -> HostName
emptyGroups (HostName -> Int
numberOfImplicitGroups HostName
a) forall a. a -> [a] -> [a]
: [HostName]
xs

getIPAddr :: Record -> Maybe IPAddr
getIPAddr :: Record -> Maybe IPAddr
getIPAddr (Address IPAddr
addr) = forall a. a -> Maybe a
Just IPAddr
addr
getIPAddr Record
_ = forall a. Maybe a
Nothing

getCNAME :: Record -> Maybe BindDomain
getCNAME :: Record -> Maybe BindDomain
getCNAME (CNAME BindDomain
d) = forall a. a -> Maybe a
Just BindDomain
d
getCNAME Record
_ = forall a. Maybe a
Nothing

getNS :: Record -> Maybe BindDomain
getNS :: Record -> Maybe BindDomain
getNS (NS BindDomain
d) = forall a. a -> Maybe a
Just BindDomain
d
getNS Record
_ = forall a. Maybe a
Nothing

-- | Bind serial numbers are unsigned, 32 bit integers.
type SerialNumber = Word32

-- | Domains in the zone file must end with a period if they are absolute.
--
-- Let's use a type to keep absolute domains straight from relative
-- domains.
--
-- The RootDomain refers to the top level of the domain, so can be used
-- to add nameservers, MX's, etc to a domain.
data BindDomain = RelDomain Domain | AbsDomain Domain | RootDomain
	deriving (ReadPrec [BindDomain]
ReadPrec BindDomain
Int -> ReadS BindDomain
ReadS [BindDomain]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [BindDomain]
$creadListPrec :: ReadPrec [BindDomain]
readPrec :: ReadPrec BindDomain
$creadPrec :: ReadPrec BindDomain
readList :: ReadS [BindDomain]
$creadList :: ReadS [BindDomain]
readsPrec :: Int -> ReadS BindDomain
$creadsPrec :: Int -> ReadS BindDomain
Read, Int -> BindDomain -> ShowS
[BindDomain] -> ShowS
BindDomain -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [BindDomain] -> ShowS
$cshowList :: [BindDomain] -> ShowS
show :: BindDomain -> HostName
$cshow :: BindDomain -> HostName
showsPrec :: Int -> BindDomain -> ShowS
$cshowsPrec :: Int -> BindDomain -> ShowS
Show, BindDomain -> BindDomain -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BindDomain -> BindDomain -> Bool
$c/= :: BindDomain -> BindDomain -> Bool
== :: BindDomain -> BindDomain -> Bool
$c== :: BindDomain -> BindDomain -> Bool
Eq, Eq BindDomain
BindDomain -> BindDomain -> Bool
BindDomain -> BindDomain -> Ordering
BindDomain -> BindDomain -> BindDomain
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: BindDomain -> BindDomain -> BindDomain
$cmin :: BindDomain -> BindDomain -> BindDomain
max :: BindDomain -> BindDomain -> BindDomain
$cmax :: BindDomain -> BindDomain -> BindDomain
>= :: BindDomain -> BindDomain -> Bool
$c>= :: BindDomain -> BindDomain -> Bool
> :: BindDomain -> BindDomain -> Bool
$c> :: BindDomain -> BindDomain -> Bool
<= :: BindDomain -> BindDomain -> Bool
$c<= :: BindDomain -> BindDomain -> Bool
< :: BindDomain -> BindDomain -> Bool
$c< :: BindDomain -> BindDomain -> Bool
compare :: BindDomain -> BindDomain -> Ordering
$ccompare :: BindDomain -> BindDomain -> Ordering
Ord)

domainHostName :: BindDomain -> Maybe HostName
domainHostName :: BindDomain -> Maybe HostName
domainHostName (RelDomain HostName
d) = forall a. a -> Maybe a
Just HostName
d
domainHostName (AbsDomain HostName
d) = forall a. a -> Maybe a
Just HostName
d
domainHostName BindDomain
RootDomain = forall a. Maybe a
Nothing

newtype NamedConfMap = NamedConfMap (M.Map Domain NamedConf)
	deriving (NamedConfMap -> NamedConfMap -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NamedConfMap -> NamedConfMap -> Bool
$c/= :: NamedConfMap -> NamedConfMap -> Bool
== :: NamedConfMap -> NamedConfMap -> Bool
$c== :: NamedConfMap -> NamedConfMap -> Bool
Eq, Eq NamedConfMap
NamedConfMap -> NamedConfMap -> Bool
NamedConfMap -> NamedConfMap -> Ordering
NamedConfMap -> NamedConfMap -> NamedConfMap
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NamedConfMap -> NamedConfMap -> NamedConfMap
$cmin :: NamedConfMap -> NamedConfMap -> NamedConfMap
max :: NamedConfMap -> NamedConfMap -> NamedConfMap
$cmax :: NamedConfMap -> NamedConfMap -> NamedConfMap
>= :: NamedConfMap -> NamedConfMap -> Bool
$c>= :: NamedConfMap -> NamedConfMap -> Bool
> :: NamedConfMap -> NamedConfMap -> Bool
$c> :: NamedConfMap -> NamedConfMap -> Bool
<= :: NamedConfMap -> NamedConfMap -> Bool
$c<= :: NamedConfMap -> NamedConfMap -> Bool
< :: NamedConfMap -> NamedConfMap -> Bool
$c< :: NamedConfMap -> NamedConfMap -> Bool
compare :: NamedConfMap -> NamedConfMap -> Ordering
$ccompare :: NamedConfMap -> NamedConfMap -> Ordering
Ord, Int -> NamedConfMap -> ShowS
[NamedConfMap] -> ShowS
NamedConfMap -> HostName
forall a.
(Int -> a -> ShowS) -> (a -> HostName) -> ([a] -> ShowS) -> Show a
showList :: [NamedConfMap] -> ShowS
$cshowList :: [NamedConfMap] -> ShowS
show :: NamedConfMap -> HostName
$cshow :: NamedConfMap -> HostName
showsPrec :: Int -> NamedConfMap -> ShowS
$cshowsPrec :: Int -> NamedConfMap -> ShowS
Show, Typeable)

instance IsInfo NamedConfMap where
	propagateInfo :: NamedConfMap -> PropagateInfo
propagateInfo NamedConfMap
_ = Bool -> PropagateInfo
PropagateInfo Bool
False

-- | Adding a Master NamedConf stanza for a particular domain always
-- overrides an existing Secondary stanza for that domain, while a
-- Secondary stanza is only added when there is no existing Master stanza.
instance Sem.Semigroup NamedConfMap where
	NamedConfMap Map HostName NamedConf
old <> :: NamedConfMap -> NamedConfMap -> NamedConfMap
<> NamedConfMap Map HostName NamedConf
new = Map HostName NamedConf -> NamedConfMap
NamedConfMap forall a b. (a -> b) -> a -> b
$
		forall k a. Ord k => (a -> a -> a) -> Map k a -> Map k a -> Map k a
M.unionWith NamedConf -> NamedConf -> NamedConf
combiner Map HostName NamedConf
new Map HostName NamedConf
old
	  where
		combiner :: NamedConf -> NamedConf -> NamedConf
combiner NamedConf
n NamedConf
o = case (NamedConf -> DnsServerType
confDnsServerType NamedConf
n, NamedConf -> DnsServerType
confDnsServerType NamedConf
o) of
			(DnsServerType
Secondary, DnsServerType
Master) -> NamedConf
o
			(DnsServerType, DnsServerType)
_  -> NamedConf
n

instance Monoid NamedConfMap where
	mempty :: NamedConfMap
mempty = Map HostName NamedConf -> NamedConfMap
NamedConfMap forall k a. Map k a
M.empty
	mappend :: NamedConfMap -> NamedConfMap -> NamedConfMap
mappend = forall a. Semigroup a => a -> a -> a
(Sem.<>)

instance Empty NamedConfMap where
	isEmpty :: NamedConfMap -> Bool
isEmpty (NamedConfMap Map HostName NamedConf
m) = forall t. Empty t => t -> Bool
isEmpty Map HostName NamedConf
m

fromNamedConfMap :: NamedConfMap -> M.Map Domain NamedConf
fromNamedConfMap :: NamedConfMap -> Map HostName NamedConf
fromNamedConfMap (NamedConfMap Map HostName NamedConf
m) = Map HostName NamedConf
m