---
title: SAIF.Framework.DNS business rules
summary: Enumerated business rules with per-rule trigger, enforcement, and outcomes.
status: draft
owner: <owner>
last_reviewed: 2026-07-23
library: SAIF.Framework.DNS
reference_type: package
---

# SAIF.Framework.DNS business rules

This page captures business rules enforced by this library.

## BR-001: Lookup arguments must not be null

| Field | Value |
| --- | --- |
| **Statement** | The `domain` and `dnsServer` arguments must not be null for any public lookup call. |
| **Trigger** | Call to `Resolver.MXLookup(domain, dnsServer)` or `Resolver.Lookup(request, dnsServer)`. |
| **Enforcement** | Explicit null checks at the start of each method, throwing `ArgumentNullException`. |
| **Outcome** | Prevents null-reference failures downstream in socket/message construction code. |
| **Confidence** | Verified |
| **Source** | SAIF.Framework.DNS\Resolver.cs |

---

## BR-002: Domain name length must be 1-255 characters

| Field | Value |
| --- | --- |
| **Statement** | A domain name supplied to the public `Question` constructor must be between 1 and 255 characters. |
| **Trigger** | `Question(string domain, DnsType dnsType, DnsClass dnsClass)` constructor invoked. |
| **Enforcement** | Length check in the constructor throwing `ArgumentException` when violated; a per-label 63-character regex check exists in source but is commented out and not enforced. |
| **Outcome** | Rejects domain strings that violate the RFC1035 overall length limit before a `Question` object is created. |
| **Confidence** | Verified |
| **Source** | SAIF.Framework.DNS\Question.cs |

---

## BR-003: DnsType must be a defined, non-None enum value

| Field | Value |
| --- | --- |
| **Statement** | The `DnsType` supplied to the public `Question` constructor must be a defined enum value other than `None`. |
| **Trigger** | `Question` public constructor invoked with a `DnsType` argument. |
| **Enforcement** | `Enum.IsDefined` check in the constructor throwing `ArgumentOutOfRangeException` when violated. |
| **Outcome** | Rejects invalid or undefined query types before a `Question` object is created. |
| **Confidence** | Verified |
| **Source** | SAIF.Framework.DNS\Question.cs |

---

## BR-004: DnsClass must be a defined, non-None enum value

| Field | Value |
| --- | --- |
| **Statement** | The `DnsClass` supplied to the public `Question` constructor must be a defined enum value other than `None`. |
| **Trigger** | `Question` public constructor invoked with a `DnsClass` argument. |
| **Enforcement** | `Enum.IsDefined` check in the constructor throwing `ArgumentOutOfRangeException` when violated. |
| **Outcome** | Rejects invalid or undefined query classes before a `Question` object is created. |
| **Confidence** | Verified |
| **Source** | SAIF.Framework.DNS\Question.cs |

---

## BR-005: UDP requests are retried up to two additional times before failing

| Field | Value |
| --- | --- |
| **Statement** | A DNS UDP request is retried up to 2 additional times before the operation is considered failed. |
| **Trigger** | No matching-id response is received within the 1-second receive timeout on a given attempt. |
| **Enforcement** | `Resolver.UdpTransfer` retry loop, bounded by the constant `_udpRetryAttempts` (2). |
| **Outcome** | After exhausting all attempts, `NoResponseException` is thrown to the caller. |
| **Confidence** | Verified |
| **Source** | SAIF.Framework.DNS\Resolver.cs |

---

## BR-006: UDP replies are only accepted when the transaction id matches

| Field | Value |
| --- | --- |
| **Statement** | A returned UDP datagram is only accepted as a valid reply if its 2-byte transaction id matches the request's stamped id. |
| **Trigger** | Every UDP receive performed inside `Resolver.UdpTransfer`. |
| **Enforcement** | Byte-level comparison of `responseMessage[0..1]` against `requestMessage[0..1]`. |
| **Outcome** | Mismatched or unrelated packets are ignored, which implicitly drives the retry loop (see [BR-005](#br-005-udp-requests-are-retried-up-to-two-additional-times-before-failing)). |
| **Confidence** | Verified |
| **Source** | SAIF.Framework.DNS\Resolver.cs |

---

## BR-007: Malformed embedded questions abort response construction

| Field | Value |
| --- | --- |
| **Statement** | A malformed embedded `Question` encountered while parsing the questions section of a reply aborts construction of the entire `Response`. |
| **Trigger** | `Response` constructor parsing the questions section of a raw reply. |
| **Enforcement** | `try`/`catch` around `new Question(pointer)`; any caught exception is rethrown as `InvalidResponseException`. |
| **Outcome** | The caller receives a clear, typed exception instead of a partially-parsed or corrupt `Response` object. |
| **Confidence** | Verified |
| **Source** | SAIF.Framework.DNS\Response.cs |

---

## BR-008: MX records are ordered by ascending preference

| Field | Value |
| --- | --- |
| **Statement** | MX records are ordered by ascending preference (a lower numeric value indicates higher priority), tie-broken by descending domain-name comparison. |
| **Trigger** | `Resolver.MXLookup` return path, or any `Array.Sort` performed over an `MXRecord[]`. |
| **Enforcement** | `MXRecord.CompareTo` (`IComparable` implementation). |
| **Outcome** | Callers iterating the returned array process the most-preferred mail exchanger first. |
| **Confidence** | Verified |
| **Source** | SAIF.Framework.DNS\MXRecord.cs |

## Notes
- Rule enforcement in this library is entirely input-validation and transport-retry logic; no persistence, workflow, or authorization rules apply, consistent with this library performing no database or security interactions.
- The per-label 63-character domain validation described in `Question.cs` exists only as a commented-out `Regex.IsMatch` call and is not currently enforced; whether this was an intentional relaxation or an oversight is unknown.**

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Configuration](configuration.md)
- [API reference](api/index.md)

> **Note:** Statements marked with ** could not be confirmed; treat as unknown until verified.

## Sources
- SAIF.Framework.DNS\Resolver.cs
- SAIF.Framework.DNS\Question.cs
- SAIF.Framework.DNS\Response.cs
- SAIF.Framework.DNS\MXRecord.cs
