-zoneSOARecord :: Zone -> Maybe SomeRR
-zoneSOARecord zone
- = do soa <- zoneSOA zone
- return $ wrapRecord
- $ ResourceRecord {
- rrName = zoneName zone
- , rrType = SOA
- , rrClass = IN
- , rrTTL = soaMinimumTTL soa
- , rrData = soa
- }
-
-zoneNSRecord :: Zone -> Maybe SomeRR
-zoneNSRecord zone
- = do soa <- zoneSOA zone
- return $ wrapRecord
- $ ResourceRecord {
- rrName = zoneName zone
- , rrType = NS
- , rrClass = IN
- , rrTTL = soaMinimumTTL soa
- , rrData = soaMasterNameServer soa
- }
+
+wrapZone :: Zone z => z -> SomeZone
+wrapZone = SomeZone
+
+
+isAuthoritativeZone :: Zone z => z -> IO Bool
+isAuthoritativeZone z
+ = do let q = Question {
+ qName = zoneName z
+ , qType = SOA
+ , qClass = IN -- Should we consider any classes other than the Internet?
+ }
+ rs <- getRecords z q
+ case rs of
+ [] -> return False
+ _ -> return True
+
+
+getRecords :: (QueryType qt, QueryClass qc, Zone z) =>
+ z
+ -> Question qt qc
+ -> IO [SomeRR]
+getRecords z q
+ | cast (qType q) == Just AXFR
+ = getRecordsForAXFR
+
+ | otherwise
+ = do rs <- getRecordsForName z (qName q)
+ return $ filterRecords q rs
+
+ where
+ getRecordsForAXFR
+ | qName q == zoneName z
+ = do names <- getRecordNames z
+ (soaM, rs) <- liftM (spitSOA . concat) $ mapM (getRecordsForName z) names
+ case soaM of
+ Just soa -> return ([soa] ++ rs ++ [soa])
+ Nothing -> return []
+ | otherwise
+ = return []
+
+ spitSOA :: [SomeRR] -> (Maybe SomeRR, [SomeRR])
+ spitSOA xs = (findSOA xs, collectNonSOA xs)
+
+ findSOA :: [SomeRR] -> Maybe SomeRR
+ findSOA [] = Nothing
+ findSOA (SomeRR x : xs)
+ | typeOf (rrType x) == typeOf SOA = Just (SomeRR x)
+ | otherwise = findSOA xs
+
+ collectNonSOA :: [SomeRR] -> [SomeRR]
+ collectNonSOA [] = []
+ collectNonSOA (SomeRR x : xs)
+ | typeOf (rrType x) == typeOf SOA = collectNonSOA xs
+ | otherwise = SomeRR x : collectNonSOA xs
+
+
+filterRecords :: (QueryType qt, QueryClass qc) =>
+ Question qt qc
+ -> [SomeRR]
+ -> [SomeRR]
+filterRecords q = filter predicate
+ where
+ predicate rr
+ = predForType rr && predForClass rr
+
+ predForType (SomeRR rr)
+ | typeOf (qType q) == typeOf ANY
+ = True
+
+ | typeOf (qType q) == typeOf MAILB
+ = typeOf (rrType rr) == typeOf MR ||
+ typeOf (rrType rr) == typeOf MB ||
+ typeOf (rrType rr) == typeOf MG ||
+ typeOf (rrType rr) == typeOf MINFO
+
+ | otherwise
+ = typeOf (rrType rr) == typeOf (qType q) ||
+ typeOf (rrType rr) == typeOf CNAME
+
+ predForClass (SomeRR rr)
+ | typeOf (qClass q) == typeOf ANY
+ = True
+
+ | otherwise
+ = typeOf (rrClass rr) == typeOf (qClass q)