* * * * *
Dealing with phone numbers
“Project: Wolowizard [1] only supports NANP (North American Numbering Plan)
numbers, but since those numbers come via The Protocol Stack From Hell [2]
clearly marked as NANP, it's easy to determine there if a number is NANP or
not. It's not quite as simple in “Project: Sippy-Cup [3]” since SIP (Session
Initiation Protocol) [4] is … a bit loose with the data formatting.
There, the numbers are formatted as a tel: URI (Uniform Resource Identifier)
[5] (or a sip: URI [6] but the differences are minor). If the number is
“global,” it's easy to determine a NANP number because it will be marked with
a “+1” (“1” being the country code for North America). So, tel:+1-501-555-
1212 is most definitely a NANP number, while tel:+501-555-1212 is not.
Things get a bit more muddy when we receive a so-called “local” number. RFC
(Request For Comments)-3966 (The tel URI for Telephone Numbers) [7] clearly
states that a “local” tel: URI MUST (as defined in RFC-2119 (Key words for
use in RFCs to Indicate Requirement Levels) [8]) contain a phone-context
attribute—except when it doesn't (I swear—the RFC contradicts itself on that
point; tel:8005551212 is valid, even though it's a “local” number and missing
a phone-context attribute because it's a “national freephone number”). So
tel:555-1212;phone-context=+1501 is NANP, while tel:555-1212;phone-
context=+501 is not (look closely at the two—one has a country code of “1”
while the other has a country code of “501”). It's worse though, because
while tel:555-1212;phone-context=+1501 is NANP, you cannot use the phone-
context attribute to reconstruct a global number (the RFC contains the
following example: tel:863-1234;phone-context=+1-914-555—um … yeah).
To further complicate things, the phone-context attribute does not have to
contain digits—it can be a domain name. So tel:555-1212;phone-
context=example.com is a valid number. Is it NANP? International? Who knows?
So what does “Project: Sippy-Cup” do? If it receives a “local” number with a
“+1” country code in the phone-context attribute, it's marked as NANP; any
other country code is it marked as non-NANP. If the phone-context attribute
contains a domain name, it is treated as a NANP number (based on what I saw
in production). And if there's a missing phone-context attribute for a
“local” number, “Project: Sippy-Cup” treats it as a NANP number if it has at
least 10 digits.
Now, why do I care about this? Because we want to avoid doing an expensive
database query for non-NANP and invalid NANP numbers, but “Project: Heimdall
[9]” wants all the numbers for tracking potentially fraudulent calls.
[1]
gopher://gopher.conman.org/0Phlog:2010/10/11.1
[2]
gopher://gopher.conman.org/0Phlog:2012/01/31.1
[3]
gopher://gopher.conman.org/0Phlog:2014/03/05.1
[4]
https://en.wikipedia.org/wiki/Session_Initiation_Protocol
[5]
https://www.ietf.org/rfc/rfc3966.txt
[6]
https://www.ietf.org/rfc/rfc3261.txt
[7]
https://www.ietf.org/rfc/rfc3966.txt
[8]
https://www.ietf.org/rfc/rfc2119.txt
[9]
gopher://gopher.conman.org/0Phlog:2019/04/23.1
Email author at
[email protected]