diff --git a/local-db-client.js b/local-db-client.js index c3df0e7..9faf0ff 100644 --- a/local-db-client.js +++ b/local-db-client.js @@ -101,10 +101,17 @@ async function validateRpki(prefix, originAsn) { const prefixLength = parseInt(prefixParts[1]); - // Query for covering ROAs + // Query for covering ROAs. `prefix` is already a `cidr` column (its own + // mask, e.g. "1.1.1.0/24") -- appending "/" + max_length a second time + // produced invalid CIDR literals like "1.1.1.0/24/24" and made this + // query fail for every prefix. max_length is a separate upper bound, + // checked below against prefixLength once we have a covering ROA. + // Uses <<= (contained-by-or-equal), not << (strictly contained) -- a + // route announced at exactly the ROA's own prefix length is the most + // common real-world case and << alone misses it entirely. const result = await pool.query( `SELECT * FROM rpki_roas - WHERE $1::cidr << (prefix || '/' || max_length)::cidr + WHERE $1::cidr <<= prefix AND origin_asn = $2 AND expires > NOW() LIMIT 10`, @@ -113,7 +120,7 @@ async function validateRpki(prefix, originAsn) { if (result.rows.length === 0) { const anyRoa = await pool.query( - `SELECT 1 FROM rpki_roas WHERE $1::cidr << prefix AND expires > NOW() LIMIT 1`, + `SELECT 1 FROM rpki_roas WHERE $1::cidr <<= prefix AND expires > NOW() LIMIT 1`, [prefix] );