-- IMPORTANT: This is the ONLY place where schema changes should be made. -- We do NOT support migrations. All schema changes MUST be in this file. -- DO NOT make schema changes anywhere else in the codebase. CREATE TABLE IF NOT EXISTS asns ( asn INTEGER PRIMARY KEY, handle TEXT, description TEXT, -- WHOIS parsed fields as_name TEXT, org_name TEXT, org_id TEXT, address TEXT, -- full address (may be multi-line) country_code TEXT, abuse_email TEXT, abuse_phone TEXT, tech_email TEXT, tech_phone TEXT, rir TEXT, -- ARIN, RIPE, APNIC, LACNIC, AFRINIC rir_registration_date DATETIME, rir_last_modified DATETIME, -- Raw WHOIS response whois_raw TEXT, -- complete WHOIS response text -- Timestamps first_seen DATETIME NOT NULL, last_seen DATETIME NOT NULL, whois_updated_at DATETIME -- when we last fetched WHOIS data ); -- IPv4 prefixes table. Every read and write finds a row by its prefix, so the -- rows are stored by prefix (WITHOUT ROWID) and need no index of their own. CREATE TABLE IF NOT EXISTS prefixes_v4 ( prefix TEXT PRIMARY KEY, first_seen DATETIME NOT NULL ) WITHOUT ROWID; -- IPv6 prefixes table, stored as prefixes_v4 is. CREATE TABLE IF NOT EXISTS prefixes_v6 ( prefix TEXT PRIMARY KEY, first_seen DATETIME NOT NULL ) WITHOUT ROWID; CREATE TABLE IF NOT EXISTS announcements ( id TEXT PRIMARY KEY, prefix_id TEXT NOT NULL, peer_asn INTEGER NOT NULL, origin_asn INTEGER NOT NULL, path TEXT NOT NULL, next_hop TEXT, timestamp DATETIME NOT NULL, is_withdrawal BOOLEAN NOT NULL DEFAULT 0, FOREIGN KEY (peer_asn) REFERENCES asns(asn), FOREIGN KEY (origin_asn) REFERENCES asns(asn) ); CREATE TABLE IF NOT EXISTS peerings ( id TEXT PRIMARY KEY, as_a INTEGER NOT NULL, as_b INTEGER NOT NULL, first_seen DATETIME NOT NULL, last_seen DATETIME NOT NULL, UNIQUE(as_a, as_b) ); -- BGP peers that send us messages CREATE TABLE IF NOT EXISTS bgp_peers ( id TEXT PRIMARY KEY, peer_ip TEXT UNIQUE NOT NULL, peer_asn INTEGER NOT NULL, first_seen DATETIME NOT NULL, last_seen DATETIME NOT NULL, last_message_type TEXT ); CREATE INDEX IF NOT EXISTS idx_announcements_timestamp ON announcements(timestamp); CREATE INDEX IF NOT EXISTS idx_announcements_prefix_id ON announcements(prefix_id); CREATE INDEX IF NOT EXISTS idx_announcements_peer_asn ON announcements(peer_asn); CREATE INDEX IF NOT EXISTS idx_announcements_origin_asn ON announcements(origin_asn); CREATE INDEX IF NOT EXISTS idx_peerings_as_a ON peerings(as_a); CREATE INDEX IF NOT EXISTS idx_peerings_as_b ON peerings(as_b); CREATE INDEX IF NOT EXISTS idx_peerings_lookup ON peerings(as_a, as_b); -- Indexes for asns table CREATE INDEX IF NOT EXISTS idx_asns_asn ON asns(asn); CREATE INDEX IF NOT EXISTS idx_asns_whois_updated_at ON asns(whois_updated_at); -- Finds the AS last seen most recently and the one last seen longest ago, for -- the home page. CREATE INDEX IF NOT EXISTS idx_asns_last_seen ON asns(last_seen); -- Indexes for bgp_peers table CREATE INDEX IF NOT EXISTS idx_bgp_peers_asn ON bgp_peers(peer_asn); CREATE INDEX IF NOT EXISTS idx_bgp_peers_last_seen ON bgp_peers(last_seen); CREATE INDEX IF NOT EXISTS idx_bgp_peers_ip ON bgp_peers(peer_ip); -- The whole routing table, as internal/routetable keeps it in memory: one row -- for each prefix and origin AS that some peer carries. Startup reads every -- row, and the rows of the pairs that change are written back. CREATE TABLE IF NOT EXISTS routes ( prefix TEXT NOT NULL, -- in the text form Go's net/netip prints origin_asn INTEGER NOT NULL, -- The peers whose current route to the prefix has this origin AS: a set -- of their numbers in route_peers, as the bitset package's MarshalBinary -- writes it. peers BLOB NOT NULL, -- The newest of those routes and the one before it, the two kept in full. -- Each has its peer's number in route_peers, its AS path as a JSON array, -- and its time in seconds since 1970, UTC. A route that is not kept has -- NULL in its three columns. newest_peer INTEGER, newest_as_path TEXT, newest_time INTEGER, older_peer INTEGER, older_as_path TEXT, older_time INTEGER, PRIMARY KEY (prefix, origin_asn) ) WITHOUT ROWID; -- The peers of the routes table, each with the number it has there. CREATE TABLE IF NOT EXISTS route_peers ( number INTEGER PRIMARY KEY, address TEXT NOT NULL UNIQUE );