IRR Database¶
The Internet Routing Registry (IRR) is a distributed database of routing policy information. APNIC publishes IRR database dumps containing RPSL (Routing Policy Specification Language) objects for 19 different object types.
flowchart TB
subgraph IRR_Download["IRR Database Dump"]
Fetch["FetchIRRDatabase(ctx, objType)"]
URL["ftp.apnic.net/apnic/whois/<br/>apnic.db.TYPE.gz"]
Decompress["Transparent gzip<br/>decompression"]
Parse["RPSL Parser"]
end
subgraph Objects["IRR Objects"]
Obj1["IRRObject 1<br/>Type: inetnum<br/>PK: 203.0.113.0 - 203.0.113.255"]
Obj2["IRRObject 2<br/>Type: route<br/>PK: 203.0.113.0/24"]
ObjN["..."]
end
subgraph Result["IRRDatabase"]
Type["Type: \"inetnum\""]
ObjList["Objects: []IRRObject"]
end
Fetch --> URL --> Decompress --> Parse
Parse --> Obj1 --> ObjList
Parse --> Obj2 --> ObjList
Parse --> ObjN --> ObjList
Type --> Result
ObjList --> Result Methods¶
| Method | Description |
|---|---|
FetchIRRDatabase(ctx, objType) | Fetch and parse IRR dump for a specific object type |
GetIRRDatabase(ctx, objType) | Cached IRR database dump |
FetchIRRCurrentSerial(ctx) | Fetch APNIC.CURRENTSERIAL (current IRR serial number) |
Object Types (19)¶
flowchart TB
subgraph Network["Network Objects"]
inetnum["inetnum<br/>IPv4 allocation"]
inet6num["inet6num<br/>IPv6 allocation"]
route["route<br/>IPv4 prefix"]
route6["route6<br/>IPv6 prefix"]
autnum["aut-num<br/>Autonomous System"]
end
subgraph Routing["Routing Policy Objects"]
as_set["as-set<br/>AS group"]
route_set["route-set<br/>Prefix group"]
peering_set["peering-set<br/>Peering config"]
filter_set["filter-set<br/>Filter rules"]
rtr_set["rtr-set<br/>Router group"]
inet_rtr["inet-rtr<br/>Router definition"]
end
subgraph Organizational["Organizational Objects"]
organisation["organisation<br/>Entity info"]
role["role<br/>Contact role"]
irt["irt<br/>Incident Response Team"]
mntner["mntner<br/>Maintainer"]
key_cert["key-cert<br/>PGP key"]
end
subgraph DNS["DNS Objects"]
domain["domain<br/>Reverse DNS delegation"]
limerick["limerick<br/>Documentation"]
end IRRObjectTypes List¶
var IRRObjectTypes = []string{
"as-block",
"as-set",
"aut-num",
"domain",
"filter-set",
"inet6num",
"inetnum",
"inet-rtr",
"irt",
"key-cert",
"limerick",
"mntner",
"organisation",
"peering-set",
"role",
"route",
"route6",
"route-set",
"rtr-set",
}
Domain Type and Reverse DNS¶
The domain object type is particularly important for reverse DNS delegation:
flowchart LR
subgraph Domain["domain Object"]
Name["domain: 0.0.1.in-addr.arpa"]
NS["nserver: ns1.example.com"]
NS2["nserver: ns2.example.com"]
ZoneC["zone-c: ADMIN-HANDLE"]
end
subgraph Meaning["Purpose"]
Delegate["Delegates reverse DNS<br/>for 1.0.0.0/8"]
NSRec["Specifies nameservers<br/>for PTR queries"]
end
Domain --> Meaning Examples¶
Fetch inetnum Objects¶
package main
import (
"context"
"fmt"
"log"
apnic "github.com/cyberspacesec/apnic-skills"
)
func main() {
client := apnic.NewClient()
ctx := context.Background()
// Fetch inetnum (IPv4 allocation) objects
db, err := client.FetchIRRDatabase(ctx, "inetnum")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total inetnum objects: %d\n", len(db.Objects))
// Show first few objects
for i, obj := range db.Objects {
if i >= 3 {
break
}
fmt.Printf("\nObject %d:\n", i+1)
fmt.Printf(" Primary Key: %s\n", obj.PrimaryKey)
for key, values := range obj.Attributes {
fmt.Printf(" %s: %v\n", key, values)
}
}
}
Fetch route Objects¶
package main
import (
"context"
"fmt"
"log"
apnic "github.com/cyberspacesec/apnic-skills"
)
func main() {
client := apnic.NewClient()
ctx := context.Background()
// Fetch route objects
db, err := client.FetchIRRDatabase(ctx, "route")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total route objects: %d\n", len(db.Objects))
// Find routes with specific origin
for _, obj := range db.Objects {
if origins, ok := obj.Attributes["origin"]; ok {
for _, origin := range origins {
if origin == "AS13335" {
fmt.Printf("Route: %s -> %s\n", obj.PrimaryKey, origin)
}
}
}
}
}
Fetch aut-num (ASN) Objects¶
package main
import (
"context"
"fmt"
"log"
apnic "github.com/cyberspacesec/apnic-skills"
)
func main() {
client := apnic.NewClient()
ctx := context.Background()
// Fetch aut-num (ASN) objects
db, err := client.FetchIRRDatabase(ctx, "aut-num")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total aut-num objects: %d\n", len(db.Objects))
// Print some ASNs
for i, obj := range db.Objects {
if i >= 5 {
break
}
fmt.Printf("ASN: %s\n", obj.PrimaryKey)
if names, ok := obj.Attributes["as-name"]; ok {
fmt.Printf(" Name: %s\n", names[0])
}
if descrs, ok := obj.Attributes["descr"]; ok {
fmt.Printf(" Description: %s\n", descrs[0])
}
}
}
Fetch domain Objects (Reverse DNS Delegation)¶
package main
import (
"context"
"fmt"
"log"
apnic "github.com/cyberspacesec/apnic-skills"
)
func main() {
client := apnic.NewClient()
ctx := context.Background()
// Fetch domain objects (reverse DNS delegation)
db, err := client.FetchIRRDatabase(ctx, "domain")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total domain objects: %d\n", len(db.Objects))
// Show some reverse DNS delegations
for i, obj := range db.Objects {
if i >= 5 {
break
}
fmt.Printf("\nDomain: %s\n", obj.PrimaryKey)
if nss, ok := obj.Attributes["nserver"]; ok {
fmt.Printf(" Nameservers:\n")
for _, ns := range nss {
fmt.Printf(" - %s\n", ns)
}
}
}
}
Get Current IRR Serial¶
package main
import (
"context"
"fmt"
"log"
apnic "github.com/cyberspacesec/apnic-skills"
)
func main() {
client := apnic.NewClient()
ctx := context.Background()
serial, err := client.FetchIRRCurrentSerial(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Current IRR serial: %d\n", serial)
}
Using Cached IRR Data¶
package main
import (
"context"
"fmt"
apnic "github.com/cyberspacesec/apnic-skills"
)
func main() {
client := apnic.NewClient()
ctx := context.Background()
// First call fetches from network
db1, _ := client.FetchIRRDatabase(ctx, "route")
fmt.Printf("First fetch: %d objects\n", len(db1.Objects))
// Subsequent Get call uses cache (if within TTL)
db2, err := client.GetIRRDatabase(ctx, "route")
if err != nil {
fmt.Printf("Cache miss or expired\n")
} else {
fmt.Printf("From cache: %d objects\n", len(db2.Objects))
}
}
Data Structures¶
IRRDatabase¶
type IRRDatabase struct {
Type string // Object type (e.g., "inetnum")
Objects []IRRObject // Parsed RPSL objects
}
type IRRObject struct {
Type string // Object type
PrimaryKey string // Primary key value
Attributes map[string][]string // All attributes (key -> values)
}
RPSL Parsing¶
The SDK handles RPSL format specifics:
- Blank lines separate objects
- Comment lines (
#) are skipped - Continuation lines (leading whitespace or
+) are folded into the preceding attribute - Multi-valued attributes are collected in a slice
inetnum: 203.0.113.0 - 203.0.113.255
netname: EXAMPLE-NET
descr: Example Network
descr: Additional description line
country: AU
admin-c: ADMIN-HANDLE
tech-c: TECH-HANDLE
mnt-by: MAINT-EXAMPLE
changed: admin@example.com 20240101
source: APNIC
Error Handling¶
db, err := client.FetchIRRDatabase(ctx, "inetnum")
if err != nil {
// Possible errors:
// - ErrInvalidIRRType: unknown object type
// - Network timeout
// - Decompression failure
// - Parse error
log.Printf("IRR fetch failed: %v", err)
return
}
Large File Handling¶
IRR dumps can be large (e.g., apnic.db.inetnum.gz is 50MB+). The SDK handles this through:
- Transparent decompression: gzip is handled automatically
- Chunked download: Multi-connection download for large files
- Streaming parser: Memory-efficient parsing without loading entire file