%% dnsrecord.sty %% Copyright 2026 Vahid Shaik %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3c %% of this license or (at your option) any later version. %% The latest version of this license is in %% https://www.latex-project.org/lppl.txt %% and version 1.3c or later is part of all distributions of LaTeX %% version 2008 or later. %% %% This work has the LPPL maintenance status `maintained'. %% The Current Maintainer of this work is Vahid Shaik. %% %% Homepage: https://dnsrobot.net %% Repository: https://github.com/dnsrobot/latex-dnsrecord %% \NeedsTeXFormat{LaTeX2e}[2020/10/01] \ProvidesPackage{dnsrecord}[2026/03/09 v1.0.0 Typeset DNS records in LaTeX documents] % Required packages \RequirePackage{booktabs} \RequirePackage{xcolor} \RequirePackage{xparse} \RequirePackage{etoolbox} \RequirePackage{amsmath} % ============================================================ % Color definitions for DNS record types % ============================================================ \definecolor{dns@a}{HTML}{2563EB} \definecolor{dns@aaaa}{HTML}{7C3AED} \definecolor{dns@cname}{HTML}{059669} \definecolor{dns@mx}{HTML}{DC2626} \definecolor{dns@ns}{HTML}{D97706} \definecolor{dns@txt}{HTML}{4B5563} \definecolor{dns@soa}{HTML}{BE185D} \definecolor{dns@ptr}{HTML}{0891B2} \definecolor{dns@srv}{HTML}{4338CA} \definecolor{dns@caa}{HTML}{B45309} \definecolor{dns@dnskey}{HTML}{1D4ED8} \definecolor{dns@ds}{HTML}{6D28D9} \definecolor{dns@rrsig}{HTML}{9333EA} \definecolor{dns@nsec}{HTML}{065F46} \definecolor{dns@nsec3}{HTML}{047857} \definecolor{dns@tlsa}{HTML}{7E22CE} \definecolor{dns@spf}{HTML}{B91C1C} \definecolor{dns@dkim}{HTML}{92400E} \definecolor{dns@dmarc}{HTML}{9F1239} \definecolor{dns@https}{HTML}{0E7490} \definecolor{dns@svcb}{HTML}{155E75} \definecolor{dns@default}{HTML}{374151} % Propagation status colors \definecolor{dns@propagated}{HTML}{059669} \definecolor{dns@pending}{HTML}{D97706} \definecolor{dns@failed}{HTML}{DC2626} \definecolor{dns@timeout}{HTML}{6B7280} % Health check colors \definecolor{dns@healthy}{HTML}{059669} \definecolor{dns@warning}{HTML}{D97706} \definecolor{dns@critical}{HTML}{DC2626} \definecolor{dns@info}{HTML}{2563EB} % Background colors for boxed records \definecolor{dns@boxbg}{HTML}{F9FAFB} \definecolor{dns@boxborder}{HTML}{E5E7EB} % ============================================================ % Options % ============================================================ \newif\ifdns@usecolor \dns@usecolortrue \newif\ifdns@mono \dns@monotrue \newif\ifdns@showttl \dns@showttltrue \newif\ifdns@showclass \dns@showclassfalse \newif\ifdns@compact \dns@compactfalse \newif\ifdns@boxed \dns@boxedfalse \DeclareOption{color}{\dns@usecolortrue} \DeclareOption{nocolor}{\dns@usecolorfalse} \DeclareOption{monospace}{\dns@monotrue} \DeclareOption{nomonospace}{\dns@monofalse} \DeclareOption{ttl}{\dns@showttltrue} \DeclareOption{nottl}{\dns@showttlfalse} \DeclareOption{class}{\dns@showclasstrue} \DeclareOption{noclass}{\dns@showclassfalse} \DeclareOption{compact}{\dns@compacttrue} \DeclareOption{boxed}{\dns@boxedtrue} \ProcessOptions\relax % ============================================================ % Internal helpers % ============================================================ \newcommand{\dns@getcolor}[1]{% \ifdns@usecolor \@ifundefined{color@dns@\MakeLowercase{#1}}% {\color{dns@default}}% {\color{dns@\MakeLowercase{#1}}}% \fi } \newcommand{\dns@fmt}[1]{% \ifdns@mono\texttt{#1}\else#1\fi } \newcommand{\dns@badge}[1]{% {\dns@getcolor{#1}\textbf{\dns@fmt{\MakeUppercase{#1}}}}% } % Colored box around text \newcommand{\dns@colorbox}[2]{% \ifdns@usecolor \fcolorbox{dns@boxborder}{dns@boxbg}{{\dns@getcolor{#1}\textbf{\dns@fmt{\MakeUppercase{#1}}}}\ #2}% \else \fbox{\textbf{\dns@fmt{\MakeUppercase{#1}}}\ #2}% \fi } % ============================================================ % Section 1: Inline DNS record commands % ============================================================ % \dnsrecord{type}{name}{value}[ttl] \NewDocumentCommand{\dnsrecord}{m m m O{}}{% \ifdns@boxed \dns@colorbox{#1}{\dns@fmt{#2} \textrightarrow\ \dns@fmt{#3}% \ifblank{#4}{}{\ifdns@showttl\ {\footnotesize TTL\,\dns@fmt{#4}}\fi}}% \else \dns@badge{#1}% \enspace\dns@fmt{#2}% \enspace\textrightarrow\enspace\dns@fmt{#3}% \ifdns@showclass\enspace{\footnotesize IN}\fi% \ifblank{#4}{}{\ifdns@showttl\enspace{\footnotesize TTL\,\dns@fmt{#4}}\fi}% \fi } % Standard record type shorthands \NewDocumentCommand{\dnsA}{m m O{}}{\dnsrecord{A}{#1}{#2}[#3]} \NewDocumentCommand{\dnsAAAA}{m m O{}}{\dnsrecord{AAAA}{#1}{#2}[#3]} \NewDocumentCommand{\dnsCNAME}{m m O{}}{\dnsrecord{CNAME}{#1}{#2}[#3]} \NewDocumentCommand{\dnsMX}{m m m O{}}{\dnsrecord{MX}{#1}{#3 (pri #2)}[#4]} \NewDocumentCommand{\dnsNS}{m m O{}}{\dnsrecord{NS}{#1}{#2}[#3]} \NewDocumentCommand{\dnsTXT}{m m O{}}{\dnsrecord{TXT}{#1}{"#2"}[#3]} \NewDocumentCommand{\dnsSOA}{m m m O{}}{\dnsrecord{SOA}{#1}{#2 (#3)}[#4]} \NewDocumentCommand{\dnsPTR}{m m O{}}{\dnsrecord{PTR}{#1}{#2}[#3]} \NewDocumentCommand{\dnsSRV}{m m m m O{}}{\dnsrecord{SRV}{#1}{#3:#4 (pri #2)}[#5]} \NewDocumentCommand{\dnsCAA}{m m m O{}}{\dnsrecord{CAA}{#1}{#2 #3}[#4]} % DNSSEC record type shorthands \NewDocumentCommand{\dnsDNSKEY}{m m O{}}{\dnsrecord{DNSKEY}{#1}{#2}[#3]} \NewDocumentCommand{\dnsDS}{m m O{}}{\dnsrecord{DS}{#1}{#2}[#3]} \NewDocumentCommand{\dnsRRSIG}{m m O{}}{\dnsrecord{RRSIG}{#1}{#2}[#3]} \NewDocumentCommand{\dnsNSEC}{m m O{}}{\dnsrecord{NSEC}{#1}{#2}[#3]} \NewDocumentCommand{\dnsNSEC3}{m m O{}}{\dnsrecord{NSEC3}{#1}{#2}[#3]} % Modern record type shorthands \NewDocumentCommand{\dnsTLSA}{m m O{}}{\dnsrecord{TLSA}{#1}{#2}[#3]} \NewDocumentCommand{\dnsHTTPS}{m m O{}}{\dnsrecord{HTTPS}{#1}{#2}[#3]} \NewDocumentCommand{\dnsSVCB}{m m O{}}{\dnsrecord{SVCB}{#1}{#2}[#3]} % Email authentication shorthands \NewDocumentCommand{\dnsSPF}{m m O{}}{\dnsrecord{SPF}{#1}{#2}[#3]} \NewDocumentCommand{\dnsDKIM}{m m O{}}{\dnsrecord{DKIM}{#1}{#2}[#3]} \NewDocumentCommand{\dnsDMARC}{m m O{}}{\dnsrecord{DMARC}{#1}{#2}[#3]} % ============================================================ % Section 2: DNS zone table environment % ============================================================ \newcounter{dns@entrycount} \NewDocumentEnvironment{dnszone}{m}{% \setcounter{dns@entrycount}{0}% \def\dns@zonedomain{#1}% \ifdns@showclass \begin{tabular}{@{} l l l l l @{}} \else \begin{tabular}{@{} l l l l @{}} \fi \toprule \textbf{Type} & \textbf{Name} & \textbf{Value} \ifdns@showclass & \textbf{Class}\fi \ifdns@showttl & \textbf{TTL}\fi \\ \midrule }{% \bottomrule \ifdns@showclass \end{tabular} \else \end{tabular} \fi \par\smallskip {\footnotesize\textit{DNS zone: \dns@fmt{\dns@zonedomain} --- \arabic{dns@entrycount} records}}% } \NewDocumentCommand{\dnsentry}{m m m O{}}{% \stepcounter{dns@entrycount}% \dns@badge{#1} & \dns@fmt{#2} & \dns@fmt{#3} \ifdns@showclass & IN\fi \ifdns@showttl & \ifblank{#4}{---}{\dns@fmt{#4}}\fi \\ } % ============================================================ % Section 3: DNS propagation table environment % ============================================================ \NewDocumentEnvironment{dnspropagation}{m m}{% \def\dns@propdomain{#1}% \def\dns@proptype{#2}% \begin{tabular}{@{} l l l l l @{}} \toprule \textbf{Server} & \textbf{IP} & \textbf{Result} & \textbf{RTT} & \textbf{Status} \\ \midrule }{% \bottomrule \end{tabular} \par\smallskip {\footnotesize\textit{Propagation check: \dns@badge{\dns@proptype} record for \dns@fmt{\dns@propdomain}}}% } \NewDocumentCommand{\dnsstatus}{m}{% \ifstrequal{#1}{propagated}{{\color{dns@propagated}\textbullet\ Propagated}}{}% \ifstrequal{#1}{pending}{{\color{dns@pending}\textbullet\ Pending}}{}% \ifstrequal{#1}{failed}{{\color{dns@failed}\textbullet\ Failed}}{}% \ifstrequal{#1}{timeout}{{\color{dns@timeout}\textbullet\ Timeout}}{}% } \NewDocumentCommand{\dnsserver}{m m m m m}{% \dns@fmt{#1} & \dns@fmt{#2} & \dns@fmt{#3} & \dns@fmt{#4} & \dnsstatus{#5} \\ } % ============================================================ % Section 4: DNSSEC validation display % ============================================================ \NewDocumentCommand{\dnssec}{m}{% \ifstrequal{#1}{valid}{{\color{dns@propagated}\textbf{DNSSEC:} Validated}}{}% \ifstrequal{#1}{invalid}{{\color{dns@failed}\textbf{DNSSEC:} Validation Failed}}{}% \ifstrequal{#1}{unsigned}{{\color{dns@pending}\textbf{DNSSEC:} Not Signed}}{}% \ifstrequal{#1}{insecure}{{\color{dns@timeout}\textbf{DNSSEC:} Insecure Delegation}}{}% } % DNSSEC chain of trust table \NewDocumentEnvironment{dnssecchain}{m}{% \def\dns@secdomain{#1}% \begin{tabular}{@{} l l l l @{}} \toprule \textbf{Zone} & \textbf{Record} & \textbf{Key Tag} & \textbf{Algorithm} \\ \midrule }{% \bottomrule \end{tabular} \par\smallskip {\footnotesize\textit{DNSSEC chain of trust for \dns@fmt{\dns@secdomain}}}% } \NewDocumentCommand{\dnssecentry}{m m m m}{% \dns@fmt{#1} & \dns@badge{#2} & \dns@fmt{#3} & \dns@fmt{#4} \\ } % ============================================================ % Section 5: DNS health check environment % ============================================================ \NewDocumentCommand{\dnshealth}{m m}{% \ifstrequal{#1}{healthy}{{\color{dns@healthy}\textbullet\ \textbf{PASS:}} #2}{}% \ifstrequal{#1}{warning}{{\color{dns@warning}\textbullet\ \textbf{WARN:}} #2}{}% \ifstrequal{#1}{critical}{{\color{dns@critical}\textbullet\ \textbf{FAIL:}} #2}{}% \ifstrequal{#1}{info}{{\color{dns@info}\textbullet\ \textbf{INFO:}} #2}{}% } \NewDocumentEnvironment{dnshealthcheck}{m}{% \def\dns@healthdomain{#1}% \par\medskip {\large\textbf{DNS Health Check:} \dns@fmt{#1}}\par\smallskip \begin{list}{}{\setlength{\leftmargin}{1em}\setlength{\itemsep}{2pt}}% }{% \end{list}% \par } \NewDocumentCommand{\dnshealthitem}{m m}{% \item \dnshealth{#1}{#2}% } % ============================================================ % Section 6: Email authentication summary % ============================================================ \NewDocumentEnvironment{dnsemailauth}{m}{% \def\dns@emaildomain{#1}% \begin{tabular}{@{} l l l l @{}} \toprule \textbf{Protocol} & \textbf{Record} & \textbf{Policy} & \textbf{Status} \\ \midrule }{% \bottomrule \end{tabular} \par\smallskip {\footnotesize\textit{Email authentication for \dns@fmt{\dns@emaildomain}}}% } \NewDocumentCommand{\dnsemailentry}{m m m m}{% \dns@badge{#1} & \dns@fmt{#2} & \dns@fmt{#3} & \dnsstatus{#4} \\ } % ============================================================ % Section 7: DNS response time comparison % ============================================================ \NewDocumentEnvironment{dnslatency}{m}{% \def\dns@latencydomain{#1}% \begin{tabular}{@{} l l r r r @{}} \toprule \textbf{Resolver} & \textbf{IP} & \textbf{Min (ms)} & \textbf{Avg (ms)} & \textbf{Max (ms)} \\ \midrule }{% \bottomrule \end{tabular} \par\smallskip {\footnotesize\textit{DNS latency for \dns@fmt{\dns@latencydomain}}}% } \NewDocumentCommand{\dnslatencyentry}{m m m m m}{% \dns@fmt{#1} & \dns@fmt{#2} & #3 & #4 & #5 \\ } % ============================================================ % Section 8: TTL timeline visualization (text-based) % ============================================================ \newcommand{\dnsttlbar}[3]{% % #1 = label, #2 = TTL value, #3 = max TTL for scale \dns@fmt{#1}\enspace% {\color{dns@a}\rule{\dimexpr#2pt*200/#3\relax}{8pt}}% \enspace{\footnotesize\dns@fmt{#2}s}% } % ============================================================ % Section 9: Comparison table for DNS providers % ============================================================ \NewDocumentEnvironment{dnsproviders}{}{% \begin{tabular}{@{} l l l l l @{}} \toprule \textbf{Provider} & \textbf{Primary} & \textbf{Secondary} & \textbf{DNSSEC} & \textbf{DoH/DoT} \\ \midrule }{% \bottomrule \end{tabular} } \NewDocumentCommand{\dnsprovider}{m m m m m}{% \textbf{#1} & \dns@fmt{#2} & \dns@fmt{#3} & #4 & #5 \\ } % ============================================================ % Section 10: Utility commands % ============================================================ % Domain name formatting \NewDocumentCommand{\dnsdomain}{m}{\dns@fmt{#1}} % IP address formatting \NewDocumentCommand{\dnsip}{m}{\dns@fmt{#1}} % TTL value with human-readable conversion \NewDocumentCommand{\dnsttl}{m}{% \dns@fmt{#1}% \ifnum#1>86399\enspace(\the\numexpr#1/86400\relax d)\fi \ifnum#1<86400\ifnum#1>3599\enspace(\the\numexpr#1/3600\relax h)\fi\fi \ifnum#1<3600\ifnum#1>59\enspace(\the\numexpr#1/60\relax m)\fi\fi \ifnum#1<60\enspace(#1s)\fi } % Record class \NewDocumentCommand{\dnsclass}{m}{\dns@fmt{\MakeUppercase{#1}}} % RCODE formatting \NewDocumentCommand{\dnsrcode}{m}{% \ifstrequal{#1}{NOERROR}{{\color{dns@propagated}\dns@fmt{NOERROR}}}{}% \ifstrequal{#1}{NXDOMAIN}{{\color{dns@failed}\dns@fmt{NXDOMAIN}}}{}% \ifstrequal{#1}{SERVFAIL}{{\color{dns@failed}\dns@fmt{SERVFAIL}}}{}% \ifstrequal{#1}{REFUSED}{{\color{dns@warning}\dns@fmt{REFUSED}}}{}% \ifstrequal{#1}{FORMERR}{{\color{dns@warning}\dns@fmt{FORMERR}}}{}% } % DNS flag formatting \NewDocumentCommand{\dnsflag}{ m }{% \fbox{\footnotesize\dns@fmt{\MakeUppercase{#1}}}% } % Query/Response header \NewDocumentCommand{\dnsheader}{m m m m}{% % #1=id, #2=opcode, #3=rcode, #4=flags \par\smallskip \dns@fmt{;; HEADER: id=#1, opcode=#2, rcode=}\dnsrcode{#3}\dns@fmt{, flags=#4}% \par\smallskip } \endinput