check / check (push) Canceled after 0s
The IP lookups, the AS and prefix pages and their API answers, the prefix-length pages and the stats read routes only from the routing table the prefix handler keeps. fx reads the table at startup and gives it to both. AS names, WHOIS details and first-seen times still come from the database. The IP lookup names the origin AS most peers carry, with the time of the newest kept route. The prefix answers list peers whose routes are not kept without a path or time. The stats gain origins_without_kept_route. They no longer read route times from the per-peer tables, so the two helpers that did are gone. Model: opus-5-5
176 lines
5.6 KiB
Go
176 lines
5.6 KiB
Go
package database
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// ASN represents an Autonomous System Number with its metadata including
|
|
// handle, description, WHOIS data, and first/last seen timestamps.
|
|
//
|
|
//nolint:tagliatelle // field names are the existing JSON API
|
|
type ASN struct {
|
|
ASN int `json:"asn"`
|
|
Handle string `json:"handle"`
|
|
Description string `json:"description"`
|
|
// WHOIS parsed fields
|
|
ASName string `json:"as_name,omitempty"`
|
|
OrgName string `json:"org_name,omitempty"`
|
|
OrgID string `json:"org_id,omitempty"`
|
|
Address string `json:"address,omitempty"`
|
|
CountryCode string `json:"country_code,omitempty"`
|
|
AbuseEmail string `json:"abuse_email,omitempty"`
|
|
AbusePhone string `json:"abuse_phone,omitempty"`
|
|
TechEmail string `json:"tech_email,omitempty"`
|
|
TechPhone string `json:"tech_phone,omitempty"`
|
|
RIR string `json:"rir,omitempty"` // ARIN, RIPE, APNIC, LACNIC, AFRINIC
|
|
RIRRegDate *time.Time `json:"rir_registration_date,omitempty"`
|
|
RIRLastMod *time.Time `json:"rir_last_modified,omitempty"`
|
|
WHOISRaw string `json:"whois_raw,omitempty"`
|
|
// Timestamps. They are zero, and left out of JSON, for an AS that has no
|
|
// record in the asns table.
|
|
FirstSeen time.Time `json:"first_seen,omitzero"`
|
|
LastSeen time.Time `json:"last_seen,omitzero"`
|
|
WHOISUpdatedAt *time.Time `json:"whois_updated_at,omitempty"`
|
|
}
|
|
|
|
// Prefix represents an IP prefix (CIDR block) with its IP version (4 or 6)
|
|
// and the time it was first seen.
|
|
type Prefix struct {
|
|
Prefix string
|
|
IPVersion int // 4 or 6
|
|
FirstSeen time.Time
|
|
}
|
|
|
|
// Announcement represents a BGP announcement or withdrawal event,
|
|
// containing the prefix, AS path, origin ASN, peer ASN, next hop, and timestamp.
|
|
type Announcement struct {
|
|
ID uuid.UUID
|
|
PrefixID uuid.UUID
|
|
PeerASN int
|
|
OriginASN int
|
|
Path string // JSON-encoded AS path
|
|
NextHop string
|
|
Timestamp time.Time
|
|
IsWithdrawal bool
|
|
}
|
|
|
|
// ASNPeering represents a peering relationship between two ASNs,
|
|
// stored with the lower ASN as ASA and the higher as ASB.
|
|
type ASNPeering struct {
|
|
ID uuid.UUID
|
|
ASA int
|
|
ASB int
|
|
FirstSeen time.Time
|
|
LastSeen time.Time
|
|
}
|
|
|
|
// LiveRoute represents a route in the live routing table. JSON leaves out an
|
|
// empty AS path, next hop or time: the routing table in memory keeps them only
|
|
// for the two newest routes of each prefix and origin AS.
|
|
//
|
|
//nolint:tagliatelle // field names are the existing JSON API
|
|
type LiveRoute struct {
|
|
Prefix string `json:"prefix"`
|
|
MaskLength int `json:"mask_length"`
|
|
IPVersion int `json:"ip_version"`
|
|
OriginASN int `json:"origin_asn"`
|
|
PeerIP string `json:"peer_ip"`
|
|
ASPath []int `json:"as_path,omitempty"`
|
|
NextHop string `json:"next_hop,omitempty"`
|
|
LastUpdated time.Time `json:"last_updated,omitzero"`
|
|
}
|
|
|
|
// PrefixDistribution represents the distribution of prefixes by mask length
|
|
//
|
|
//nolint:tagliatelle // field names are the existing JSON API
|
|
type PrefixDistribution struct {
|
|
MaskLength int `json:"mask_length"`
|
|
Count int `json:"count"`
|
|
}
|
|
|
|
// IPInfo represents comprehensive IP information for the /ip endpoint
|
|
//
|
|
//nolint:tagliatelle // field names are the existing JSON API
|
|
type IPInfo struct {
|
|
IP string `json:"ip"`
|
|
Netblock string `json:"netblock"`
|
|
MaskLength int `json:"mask_length"`
|
|
IPVersion int `json:"ip_version"`
|
|
NumPeers int `json:"num_peers"`
|
|
// AS information
|
|
ASN int `json:"asn"`
|
|
ASName string `json:"as_name,omitempty"`
|
|
Handle string `json:"handle,omitempty"`
|
|
Description string `json:"description,omitempty"`
|
|
OrgName string `json:"org_name,omitempty"`
|
|
OrgID string `json:"org_id,omitempty"`
|
|
Address string `json:"address,omitempty"`
|
|
CountryCode string `json:"country_code,omitempty"`
|
|
AbuseEmail string `json:"abuse_email,omitempty"`
|
|
RIR string `json:"rir,omitempty"`
|
|
// Timestamps. LastSeen is zero, and left out of JSON, when the prefix
|
|
// keeps no route.
|
|
FirstSeen time.Time `json:"first_seen"`
|
|
LastSeen time.Time `json:"last_seen,omitzero"`
|
|
// Indicates if WHOIS data needs refresh (not serialized)
|
|
NeedsWHOISRefresh bool `json:"-"`
|
|
}
|
|
|
|
// LiveRouteDeletion represents parameters for deleting a live route
|
|
type LiveRouteDeletion struct {
|
|
Prefix string
|
|
PeerIP string
|
|
IPVersion int
|
|
}
|
|
|
|
// SeenTimes is the earliest and the latest time one batch of updates saw an AS,
|
|
// a peer or a peering. A row the batch adds is stored first seen at First and
|
|
// last seen at Last. A row already stored takes First as its first_seen only
|
|
// when First is earlier, and Last as its last_seen only when Last is later.
|
|
type SeenTimes struct {
|
|
First time.Time
|
|
Last time.Time
|
|
}
|
|
|
|
// Add makes t the earliest time of s when it is earlier than First, and the
|
|
// latest when it is later than Last. The zero SeenTimes holds no time yet, so
|
|
// the first Add sets both.
|
|
func (s *SeenTimes) Add(t time.Time) {
|
|
if s.First.IsZero() || t.Before(s.First) {
|
|
s.First = t
|
|
}
|
|
|
|
if s.Last.IsZero() || t.After(s.Last) {
|
|
s.Last = t
|
|
}
|
|
}
|
|
|
|
// PeerUpdate represents parameters for updating a peer. PeerASN and
|
|
// MessageType are those of the peer's latest update.
|
|
type PeerUpdate struct {
|
|
PeerIP string
|
|
PeerASN int
|
|
MessageType string
|
|
Seen SeenTimes
|
|
}
|
|
|
|
// ASNWHOISUpdate contains WHOIS data for updating an ASN record.
|
|
type ASNWHOISUpdate struct {
|
|
ASN int
|
|
ASName string
|
|
OrgName string
|
|
OrgID string
|
|
Address string
|
|
CountryCode string
|
|
AbuseEmail string
|
|
AbusePhone string
|
|
TechEmail string
|
|
TechPhone string
|
|
RIR string
|
|
RIRRegDate *time.Time
|
|
RIRLastMod *time.Time
|
|
WHOISRaw string
|
|
}
|