mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 04:11:08 +00:00
Add DUNDi.... (http://www.dundi.com)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4033 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
172
configs/dundi.conf.sample
Executable file
172
configs/dundi.conf.sample
Executable file
@@ -0,0 +1,172 @@
|
|||||||
|
;
|
||||||
|
; DUNDi configuration file
|
||||||
|
;
|
||||||
|
;
|
||||||
|
[general]
|
||||||
|
;
|
||||||
|
; The "general" section contains general parameters relating
|
||||||
|
; to the operation of the dundi client and server.
|
||||||
|
;
|
||||||
|
; The first part should be your complete contact information
|
||||||
|
; should someone else in your peer group need to contact you.
|
||||||
|
;
|
||||||
|
;department=Your Department
|
||||||
|
;organization=Your Company, Inc.
|
||||||
|
;locality=Your City
|
||||||
|
;stateprov=ST
|
||||||
|
;country=US
|
||||||
|
;email=your@email.com
|
||||||
|
;phone=+12565551212
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; Specify bind address and port number. Default is
|
||||||
|
; 4520
|
||||||
|
;
|
||||||
|
;bindaddr=0.0.0.0
|
||||||
|
;port=4520
|
||||||
|
;
|
||||||
|
; Our entity identifier (Should generally be the MAC address of the
|
||||||
|
; machine it's running on. Defaults to the first eth address, but you
|
||||||
|
; can override it here, as long as you set it to the MAC of *something*
|
||||||
|
; you own!)
|
||||||
|
;
|
||||||
|
;entityid=00:07:E9:3B:76:60
|
||||||
|
;
|
||||||
|
; Define the max depth in which to search the DUNDi system (also max # of
|
||||||
|
; seconds to wait for a reply)
|
||||||
|
;
|
||||||
|
ttl=32
|
||||||
|
;
|
||||||
|
; If we don't get ACK to our DPREQUEST within 2000ms, and autokill is set
|
||||||
|
; to yes, then we cancel the whole thing (that's enough time for one
|
||||||
|
; retransmission only). This is used to keep things from stalling for a long
|
||||||
|
; time for a host that is not available, but would be ill advised for bad
|
||||||
|
; connections. In addition to 'yes' or 'no' you can also specify a number
|
||||||
|
; of milliseconds. See 'qualify' for individual peers to turn on for just
|
||||||
|
; a specific peer.
|
||||||
|
;
|
||||||
|
autokill=yes
|
||||||
|
;
|
||||||
|
; pbx_dundi creates a rotating key called "secret", under the family
|
||||||
|
; 'secretpath'. The default family is dundi (resulting in
|
||||||
|
; the key being held at dundi/secret).
|
||||||
|
;
|
||||||
|
;secretpath=dundi
|
||||||
|
|
||||||
|
[mappings]
|
||||||
|
;
|
||||||
|
; The "mappings" section maps DUNDi contexts
|
||||||
|
; to contexts on the local asterisk system. Remember
|
||||||
|
; that numbers that are made available under the e164
|
||||||
|
; DUNDi context are regulated by the DUNDi General Peering
|
||||||
|
; Agreement (GPA) if you are a member of the DUNDi E.164
|
||||||
|
; Peering System.
|
||||||
|
;
|
||||||
|
; dundi_context => local_context,weight,tech,dest[,options]]
|
||||||
|
;
|
||||||
|
; dundi_context is the name of the context being requested
|
||||||
|
; within the DUNDi request
|
||||||
|
;
|
||||||
|
; local_context is the name of the context on the local system
|
||||||
|
; in which numbers can be looked up for which responses shall be given.
|
||||||
|
;
|
||||||
|
; tech is the technology to use (IAX, SIP, H323)
|
||||||
|
;
|
||||||
|
; dest is the destination to supply for reaching that number. Note
|
||||||
|
; that the variable ${NUMBER} shall be replaced by the number being
|
||||||
|
; requested.
|
||||||
|
;
|
||||||
|
; Further options may include:
|
||||||
|
;
|
||||||
|
; nounsolicited: No unsolicited calls of any type permitted via this
|
||||||
|
; route
|
||||||
|
; nocomunsolicit: No commercial unsolicited calls permitted via
|
||||||
|
; this route
|
||||||
|
; residential: This number is known to be a residence
|
||||||
|
; commercial: This number is known to be a business
|
||||||
|
; mobile: This number is known to be a mobile phone
|
||||||
|
; nocomunsolicit: No commercial unsolicited calls permitted via
|
||||||
|
; this route
|
||||||
|
; nopartial: Do not search for partial matches
|
||||||
|
;
|
||||||
|
; There *must* exist an entry in mappings for DUNDi to respond
|
||||||
|
; to any request, although it may be empty.
|
||||||
|
;
|
||||||
|
;e164 => dundi-e164-canonical,0,IAX2,dundi:${SECRET}@${IPADDR}/${NUMBER},nounsolicited,nocomunsolicit,nopartial
|
||||||
|
;e164 => dundi-e164-customers,100,IAX2,dundi:${SECRET}@${IPADDR}/${NUMBER},nounsolicited,nocomunsolicit,nopartial
|
||||||
|
;e164 => dundi-e164-via-pstn,400,IAX2,dundi:${SECRET}@${IPADDR}/${NUMBER},nounsolicited,nocomunsolicit,nopartial
|
||||||
|
|
||||||
|
;digexten => default,0,IAX2,guest@lappy/${NUMBER}
|
||||||
|
;asdf =>
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; The remaining sections represent the peers
|
||||||
|
; that we fundamentally trust. The section name
|
||||||
|
; represents the name and optionally at a specific
|
||||||
|
; DUNDi context if you want the trust to be established
|
||||||
|
; for only a specific DUNDi context.
|
||||||
|
;
|
||||||
|
; inkey - What key they will be authenticating to us with
|
||||||
|
;
|
||||||
|
; outkey - What key we use to authenticate to them
|
||||||
|
;
|
||||||
|
; host - What their host is
|
||||||
|
;
|
||||||
|
; order - What search order to use. May be 'primary', 'secondary',
|
||||||
|
; 'tertiary' or 'quartiary'. In large systems, it is beneficial
|
||||||
|
; to only query one up-stream host in order to maximize caching
|
||||||
|
; value. Adding one with primary and one with secondary gives you
|
||||||
|
; redundancy without sacraficing performance.
|
||||||
|
;
|
||||||
|
; include - Includes this peer when searching a particular context
|
||||||
|
; for lookup (set "all" to perform all lookups with that
|
||||||
|
; host.
|
||||||
|
;
|
||||||
|
; noinclude - Disincludes this peer when searching a particular context
|
||||||
|
; for lookup (set "all" to perform no lookups with that
|
||||||
|
; host.
|
||||||
|
;
|
||||||
|
; permit - Permits this peer to search a given DUNDi context on
|
||||||
|
; the local system. Set "all" to permit this host to
|
||||||
|
; lookup all contexts.
|
||||||
|
;
|
||||||
|
; deny - Denies this peer to search a given DUNDi context on
|
||||||
|
; the local system. Set "all" to deny this host to
|
||||||
|
; lookup all contexts.
|
||||||
|
;
|
||||||
|
; model - inbound, outbound, or symmetric for whether we receive
|
||||||
|
; requests only, transmit requests only, or do both.
|
||||||
|
;
|
||||||
|
; The '*' peer is special and matches an unspecified entity
|
||||||
|
;
|
||||||
|
|
||||||
|
;
|
||||||
|
; Sample Primary e164 DUNDi peer
|
||||||
|
;
|
||||||
|
[00:50:8B:F3:75:BB]
|
||||||
|
model = symmetric
|
||||||
|
host = 64.215.96.114
|
||||||
|
inkey = digium
|
||||||
|
outkey = misery
|
||||||
|
include = e164
|
||||||
|
permit = e164
|
||||||
|
qualify = yes
|
||||||
|
|
||||||
|
;
|
||||||
|
; Sample Secondary e164 DUNDi peer
|
||||||
|
;
|
||||||
|
;[00:A0:C9:96:92:84]
|
||||||
|
;model = symmetric
|
||||||
|
;host = misery.digium.com
|
||||||
|
;inkey = misery
|
||||||
|
;outkey = ourkey
|
||||||
|
;include = e164
|
||||||
|
;permit = e164
|
||||||
|
;qualify = yes
|
||||||
|
;order = secondary
|
||||||
|
|
||||||
|
|
||||||
|
;[*]
|
||||||
|
;
|
@@ -108,6 +108,64 @@ TRUNKMSD=1 ; MSD digits to strip (usually 1 or 0)
|
|||||||
; so that dialtone remains even after dialing a 9.
|
; so that dialtone remains even after dialing a 9.
|
||||||
;
|
;
|
||||||
|
|
||||||
|
;
|
||||||
|
; Sample entries for extensions.conf
|
||||||
|
;
|
||||||
|
;
|
||||||
|
[dundi-e164-canonical]
|
||||||
|
;
|
||||||
|
; List canonical entries here
|
||||||
|
;
|
||||||
|
;exten => 12564286000,1,Macro(std-exten,6000,IAX2/foo)
|
||||||
|
;exten => _125642860XX,1,Dial(IAX2/otherbox/${EXTEN:7})
|
||||||
|
|
||||||
|
[dundi-e164-customers]
|
||||||
|
;
|
||||||
|
; If you are an ITSP or Reseller, list your customers here.
|
||||||
|
;
|
||||||
|
;exten => _12564286000,1,Dial(SIP/customer1)
|
||||||
|
;exten => _12564286001,1,Dial(IAX2/customer2)
|
||||||
|
|
||||||
|
[dundi-e164-via-pstn]
|
||||||
|
;
|
||||||
|
; If you are freely delivering calls to the PSTN, list them here
|
||||||
|
;
|
||||||
|
;exten => _1256428XXXX,1,Dial(Zap/g2/${EXTEN:7}) ; Expose all of 256-428
|
||||||
|
;exten => _1256325XXXX,1,Dial(Zap/g2/${EXTEN:7}) ; Ditto for 256-325
|
||||||
|
|
||||||
|
[dundi-e164-local]
|
||||||
|
;
|
||||||
|
; Context to put your dundi IAX2 or SIP user in for
|
||||||
|
; full access
|
||||||
|
;
|
||||||
|
include => dundi-e164-canonical
|
||||||
|
include => dundi-e164-customers
|
||||||
|
include => dundi-e164-via-pstn
|
||||||
|
|
||||||
|
[dundi-e164-switch]
|
||||||
|
;
|
||||||
|
; Just a wrapper for the switch
|
||||||
|
;
|
||||||
|
switch => DUNDi/e164
|
||||||
|
|
||||||
|
[dundi-e164-lookup]
|
||||||
|
;
|
||||||
|
; Locally to lookup, try looking for a local E.164 solution
|
||||||
|
; then try DUNDi if we don't have one.
|
||||||
|
;
|
||||||
|
include => dundi-e164-local
|
||||||
|
include => dundi-e164-switch
|
||||||
|
;
|
||||||
|
; DUNDi can also be implemented as a Macro instead of using
|
||||||
|
; the Local channel driver.
|
||||||
|
;
|
||||||
|
[macro-dundi-e164]
|
||||||
|
;
|
||||||
|
; ARG1 is the extension to Dial
|
||||||
|
;
|
||||||
|
exten => s,1,Goto(${ARG1},1)
|
||||||
|
include => dundi-e164-lookup
|
||||||
|
|
||||||
;
|
;
|
||||||
; Here are the entries you need to participate in the IAXTEL
|
; Here are the entries you need to participate in the IAXTEL
|
||||||
; call routing system. Most IAXTEL numbers begin with 1-700, but
|
; call routing system. Most IAXTEL numbers begin with 1-700, but
|
||||||
@@ -130,13 +188,15 @@ exten => _91700XXXXXXX,1,Dial(IAX2/${IAXINFO}@iaxtel.com/${EXTEN:1}@iaxtel)
|
|||||||
;
|
;
|
||||||
; International long distance through trunk
|
; International long distance through trunk
|
||||||
;
|
;
|
||||||
exten => _9011.,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
exten => _9011.,1,Macro(dundi-e164,${EXTEN:4})
|
||||||
|
exten => _9011.,n,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
||||||
|
|
||||||
[trunkld]
|
[trunkld]
|
||||||
;
|
;
|
||||||
; Long distance context accessed through trunk
|
; Long distance context accessed through trunk
|
||||||
;
|
;
|
||||||
exten => _91NXXNXXXXXX,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
exten => _91NXXNXXXXXX,1,Macro(dundi-e164,${EXTEN:1})
|
||||||
|
exten => _91NXXNXXXXXX,n,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
|
||||||
|
|
||||||
[trunklocal]
|
[trunklocal]
|
||||||
;
|
;
|
||||||
|
@@ -199,6 +199,15 @@ context=default
|
|||||||
auth=rsa
|
auth=rsa
|
||||||
inkeys=freeworlddialup
|
inkeys=freeworlddialup
|
||||||
|
|
||||||
|
;
|
||||||
|
; Trust callerid delivered over DUNDi/e164
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;[dundi]
|
||||||
|
;type=user
|
||||||
|
;dbsecret=dundi/secret
|
||||||
|
;context=dundi-e164-local
|
||||||
|
|
||||||
;
|
;
|
||||||
; Further user sections may be added, specifying a context and a
|
; Further user sections may be added, specifying a context and a
|
||||||
; secret used for connections with that given authentication name.
|
; secret used for connections with that given authentication name.
|
||||||
|
499
doc/PEERING
Executable file
499
doc/PEERING
Executable file
@@ -0,0 +1,499 @@
|
|||||||
|
DIGIUM GENERAL PEERING AGREEMENT (TM)
|
||||||
|
Version 1.0.0, September 2004
|
||||||
|
Copyright (C) 2004 Digium, Inc.
|
||||||
|
150 West Park Loop Suite 100, Huntsville, AL 35806 USA
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute complete verbatim copies
|
||||||
|
of this General Peering Agreement provided it is not modified in any
|
||||||
|
manner.
|
||||||
|
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
DIGIUM GENERAL PEERING AGREEMENT
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
|
||||||
|
For most of the history of telecommunications, the power of being able
|
||||||
|
to locate and communicate with another person in a system, be it across
|
||||||
|
a hall or around the world, has always centered around a centralized
|
||||||
|
authority -- from a local PBX administrator to regional and national
|
||||||
|
RBOCs, generally requiring fees, taxes or regulation. By contrast,
|
||||||
|
DUNDi is a technology developed to provide users the freedom to
|
||||||
|
communicate with each other without the necessity of any centralized
|
||||||
|
authority. This General Peering Agreement ("GPA") is used by individual
|
||||||
|
parties (each, a "Participant") to allow them to build the E164 trust
|
||||||
|
group for the DUNDi protocol.
|
||||||
|
|
||||||
|
To protect the usefulness of the E164 trust group for those who use
|
||||||
|
it, while keeping the system wholly decentralized, it is necessary to
|
||||||
|
replace many of the responsibilities generally afforded to a company or
|
||||||
|
government agency, with a set of responsibilities implemented by the
|
||||||
|
parties who use the system, themselves. It is the goal of this document
|
||||||
|
to provide all the protections necessary to keep the DUNDi E164 trust
|
||||||
|
group useful and reliable.
|
||||||
|
|
||||||
|
The Participants wish to protect competition, promote innovation and
|
||||||
|
value added services and make this service valuable both commercially
|
||||||
|
and non-commercially. To that end, this GPA provides special terms and
|
||||||
|
conditions outlining some permissible and non-permissible revenue
|
||||||
|
sources.
|
||||||
|
|
||||||
|
This GPA is independent of any software license or other license
|
||||||
|
agreement for a program or technology employing the DUNDi protocol. For
|
||||||
|
example, the implementation of DUNDi used by Asterisk is covered under a
|
||||||
|
separate license. Each Participant is responsible for compliance with
|
||||||
|
any licenses or other agreements governing use of such program or
|
||||||
|
technology that they use to peer.
|
||||||
|
|
||||||
|
You do not have to execute this GPA to use a program or technology
|
||||||
|
employing the DUNDi protocol, however if you do not execute this GPA,
|
||||||
|
you will not be able to peer using DUNDi and the E164 context with
|
||||||
|
anyone who is a member of the trust group by virtue of their having
|
||||||
|
executed this GPA with another member.
|
||||||
|
|
||||||
|
The parties to this GPA agree as follows:
|
||||||
|
|
||||||
|
0. DEFINITIONS. As used herein, certain terms shall be defined as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
(a) The term "DUNDi" means the DUNDi protocol as published by
|
||||||
|
Digium, Inc. or its successor in interest with respect to the
|
||||||
|
DUNDi protocol specification.
|
||||||
|
|
||||||
|
(b) The terms "E.164" and "E164" mean ITU-T specification E.164 as
|
||||||
|
published by the International Telecommunications Union (ITU) in
|
||||||
|
May, 1997.
|
||||||
|
|
||||||
|
(c) The term "Service" refers to any communication facility (e.g.,
|
||||||
|
telephone, fax, modem, etc.), identified by an E.164-compatible
|
||||||
|
number, and assigned by the appropriate authority in that
|
||||||
|
jurisdiction.
|
||||||
|
|
||||||
|
(d) The term "Egress Gateway" refers an Internet facility that
|
||||||
|
provides a communications path to a Service or Services that may
|
||||||
|
not be directly addressable via the Internet.
|
||||||
|
|
||||||
|
(e) The term "Route" refers to an Internet address, policies, and
|
||||||
|
other characteristics defined by the DUNDi protocol and
|
||||||
|
associated with the Service, or the Egress Gateway which
|
||||||
|
provides access to the specified Service.
|
||||||
|
|
||||||
|
(f) The term "Propagate" means to accept or transmit Service and/or
|
||||||
|
Egress Gateway Routes only using the DUNDi protocol and the
|
||||||
|
DUNDi context "e164" without regard to case, and does not apply
|
||||||
|
to the exchange of information using any other protocol or
|
||||||
|
context.
|
||||||
|
|
||||||
|
(g) The term "Peering System" means the network of systems that
|
||||||
|
Propagate Routes.
|
||||||
|
|
||||||
|
(h) The term "Subscriber" means the owner of, or someone who
|
||||||
|
contracts to receive, the services identified by an E.164
|
||||||
|
number.
|
||||||
|
|
||||||
|
(i) The term "Authorizing Individual" means the Subscriber to a
|
||||||
|
number who has authorized a Participant to provide Routes
|
||||||
|
regarding their services via this Peering System.
|
||||||
|
|
||||||
|
(j) The term "Route Authority" refers to a Participant that provides
|
||||||
|
an original source of said Route within the Peering System.
|
||||||
|
Routes are propagated from the Route Authorities through the
|
||||||
|
Peering System and may be cached at intermediate points. There
|
||||||
|
may be multiple Route Authorities for any Service.
|
||||||
|
|
||||||
|
(k) The term "Participant" (introduced above) refers to any member
|
||||||
|
of the Peering System.
|
||||||
|
|
||||||
|
(l) The term "Service Provider" refers to the carrier (e.g.,
|
||||||
|
exchange carrier, Internet Telephony Service Provider, or other
|
||||||
|
reseller) that provides communication facilities for a
|
||||||
|
particular Service to a Subscriber, Customer or other End User.
|
||||||
|
|
||||||
|
(m) The term "Weight" refers to a numeric quality assigned to a
|
||||||
|
Route as per the DUNDi protocol specification. The current
|
||||||
|
Weight definitions are shown in Exhibit A.
|
||||||
|
|
||||||
|
1. PEERING. The undersigned Participants agree to Propagate Routes
|
||||||
|
with each other and any other member of the Peering System and further
|
||||||
|
agree not to Propagate DUNDi Routes with a third party unless they have
|
||||||
|
first have executed this GPA (in its unmodified form) with such third
|
||||||
|
party. The Participants further agree only to Propagate Routes with
|
||||||
|
Participants whom they reasonably believe to be honoring the terms of
|
||||||
|
the GPA. Participants may not insert, remove, amend, or otherwise
|
||||||
|
modify any of the terms of the GPA.
|
||||||
|
|
||||||
|
2. ACCEPTABLE USE POLICY. The DUNDi protocol contains information
|
||||||
|
that reflect a Subscriber's or Egress Gateway's decisions to receive
|
||||||
|
calls. In addition to the terms and conditions set forth in this GPA,
|
||||||
|
the Participants agree to honor the intent of restrictions encoded in
|
||||||
|
the DUNDi protocol. To that end, Participants agree to the following:
|
||||||
|
|
||||||
|
(a) A Participant may not utilize or permit the utilization of
|
||||||
|
Routes for which the Subscriber or Egress Gateway provider has
|
||||||
|
indicated that they do not wish to receive "Unsolicited Calls"
|
||||||
|
for the purpose of making an unsolicited phone call on behalf of
|
||||||
|
any party or organization.
|
||||||
|
|
||||||
|
(b) A Participant may not utilize or permit the utilization of
|
||||||
|
Routes which have indicated that they do not wish to receive
|
||||||
|
"Unsolicited Commercial Calls" for the purpose of making an
|
||||||
|
unsolicited phone call on behalf of a commercial organization.
|
||||||
|
|
||||||
|
(c) A Participant may never utilize or permit the utilization of any
|
||||||
|
DUNDi route for the purpose of making harassing phone calls.
|
||||||
|
|
||||||
|
(d) A Party may not utilize or permit the utilization of DUNDi
|
||||||
|
provided Routes for any systematic or random calling of numbers
|
||||||
|
(e.g., for the purpose of locating facsimile, modem services, or
|
||||||
|
systematic telemarketing).
|
||||||
|
|
||||||
|
(e) Initial control signaling for all communication sessions that
|
||||||
|
utilize Routes obtained from the Peering System must be sent
|
||||||
|
from a member of the Peering System to the Service or Egress
|
||||||
|
Gateway identified in the selected Route. For example, 'SIP
|
||||||
|
INVITES' and IAX2 "NEW" commands must be sent from the
|
||||||
|
requesting DUNDi node to the terminating Service.
|
||||||
|
|
||||||
|
(f) A Participant may not disclose any specific Route, Service or
|
||||||
|
Participant contact information obtained from the Peering System
|
||||||
|
to any party outside of the Peering System except as a
|
||||||
|
by-product of facilitating communication in accordance with
|
||||||
|
section 2e (e.g., phone books or other databases may not be
|
||||||
|
published, but the Internet addresses of the Egress Gateway or
|
||||||
|
Service does not need to be obfuscated.)
|
||||||
|
|
||||||
|
(g) The DUNDi Protocol requires that each Participant include valid
|
||||||
|
contact information about itself (including information about
|
||||||
|
nodes connected to each Participant). Participants may use or
|
||||||
|
disclose the contact information only to ensure enforcement of
|
||||||
|
legal furtherance of this Agreement.
|
||||||
|
|
||||||
|
3. ROUTES. The Participants shall only propagate valid Routes, as
|
||||||
|
defined herein, through the Peering System, regardless of the original
|
||||||
|
source. The Participants may only provide Routes as set forth below,
|
||||||
|
and then only if such Participant has no good faith reason to believe
|
||||||
|
such Route to be invalid or unauthorized.
|
||||||
|
|
||||||
|
(a) A Participant may provide Routes if each Route has as its
|
||||||
|
original source another member of the Peering System who has
|
||||||
|
duly executed the GPA and such Routes are provided in accordance
|
||||||
|
with this Agreement; provided that the Routes are not modified
|
||||||
|
(e.g., with regards to existence, destination, technology or
|
||||||
|
Weight); or
|
||||||
|
|
||||||
|
(b) A Participant may provide Routes for Services with any Weight
|
||||||
|
for which it is the Subscriber; or
|
||||||
|
|
||||||
|
(c) A Participant may provide Routes for those Services whose
|
||||||
|
Subscriber has authorized the Participant to do so, provided
|
||||||
|
that the Participant is able to confirm that the Authorizing
|
||||||
|
Individual is the Subscriber through:
|
||||||
|
|
||||||
|
i. a written statement of ownership from the Authorizing
|
||||||
|
Individual, which the Participant believes in good faith
|
||||||
|
to be accurate (e.g., a phone bill with the name of the
|
||||||
|
Authorizing Individual and the number in question); or
|
||||||
|
|
||||||
|
ii. the Participant's own direct personal knowledge that the
|
||||||
|
Authorizing Individual is the Subscriber.
|
||||||
|
|
||||||
|
(d) A Participant may provide Routes for Services, with Weight in
|
||||||
|
accordance with the Current DUNDi Specification, if it can in
|
||||||
|
good faith provide an Egress Gateway to that Service on the
|
||||||
|
traditional telephone network without cost to the calling party.
|
||||||
|
|
||||||
|
4. REVOCATION. A Participant must provide a free, easily accessible
|
||||||
|
mechanism by which a Subscriber may revoke permission to act as a Route
|
||||||
|
Authority for his Service. A Participant must stop acting as a Route
|
||||||
|
Authority for that Service within 7 days after:
|
||||||
|
|
||||||
|
(a) receipt of a revocation request;
|
||||||
|
|
||||||
|
(b) receiving other notice that the Service is no longer valid; or
|
||||||
|
|
||||||
|
(c) determination that the Subscriber's information is no longer
|
||||||
|
accurate (including that the Subscriber is no longer the service
|
||||||
|
owner or the service owner's authorized delegate).
|
||||||
|
|
||||||
|
5. SERVICE FEES. A Participant may charge a fee to act as a Route
|
||||||
|
Authority for a Service, with any Weight, provided that no Participant
|
||||||
|
may charge a fee to propagate the Route received through the Peering
|
||||||
|
System.
|
||||||
|
|
||||||
|
6. TOLL SERVICES. No Participant may provide Routes for any Services
|
||||||
|
that require payment from the calling party or their customer for
|
||||||
|
communication with the Service. Nothing in this section shall prohibit
|
||||||
|
a Participant from providing routes for Services where the calling party
|
||||||
|
may later enter into a financial transaction with the called party
|
||||||
|
(e.g., a Participant may provide Routes for calling cards services).
|
||||||
|
|
||||||
|
7. QUALITY. A Participant may not intentionally impair communication
|
||||||
|
using a Route provided to the Peering System (e.g. by adding delay,
|
||||||
|
advertisements, reduced quality). If for any reason a Participant is
|
||||||
|
unable to deliver a call via a Route provided to the Peering System,
|
||||||
|
that Participant shall return out-of-band Network Congestion
|
||||||
|
notification (e.g. "503 Service Unavailable" with SIP protocol or
|
||||||
|
"CONGESTION" with IAX protocol).
|
||||||
|
|
||||||
|
8. PROTOCOL COMPLIANCE. Participants agree to Propagate Routes in
|
||||||
|
strict compliance with current DUNDi protocol specifications.
|
||||||
|
|
||||||
|
9. ADMINISTRATIVE FEES. A Participant may charge (but is not required
|
||||||
|
to charge) another Participant a reasonable fee to cover administrative
|
||||||
|
expenses incurred in the execution of this Agreement. A Participant may
|
||||||
|
not charge any fee to continue the relationship or to provide Routes to
|
||||||
|
another Participant in the Peering System.
|
||||||
|
|
||||||
|
10. CALLER IDENTIFICATION. A Participant will make a good faith effort
|
||||||
|
to ensure the accuracy and appropriate nature of any caller
|
||||||
|
identification that it transmits via any Route obtained from the Peering
|
||||||
|
System. Caller identification shall at least be provided as a valid
|
||||||
|
E.164 number.
|
||||||
|
|
||||||
|
11. COMPLIANCE WITH LAWS. The Participants are solely responsible for
|
||||||
|
determining to what extent, if any, the obligations set forth in this
|
||||||
|
GPA conflict with any laws or regulations their region. A Participant
|
||||||
|
may not provide any service or otherwise use DUNDi under this GPA if
|
||||||
|
doing so is prohibited by law or regulation, or if any law or regulation
|
||||||
|
imposes requirements on the Participant that are inconsistent with the
|
||||||
|
terms of this GPA or the Acceptable Use Policy.
|
||||||
|
|
||||||
|
12. WARRANTY. EACH PARTICIPANT WARRANTS TO THE OTHER PARTICIPANTS THAT
|
||||||
|
IT MADE, AND WILL CONTINUE TO MAKE, A GOOD FAITH EFFORT TO AUTHENTICATE
|
||||||
|
OTHERS IN THE PEERING SYSTEM AND TO PROVIDE ACCURATE INFORMATION IN
|
||||||
|
ACCORDANCE WITH THE TERMS OF THIS GPA. THIS WARRANTY IS MADE BETWEEN
|
||||||
|
THE PARTICIPANTS, AND THE PARTICIPANTS MAY NOT EXTEND THIS WARRANTY TO
|
||||||
|
ANY NON-PARTICIPANT INCLUDING END-USERS.
|
||||||
|
|
||||||
|
13. DISCLAIMER OF WARRANTIES. THE PARTICIPANTS UNDERSTAND AND AGREE
|
||||||
|
THAT ANY SERVICE PROVIDED AS A RESULT OF THIS GPA IS "AS IS." EXCEPT FOR
|
||||||
|
THOSE WARRANTIES OTHERWISE EXPRESSLY SET FORTH HEREIN, THE PARTICIPANTS
|
||||||
|
DISCLAIM ANY REPRESENTATIONS OR WARRANTIES OF ANY KIND OR NATURE,
|
||||||
|
EXPRESS OR IMPLIED, AS TO THE CONDITION, VALUE OR QUALITIES OF THE
|
||||||
|
SERVICES PROVIDED HEREUNDER, AND SPECIFICALLY DISCLAIM ANY
|
||||||
|
REPRESENTATION OR WARRANTY OF MERCHANTABILITY, SUITABILITY OR FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE OR AS TO THE CONDITION OR WORKMANSHIP THEREOF,
|
||||||
|
OR THE ABSENCE OF ANY DEFECTS THEREIN, WHETHER LATENT OR PATENT,
|
||||||
|
INCLUDING ANY WARRANTIES ARISING FROM A COURSE OF DEALING, USAGE OR
|
||||||
|
TRADE PRACTICE. EXCEPT AS EXPRESSLY PROVIDED HEREIN, THE PARTICIPANTS
|
||||||
|
EXPRESSLY DISCLAIM ANY REPRESENTATIONS OR WARRANTIES THAT THE PEERING
|
||||||
|
SERVICE WILL BE CONTINUOUS, UNINTERRUPTED OR ERROR-FREE, THAT ANY DATA
|
||||||
|
SHARED OR OTHERWISE MADE AVAILABLE WILL BE ACCURATE OR COMPLETE OR
|
||||||
|
OTHERWISE COMPLETELY SECURE FROM UNAUTHORIZED ACCESS.
|
||||||
|
|
||||||
|
14. LIMITATION OF LIABILITIES. NO PARTICIPANT SHALL BE LIABLE TO ANY
|
||||||
|
OTHER PARTICIPANT FOR INCIDENTAL, INDIRECT, CONSEQUENTIAL, SPECIAL,
|
||||||
|
PUNITIVE OR EXEMPLARY DAMAGES OF ANY KIND (INCLUDING LOST REVENUES OR
|
||||||
|
PROFITS, LOSS OF BUSINESS OR LOSS OF DATA) IN ANY WAY RELATED TO THIS
|
||||||
|
GPA, WHETHER IN CONTRACT OR IN TORT, REGARDLESS OF WHETHER SUCH
|
||||||
|
PARTICIPANT WAS ADVISED OF THE POSSIBILITY THEREOF.
|
||||||
|
|
||||||
|
15. END-USER AGREEMENTS. The Participants may independently enter
|
||||||
|
into agreements with end-users to provide certain services (e.g., fees
|
||||||
|
to a Subscriber to originate Routes for that Service). To the extent
|
||||||
|
that provision of these services employs the Peering System, the Parties
|
||||||
|
will include in their agreements with their end-users terms and
|
||||||
|
conditions consistent with the terms of this GPA with respect to the
|
||||||
|
exclusion of warranties, limitation of liability and Acceptable Use
|
||||||
|
Policy. In no event may a Participant extend the warranty described in
|
||||||
|
Section 12 in this GPA to any end-users.
|
||||||
|
|
||||||
|
16. INDEMNIFICATION. Each Participant agrees to defend, indemnify and
|
||||||
|
hold harmless the other Participant or third-party beneficiaries to this
|
||||||
|
GPA (including their affiliates, successors, assigns, agents and
|
||||||
|
representatives and their respective officers, directors and employees)
|
||||||
|
from and against any and all actions, suits, proceedings,
|
||||||
|
investigations, demands, claims, judgments, liabilities, obligations,
|
||||||
|
liens, losses, damages, expenses (including, without limitation,
|
||||||
|
attorneys' fees) and any other fees arising out of or relating to (i)
|
||||||
|
personal injury or property damage caused by that Participant, its
|
||||||
|
employees, agents, servants, or other representatives; (ii) any act or
|
||||||
|
omission by the Participant, its employees, agents, servants or other
|
||||||
|
representatives, including, but not limited to, unauthorized
|
||||||
|
representations or warranties made by the Participant; or (iii) any
|
||||||
|
breach by the Participant of any of the terms or conditions of this GPA.
|
||||||
|
|
||||||
|
17. THIRD PARTY BENEFICIARIES. This GPA is intended to benefit those
|
||||||
|
Participants who have executed the GPA and who are in the Peering
|
||||||
|
System. It is the intent of the Parties to this GPA to give to those
|
||||||
|
Participants who are in the Peering System standing to bring any
|
||||||
|
necessary legal action to enforce the terms of this GPA.
|
||||||
|
|
||||||
|
18. TERMINATION. Any Participant may terminate this GPA at any time,
|
||||||
|
with or without cause. A Participant that terminates must immediately
|
||||||
|
cease to Propagate.
|
||||||
|
|
||||||
|
19. CHOICE OF LAW. This GPA and the rights and duties of the Parties
|
||||||
|
hereto shall be construed and determined in accordance with the internal
|
||||||
|
laws of the State of New York, United States of America, without regard
|
||||||
|
to its conflict of laws principles and without application of the United
|
||||||
|
Nations Convention on Contracts for the International Sale of Goods.
|
||||||
|
|
||||||
|
20. DISPUTE RESOLUTION. Unless otherwise agreed in writing, the
|
||||||
|
exclusive procedure for handling disputes shall be as set forth herein.
|
||||||
|
Notwithstanding such procedures, any Participant may, at any time, seek
|
||||||
|
injunctive relief in addition to the process described below.
|
||||||
|
|
||||||
|
(a) Prior to mediation or arbitration the disputing Participants
|
||||||
|
shall seek informal resolution of disputes. The process shall be
|
||||||
|
initiated with written notice of one Participant to the other
|
||||||
|
describing the dispute with reasonable particularity followed
|
||||||
|
with a written response within ten (10) days of receipt of
|
||||||
|
notice. Each Participant shall promptly designate an executive
|
||||||
|
with requisite authority to resolve the dispute. The informal
|
||||||
|
procedure shall commence within ten (10) days of the date of
|
||||||
|
response. All reasonable requests for non-privileged information
|
||||||
|
reasonably related to the dispute shall be honored. If the
|
||||||
|
dispute is not resolved within thirty (30) days of commencement
|
||||||
|
of the procedure either Participant may proceed to mediation or
|
||||||
|
arbitration pursuant to the rules set forth in (b) or (c) below.
|
||||||
|
|
||||||
|
(b) If the dispute has not been resolved pursuant to (a) above or,
|
||||||
|
if the disputing Participants fail to commence informal dispute
|
||||||
|
resolution pursuant to (a) above, either Participant may, in
|
||||||
|
writing and within twenty (20) days of the response date noted
|
||||||
|
in (a) above, ask the other Participant to participate in a one
|
||||||
|
(1) day mediation with an impartial mediator, and the other
|
||||||
|
Participant shall do so. Each Participant will bear its own
|
||||||
|
expenses and an equal share of the fees of the mediator. If the
|
||||||
|
mediation is not successful the Participants may proceed with
|
||||||
|
arbitration pursuant to (c) below.
|
||||||
|
|
||||||
|
(c) If the dispute has not been resolved pursuant to (a) or (b)
|
||||||
|
above, the dispute shall be promptly referred, no later than one
|
||||||
|
(1) year from the date of original notice and subject to
|
||||||
|
applicable statute of limitations, to binding arbitration in
|
||||||
|
accordance with the UNCITRAL Arbitration Rules in effect on the
|
||||||
|
date of this contract. The appointing authority shall be the
|
||||||
|
International Centre for Dispute Resolution. The case shall be
|
||||||
|
administered by the International Centre for Dispute Resolution
|
||||||
|
under its Procedures for Cases under the UNCITRAL Arbitration
|
||||||
|
Rules. Each Participant shall bear its own expenses and shall
|
||||||
|
share equally in fees of the arbitrator. All arbitrators shall
|
||||||
|
have substantial experience in information technology and/or in
|
||||||
|
the telecommunications business and shall be selected by the
|
||||||
|
disputing participants in accordance with UNCITRAL Arbitration
|
||||||
|
Rules. If any arbitrator, once selected is unable or unwilling
|
||||||
|
to continue for any reason, replacement shall be filled via the
|
||||||
|
process described above and a re-hearing shall be conducted. The
|
||||||
|
disputing Participants will provide each other with all
|
||||||
|
requested documents and records reasonably related to the
|
||||||
|
dispute in a manner that will minimize the expense and
|
||||||
|
inconvenience of both parties. Discovery will not include
|
||||||
|
depositions or interrogatories except as the arbitrators
|
||||||
|
expressly allow upon a showing of need. If disputes arise
|
||||||
|
concerning discovery requests, the arbitrators shall have sole
|
||||||
|
and complete discretion to resolve the disputes. The parties and
|
||||||
|
arbitrator shall be guided in resolving discovery disputes by
|
||||||
|
the Federal Rules of Civil Procedure. The Participants agree
|
||||||
|
that time of the essence principles shall guide the hearing and
|
||||||
|
that the arbitrator shall have the right and authority to issue
|
||||||
|
monetary sanctions in the event of unreasonable delay. The
|
||||||
|
arbitrator shall deliver a written opinion setting forth
|
||||||
|
findings of fact and the rationale for the award within thirty
|
||||||
|
(30) days following conclusion of the hearing. The award of the
|
||||||
|
arbitrator, which may include legal and equitable relief, but
|
||||||
|
which may not include punitive damages, will be final and
|
||||||
|
binding upon the disputing Participants, and judgment may be
|
||||||
|
entered upon it in accordance with applicable law in any court
|
||||||
|
having jurisdiction thereof. In addition to award the
|
||||||
|
arbitrator shall have the discretion to award the prevailing
|
||||||
|
Participant all or part of its attorneys' fees and costs,
|
||||||
|
including fees associated with arbitrator, if the arbitrator
|
||||||
|
determines that the positions taken by the other Participant on
|
||||||
|
material issues of the dispute were without substantial
|
||||||
|
foundation. Any conflict between the UNCITRAL Arbitration Rules
|
||||||
|
and the provisions of this GPA shall be controlled by this GPA.
|
||||||
|
|
||||||
|
21. INTEGRATED AGREEMENT. This GPA, constitutes the complete
|
||||||
|
integrated agreement between the parties concerning the subject matter
|
||||||
|
hereof. All prior and contemporaneous agreements, understandings,
|
||||||
|
negotiations or representations, whether oral or in writing, relating to
|
||||||
|
the subject matter of this GPA are superseded and canceled in their
|
||||||
|
entirety.
|
||||||
|
|
||||||
|
22. WAIVER. No waiver of any of the provisions of this GPA shall be
|
||||||
|
deemed or shall constitute a waiver of any other provision of this GPA,
|
||||||
|
whether or not similar, nor shall such waiver constitute a continuing
|
||||||
|
waiver unless otherwise expressly so provided in writing. The failure
|
||||||
|
of either party to enforce at any time any of the provisions of this
|
||||||
|
GPA, or the failure to require at any time performance by either party
|
||||||
|
of any of the provisions of this GPA, shall in no way be construed to be
|
||||||
|
a present or future waiver of such provisions, nor in any way affect the
|
||||||
|
ability of a Participant to enforce each and every such provision
|
||||||
|
thereafter.
|
||||||
|
|
||||||
|
23. INDEPENDENT CONTRACTORS. Nothing in this GPA shall make the
|
||||||
|
Parties partners, joint venturers, or otherwise associated in or with
|
||||||
|
the business of the other. Parties are, and shall always remain,
|
||||||
|
independent contractors. No Participant shall be liable for any debts,
|
||||||
|
accounts, obligations, or other liabilities of the other Participant,
|
||||||
|
its agents or employees. No party is authorized to incur debts or other
|
||||||
|
obligations of any kind on the part of or as agent for the other. This
|
||||||
|
GPA is not a franchise agreement and does not create a franchise
|
||||||
|
relationship between the parties, and if any provision of this GPA is
|
||||||
|
deemed to create a franchise between the parties, then this GPA shall
|
||||||
|
automatically terminate.
|
||||||
|
|
||||||
|
24. CAPTIONS AND HEADINGS. The captions and headings used in this GPA
|
||||||
|
are used for convenience only and are not to be given any legal effect.
|
||||||
|
|
||||||
|
25. EXECUTION. This GPA may be executed in counterparts, each of which
|
||||||
|
so executed will be deemed to be an original and such counterparts
|
||||||
|
together will constitute one and the same Agreement. The Parties shall
|
||||||
|
transmit to each other a signed copy of the GPA by any means that
|
||||||
|
faithfully reproduces the GPA along with the Signature. For purposes of
|
||||||
|
this GPA, the term "signature" shall include digital signatures as
|
||||||
|
defined by the jurisdiction of the Participant signing the GPA.
|
||||||
|
|
||||||
|
Exhibit A
|
||||||
|
|
||||||
|
Weight Range Requirements
|
||||||
|
|
||||||
|
0-99 May only be used under authorization of Owner
|
||||||
|
|
||||||
|
100-199 May only be used by the Owner's service
|
||||||
|
provider, regardless of authorization.
|
||||||
|
|
||||||
|
200-299 Reserved -- do not use for e164 context.
|
||||||
|
|
||||||
|
300-399 May only be used by the owner of the code under
|
||||||
|
which the Owner's number is a part of.
|
||||||
|
|
||||||
|
400-499 May be used by any entity providing access via
|
||||||
|
direct connectivity to the Public Switched
|
||||||
|
Telephone Network.
|
||||||
|
|
||||||
|
500-599 May be used by any entity providing access via
|
||||||
|
indirect connectivity to the Public Switched
|
||||||
|
Telephone Network (e.g. Via another VoIP
|
||||||
|
provider)
|
||||||
|
|
||||||
|
600- Reserved-- do not use for e164 context.
|
||||||
|
|
||||||
|
Participant Participant
|
||||||
|
|
||||||
|
Company:
|
||||||
|
|
||||||
|
Address:
|
||||||
|
|
||||||
|
Email:
|
||||||
|
|
||||||
|
|
||||||
|
_________________________ _________________________
|
||||||
|
Authorized Signature Authorized Signature
|
||||||
|
|
||||||
|
Name:
|
||||||
|
|
||||||
|
|
||||||
|
END OF GENERAL PEERING AGREEMENT
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
How to Peer using this GPA If you wish to exchange routing information
|
||||||
|
with parties using the e164 DUNDi context, all you must do is execute
|
||||||
|
this GPA with any member of the Peering System and you will become a
|
||||||
|
member of the Peering System and be able to make Routes available in
|
||||||
|
accordance with this GPA.
|
||||||
|
|
||||||
|
DUNDi, IAX, Asterisk and GPA are trademarks of Digium, Inc.
|
26
doc/README.dundi
Executable file
26
doc/README.dundi
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
Distributed Universal Number Directory (DUNDi) (tm)
|
||||||
|
===================================================
|
||||||
|
http://www.dundi.com
|
||||||
|
Mark Spencer, Digium, Inc.
|
||||||
|
|
||||||
|
DUNDi is essentially a trusted, peer-to-peer system for being able to
|
||||||
|
call any phone number from the Internet. DUNDi works by creating a
|
||||||
|
network of nodes called the "DUNDi E.164 Trust Group" which are bound by
|
||||||
|
a common peering agreement known as the General Peering Agreement or
|
||||||
|
GPA. The GPA legally binds the members of the Trust Group to provide
|
||||||
|
good-faith accurate information to the other nodes on the network, and
|
||||||
|
provides standards by which the community can insure the integrity of
|
||||||
|
the information on the nodes themselves. Unlike ENUM or similar
|
||||||
|
systems, DUNDi is explicitly designed to preclude any necessity for a
|
||||||
|
single centralized system which could be a source of fees, regulation,
|
||||||
|
etc.
|
||||||
|
|
||||||
|
You can find the PEERING agreement in the doc directory.
|
||||||
|
|
||||||
|
Much less dramatically, DUNDi can also be used within a private
|
||||||
|
enterprise to share a dialplan efficiently between multiple nodes,
|
||||||
|
without incuring a risk of a single point of failure. In this way,
|
||||||
|
administrators can locally add extensions which become immediately
|
||||||
|
available to the other nodes in the system.
|
||||||
|
|
||||||
|
For more information visit http://www.dundi.com
|
186
include/asterisk/dundi.h
Executable file
186
include/asterisk/dundi.h
Executable file
@@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Distributed Universal Number Discovery (DUNDi)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004, Digium Inc.
|
||||||
|
*
|
||||||
|
* Written by Mark Spencer <markster@digium.com>
|
||||||
|
*
|
||||||
|
* This program is Free Software distributed under the terms of
|
||||||
|
* of the GNU General Public License.
|
||||||
|
*/
|
||||||
|
#ifndef _ASTERISK_DUNDI_H
|
||||||
|
#define _ASTERISK_DUNDI_H
|
||||||
|
|
||||||
|
#include <asterisk/channel.h>
|
||||||
|
|
||||||
|
#define DUNDI_PORT 4520
|
||||||
|
|
||||||
|
/* A DUNDi Entity ID is essentially a MAC address, brief and unique */
|
||||||
|
struct _dundi_eid {
|
||||||
|
unsigned char eid[6];
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
typedef struct _dundi_eid dundi_eid;
|
||||||
|
|
||||||
|
struct dundi_hdr {
|
||||||
|
unsigned short strans; /* Source transaction */
|
||||||
|
unsigned short dtrans; /* Destination transaction */
|
||||||
|
unsigned char iseqno; /* Next expected incoming sequence number */
|
||||||
|
unsigned char oseqno; /* Outgoing sequence number */
|
||||||
|
unsigned char cmdresp; /* Command / Response */
|
||||||
|
unsigned char cmdflags; /* Command / Response specific flags*/
|
||||||
|
unsigned char ies[0];
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct dundi_ie_hdr {
|
||||||
|
unsigned char ie;
|
||||||
|
unsigned char len;
|
||||||
|
unsigned char iedata[0];
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define DUNDI_FLAG_RETRANS (1 << 16) /* Applies to dtrans */
|
||||||
|
#define DUNDI_FLAG_RESERVED (1 << 16) /* Applies to strans */
|
||||||
|
|
||||||
|
#define DUNDI_PROTO_NONE 0 /* No answer yet */
|
||||||
|
#define DUNDI_PROTO_IAX 1 /* IAX version 2 */
|
||||||
|
#define DUNDI_PROTO_SIP 2 /* Session Initiation Protocol */
|
||||||
|
#define DUNDI_PROTO_H323 3 /* ITU H.323 */
|
||||||
|
|
||||||
|
#define DUNDI_FLAG_NONEXISTANT (0) /* Isn't and can't be a valid number */
|
||||||
|
#define DUNDI_FLAG_EXISTS (1 << 0) /* Is a valid number */
|
||||||
|
#define DUNDI_FLAG_MATCHMORE (1 << 1) /* Might be valid if you add more digits */
|
||||||
|
#define DUNDI_FLAG_CANMATCH (1 << 2) /* Might be a match */
|
||||||
|
#define DUNDI_FLAG_IGNOREPAT (1 << 3) /* Keep dialtone */
|
||||||
|
#define DUNDI_FLAG_RESIDENTIAL (1 << 4) /* Destination known to be residential */
|
||||||
|
#define DUNDI_FLAG_COMMERCIAL (1 << 5) /* Destination known to be commercial */
|
||||||
|
#define DUNDI_FLAG_MOBILE (1 << 6) /* Destination known to be cellular/mobile */
|
||||||
|
#define DUNDI_FLAG_NOUNSOLICITED (1 << 7) /* No unsolicited calls of any kind through this route */
|
||||||
|
#define DUNDI_FLAG_NOCOMUNSOLICIT (1 << 8) /* No commercial unsolicited calls through this route */
|
||||||
|
|
||||||
|
#define DUNDI_HINT_NONE (0)
|
||||||
|
#define DUNDI_HINT_TTL_EXPIRED (1 << 0) /* TTL Expired */
|
||||||
|
#define DUNDI_HINT_DONT_ASK (1 << 1) /* Don't ask for anything beginning with data */
|
||||||
|
#define DUNDI_HINT_UNAFFECTED (1 << 2) /* Answer not affected by entity list */
|
||||||
|
|
||||||
|
struct dundi_encblock { /* AES-128 encrypted block */
|
||||||
|
unsigned char iv[16]; /* Initialization vector of random data */
|
||||||
|
unsigned char encdata[0]; /* Encrypted / compressed data */
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct dundi_answer {
|
||||||
|
dundi_eid eid; /* Original source of answer */
|
||||||
|
unsigned char protocol; /* Protocol (DUNDI_PROTO_*) */
|
||||||
|
unsigned short flags; /* Flags relating to answer */
|
||||||
|
unsigned short weight; /* Weight of answers */
|
||||||
|
unsigned char data[0]; /* Protocol specific URI */
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct dundi_hint {
|
||||||
|
unsigned short flags; /* Flags relating to answer */
|
||||||
|
unsigned char data[0]; /* For data for hint */
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define DUNDI_CAUSE_SUCCESS 0 /* Success */
|
||||||
|
#define DUNDI_CAUSE_GENERAL 1 /* General unspecified failure */
|
||||||
|
#define DUNDI_CAUSE_DYNAMIC 2 /* Requested entity is dynamic */
|
||||||
|
#define DUNDI_CAUSE_NOAUTH 3 /* No or improper authorization */
|
||||||
|
#define DUNDI_CAUSE_DUPLICATE 4 /* Duplicate request */
|
||||||
|
#define DUNDI_CAUSE_TTL_EXPIRED 5 /* Expired TTL */
|
||||||
|
#define DUNDI_CAUSE_NEEDKEY 6 /* Need new session key to decode */
|
||||||
|
#define DUNDI_CAUSE_BADENCRYPT 7 /* Badly encrypted data */
|
||||||
|
|
||||||
|
struct dundi_cause {
|
||||||
|
unsigned char causecode; /* Numerical cause (DUNDI_CAUSE_*) */
|
||||||
|
char desc[0]; /* Textual description */
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define DUNDI_COMMAND_FINAL (0x80) /* Or'd with other flags */
|
||||||
|
|
||||||
|
#define DUNDI_COMMAND_ACK (0 | 0x40) /* Ack a message */
|
||||||
|
#define DUNDI_COMMAND_DPDISCOVER 1 /* Request discovery */
|
||||||
|
#define DUNDI_COMMAND_DPRESPONSE (2 | 0x40) /* Respond to a discovery request */
|
||||||
|
#define DUNDI_COMMAND_EIDQUERY 3 /* Request information for a peer */
|
||||||
|
#define DUNDI_COMMAND_EIDRESPONSE (4 | 0x40) /* Response to a peer query */
|
||||||
|
#define DUNDI_COMMAND_INVALID (7 | 0x40) /* Invalid dialog state (does not require ack) */
|
||||||
|
#define DUNDI_COMMAND_UNKNOWN (8 | 0x40) /* Unknown command */
|
||||||
|
#define DUNDI_COMMAND_NULL 9 /* No-op */
|
||||||
|
#define DUNDI_COMMAND_REGREQ (10) /* Register Request */
|
||||||
|
#define DUNDI_COMMAND_REGRESPONSE (11 | 0x40) /* Register Response */
|
||||||
|
#define DUNDI_COMMAND_CANCEL (12) /* Cancel transaction entirely */
|
||||||
|
#define DUNDI_COMMAND_ENCRYPT (13) /* Send an encrypted message */
|
||||||
|
#define DUNDI_COMMAND_ENCREJ (14 | 0x40) /* Reject an encrypted message */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remember that some information elements may occur
|
||||||
|
* more than one time within a message
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DUNDI_IE_EID 1 /* Entity identifier (dundi_eid) */
|
||||||
|
#define DUNDI_IE_CALLED_CONTEXT 2 /* DUNDi Context (string) */
|
||||||
|
#define DUNDI_IE_CALLED_NUMBER 3 /* Number of equivalent (string) */
|
||||||
|
#define DUNDI_IE_EID_DIRECT 4 /* Entity identifier (dundi_eid), direct connect */
|
||||||
|
#define DUNDI_IE_ANSWER 5 /* An answer (struct dundi_answer) */
|
||||||
|
#define DUNDI_IE_TTL 6 /* Max TTL for this request / Remaining TTL for the response (short)*/
|
||||||
|
#define DUNDI_IE_VERSION 10 /* DUNDi version (should be 1) (short) */
|
||||||
|
#define DUNDI_IE_EXPIRATION 11 /* Recommended expiration (short) */
|
||||||
|
#define DUNDI_IE_UNKNOWN 12 /* Unknown command (byte) */
|
||||||
|
#define DUNDI_IE_CAUSE 14 /* Success or cause of failure */
|
||||||
|
#define DUNDI_IE_REQEID 15 /* EID being requested for EIDQUERY*/
|
||||||
|
#define DUNDI_IE_ENCDATA 16 /* AES-128 encrypted data */
|
||||||
|
#define DUNDI_IE_SHAREDKEY 17 /* RSA encrypted AES-128 key */
|
||||||
|
#define DUNDI_IE_SIGNATURE 18 /* RSA Signature of encrypted shared key */
|
||||||
|
#define DUNDI_IE_KEYCRC32 19 /* CRC32 of encrypted key (int) */
|
||||||
|
#define DUNDI_IE_HINT 20 /* Answer hints (struct ast_hint) */
|
||||||
|
|
||||||
|
#define DUNDI_IE_DEPARTMENT 21 /* Department, for EIDQUERY (string) */
|
||||||
|
#define DUNDI_IE_ORGANIZATION 22 /* Organization, for EIDQUERY (string) */
|
||||||
|
#define DUNDI_IE_LOCALITY 23 /* City/Locality, for EIDQUERY (string) */
|
||||||
|
#define DUNDI_IE_STATE_PROV 24 /* State/Province, for EIDQUERY (string) */
|
||||||
|
#define DUNDI_IE_COUNTRY 25 /* Country, for EIDQUERY (string) */
|
||||||
|
#define DUNDI_IE_EMAIL 26 /* E-mail addy, for EIDQUERY (string) */
|
||||||
|
#define DUNDI_IE_PHONE 27 /* Contact Phone, for EIDQUERY (string) */
|
||||||
|
#define DUNDI_IE_IPADDR 28 /* IP Address, for EIDQUERY (string) */
|
||||||
|
|
||||||
|
#define DUNDI_FLUFF_TIME 2000 /* Amount of time for answer */
|
||||||
|
#define DUNDI_TTL_TIME 200 /* Incremental average time */
|
||||||
|
|
||||||
|
#define DUNDI_DEFAULT_RETRANS 5
|
||||||
|
#define DUNDI_DEFAULT_RETRANS_TIMER 1000
|
||||||
|
#define DUNDI_DEFAULT_TTL 120 /* In seconds/hops like TTL */
|
||||||
|
#define DUNDI_DEFAULT_VERSION 1
|
||||||
|
#define DUNDI_DEFAULT_CACHE_TIME 3600 /* In seconds */
|
||||||
|
#define DUNDI_DEFAULT_KEY_EXPIRE 3600 /* Life of shared key In seconds */
|
||||||
|
#define DUNDI_DEF_EMPTY_CACHE_TIME 60 /* In seconds, cache of empty answer */
|
||||||
|
#define DUNDI_WINDOW 1 /* Max 1 message in window */
|
||||||
|
|
||||||
|
#define DEFAULT_MAXMS 2000
|
||||||
|
|
||||||
|
struct dundi_result {
|
||||||
|
int flags;
|
||||||
|
int weight;
|
||||||
|
int expiration;
|
||||||
|
int techint;
|
||||||
|
dundi_eid eid;
|
||||||
|
char eid_str[20];
|
||||||
|
char tech[10];
|
||||||
|
char dest[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dundi_entity_info {
|
||||||
|
char country[80];
|
||||||
|
char stateprov[80];
|
||||||
|
char locality[80];
|
||||||
|
char org[80];
|
||||||
|
char orgunit[80];
|
||||||
|
char email[80];
|
||||||
|
char phone[80];
|
||||||
|
char ipaddr[80];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Lookup the given number in the given dundi context (or e164 if unspecified) using the given callerid (if specified) and return up to maxret results in the array specified.
|
||||||
|
returns the number of results found or -1 on a hangup of teh channel. */
|
||||||
|
int dundi_lookup(struct dundi_result *result, int maxret, struct ast_channel *chan, const char *dcontext, const char *number);
|
||||||
|
|
||||||
|
/* Retrieve information on a specific EID */
|
||||||
|
int dundi_query_eid(struct dundi_entity_info *dei, const char *dcontext, dundi_eid eid);
|
||||||
|
#endif /* _ASTERISK_DUNDI_H */
|
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
PBX_LIBS=pbx_config.so pbx_spool.so # pbx_gtkconsole.so pbx_kdeconsole.so
|
PBX_LIBS=pbx_config.so pbx_spool.so pbx_dundi.so
|
||||||
|
|
||||||
# Add GTK console if appropriate
|
# Add GTK console if appropriate
|
||||||
#PBX_LIBS+=$(shell gtk-config --cflags >/dev/null 2>/dev/null && echo "pbx_gtkconsole.so")
|
#PBX_LIBS+=$(shell gtk-config --cflags >/dev/null 2>/dev/null && echo "pbx_gtkconsole.so")
|
||||||
@@ -55,6 +55,9 @@ pbx_kdeconsole_main.o: pbx_kdeconsole_main.cc pbx_kdeconsole.h
|
|||||||
pbx_kdeconsole.so: $(KDE_CONSOLE_OBJS)
|
pbx_kdeconsole.so: $(KDE_CONSOLE_OBJS)
|
||||||
$(CC) $(SOLINK) -o $@ $(KDE_CONSOLE_OBJS) $(KDE_LIBS)
|
$(CC) $(SOLINK) -o $@ $(KDE_CONSOLE_OBJS) $(KDE_LIBS)
|
||||||
|
|
||||||
|
pbx_dundi.so: dundi-parser.o pbx_dundi.o
|
||||||
|
$(CC) $(SOLINK) -o $@ pbx_dundi.o dundi-parser.o -lz
|
||||||
|
|
||||||
%.moc : %.h
|
%.moc : %.h
|
||||||
$(MOC) $< -o $@
|
$(MOC) $< -o $@
|
||||||
|
|
||||||
|
802
pbx/dundi-parser.c
Executable file
802
pbx/dundi-parser.c
Executable file
@@ -0,0 +1,802 @@
|
|||||||
|
/*
|
||||||
|
* Distributed Universal Number Discovery (DUNDi)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004, Digium Inc.
|
||||||
|
*
|
||||||
|
* Written by Mark Spencer <markster@digium.com>
|
||||||
|
*
|
||||||
|
* This program is Free Software distributed under the terms of
|
||||||
|
* of the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <asterisk/frame.h>
|
||||||
|
#include <asterisk/utils.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <asterisk/dundi.h>
|
||||||
|
#include "dundi-parser.h"
|
||||||
|
#include <asterisk/dundi.h>
|
||||||
|
static void internaloutput(const char *str)
|
||||||
|
{
|
||||||
|
printf(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void internalerror(const char *str)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "WARNING: %s", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void (*outputf)(const char *str) = internaloutput;
|
||||||
|
static void (*errorf)(const char *str) = internalerror;
|
||||||
|
|
||||||
|
char *dundi_eid_to_str(char *s, int maxlen, dundi_eid *eid)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
char *os = s;
|
||||||
|
if (maxlen < 18) {
|
||||||
|
if (s && (maxlen > 0))
|
||||||
|
*s = '\0';
|
||||||
|
} else {
|
||||||
|
for (x=0;x<5;x++) {
|
||||||
|
sprintf(s, "%02x:", eid->eid[x]);
|
||||||
|
s += 3;
|
||||||
|
}
|
||||||
|
sprintf(s, "%02x", eid->eid[5]);
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
char *os = s;
|
||||||
|
if (maxlen < 13) {
|
||||||
|
if (s && (maxlen > 0))
|
||||||
|
*s = '\0';
|
||||||
|
} else {
|
||||||
|
for (x=0;x<6;x++) {
|
||||||
|
sprintf(s, "%02X", eid->eid[x]);
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_str_to_eid(dundi_eid *eid, char *s)
|
||||||
|
{
|
||||||
|
unsigned int eid_int[6];
|
||||||
|
int x;
|
||||||
|
if (sscanf(s, "%x:%x:%x:%x:%x:%x", &eid_int[0], &eid_int[1], &eid_int[2],
|
||||||
|
&eid_int[3], &eid_int[4], &eid_int[5]) != 6)
|
||||||
|
return -1;
|
||||||
|
for (x=0;x<6;x++)
|
||||||
|
eid->eid[x] = eid_int[x];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_str_short_to_eid(dundi_eid *eid, char *s)
|
||||||
|
{
|
||||||
|
unsigned int eid_int[6];
|
||||||
|
int x;
|
||||||
|
if (sscanf(s, "%2x%2x%2x%2x%2x%2x", &eid_int[0], &eid_int[1], &eid_int[2],
|
||||||
|
&eid_int[3], &eid_int[4], &eid_int[5]) != 6)
|
||||||
|
return -1;
|
||||||
|
for (x=0;x<6;x++)
|
||||||
|
eid->eid[x] = eid_int[x];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int dundi_eid_zero(dundi_eid *eid)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x=0;x<sizeof(eid->eid) / sizeof(eid->eid[0]);x++)
|
||||||
|
if (eid->eid[x]) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_eid_cmp(dundi_eid *eid1, dundi_eid *eid2)
|
||||||
|
{
|
||||||
|
return memcmp(eid1, eid2, sizeof(dundi_eid));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_string(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
maxlen--;
|
||||||
|
if (maxlen > len)
|
||||||
|
maxlen = len;
|
||||||
|
strncpy(output,value, maxlen);
|
||||||
|
output[maxlen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_eid(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
if (len == 6)
|
||||||
|
dundi_eid_to_str(output, maxlen, (dundi_eid *)value);
|
||||||
|
else
|
||||||
|
snprintf(output, maxlen, "Invalid EID len %d", len);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dundi_hint2str(char *buf, int bufsiz, int flags)
|
||||||
|
{
|
||||||
|
strcpy(buf, "");
|
||||||
|
buf[bufsiz-1] = '\0';
|
||||||
|
if (flags & DUNDI_HINT_TTL_EXPIRED) {
|
||||||
|
strncat(buf, "TTLEXPIRED|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_HINT_DONT_ASK) {
|
||||||
|
strncat(buf, "DONTASK|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_HINT_UNAFFECTED) {
|
||||||
|
strncat(buf, "UNAFFECTED|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
/* Get rid of trailing | */
|
||||||
|
if (ast_strlen_zero(buf))
|
||||||
|
strcpy(buf, "NONE|");
|
||||||
|
buf[strlen(buf)-1] = '\0';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_hint(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
unsigned short flags;
|
||||||
|
char tmp[512];
|
||||||
|
char tmp2[256];
|
||||||
|
if (len < 2) {
|
||||||
|
strncpy(output, "<invalid contents>", maxlen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(&flags, value, sizeof(flags));
|
||||||
|
flags = ntohs(flags);
|
||||||
|
memset(tmp, 0, sizeof(tmp));
|
||||||
|
dundi_hint2str(tmp2, sizeof(tmp2), flags);
|
||||||
|
snprintf(tmp, sizeof(tmp), "[%s] ", tmp2);
|
||||||
|
memcpy(tmp + strlen(tmp), value + 2, len - 2);
|
||||||
|
strncpy(output, tmp, maxlen - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_cause(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
static char *causes[] = {
|
||||||
|
"SUCCESS",
|
||||||
|
"GENERAL",
|
||||||
|
"DYNAMIC",
|
||||||
|
"NOAUTH" ,
|
||||||
|
};
|
||||||
|
char tmp[256];
|
||||||
|
char tmp2[256];
|
||||||
|
int mlen;
|
||||||
|
unsigned char cause;
|
||||||
|
if (len < 1) {
|
||||||
|
strncpy(output, "<invalid contents>", maxlen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cause = *((unsigned char *)value);
|
||||||
|
memset(tmp2, 0, sizeof(tmp2));
|
||||||
|
mlen = len - 1;
|
||||||
|
if (mlen > 255)
|
||||||
|
mlen = 255;
|
||||||
|
memcpy(tmp2, value + 1, mlen);
|
||||||
|
if (cause < sizeof(causes) / sizeof(causes[0])) {
|
||||||
|
if (len > 1)
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s: %s", causes[cause], tmp2);
|
||||||
|
else
|
||||||
|
snprintf(tmp, sizeof(tmp), "%s", causes[cause]);
|
||||||
|
} else {
|
||||||
|
if (len > 1)
|
||||||
|
snprintf(tmp, sizeof(tmp), "%d: %s", cause, tmp2);
|
||||||
|
else
|
||||||
|
snprintf(tmp, sizeof(tmp), "%d", cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(output,tmp, maxlen);
|
||||||
|
output[maxlen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_int(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
if (len == (int)sizeof(unsigned int))
|
||||||
|
snprintf(output, maxlen, "%lu", (unsigned long)ntohl(*((unsigned int *)value)));
|
||||||
|
else
|
||||||
|
snprintf(output, maxlen, "Invalid INT");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_short(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
if (len == (int)sizeof(unsigned short))
|
||||||
|
snprintf(output, maxlen, "%d", ntohs(*((unsigned short *)value)));
|
||||||
|
else
|
||||||
|
snprintf(output, maxlen, "Invalid SHORT");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_byte(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
if (len == (int)sizeof(unsigned char))
|
||||||
|
snprintf(output, maxlen, "%d", *((unsigned char *)value));
|
||||||
|
else
|
||||||
|
snprintf(output, maxlen, "Invalid BYTE");
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *proto2str(int proto, char *buf, int bufsiz)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch(proto) {
|
||||||
|
case DUNDI_PROTO_NONE:
|
||||||
|
strncpy(buf, "None", bufsiz - 1);
|
||||||
|
break;
|
||||||
|
case DUNDI_PROTO_IAX:
|
||||||
|
strncpy(buf, "IAX", bufsiz - 1);
|
||||||
|
break;
|
||||||
|
case DUNDI_PROTO_SIP:
|
||||||
|
strncpy(buf, "SIP", bufsiz - 1);
|
||||||
|
break;
|
||||||
|
case DUNDI_PROTO_H323:
|
||||||
|
strncpy(buf, "H.323", bufsiz - 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snprintf(buf, bufsiz, "Unknown Proto(%d)", proto);
|
||||||
|
}
|
||||||
|
buf[bufsiz-1] = '\0';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dundi_flags2str(char *buf, int bufsiz, int flags)
|
||||||
|
{
|
||||||
|
strcpy(buf, "");
|
||||||
|
buf[bufsiz-1] = '\0';
|
||||||
|
if (flags & DUNDI_FLAG_EXISTS) {
|
||||||
|
strncat(buf, "EXISTS|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_FLAG_MATCHMORE) {
|
||||||
|
strncat(buf, "MATCHMORE|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_FLAG_CANMATCH) {
|
||||||
|
strncat(buf, "CANMATCH|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_FLAG_IGNOREPAT) {
|
||||||
|
strncat(buf, "IGNOREPAT|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_FLAG_RESIDENTIAL) {
|
||||||
|
strncat(buf, "RESIDENCE|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_FLAG_COMMERCIAL) {
|
||||||
|
strncat(buf, "COMMERCIAL|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_FLAG_MOBILE) {
|
||||||
|
strncat(buf, "MOBILE", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_FLAG_NOUNSOLICITED) {
|
||||||
|
strncat(buf, "NOUNSLCTD|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
if (flags & DUNDI_FLAG_NOCOMUNSOLICIT) {
|
||||||
|
strncat(buf, "NOCOMUNSLTD|", bufsiz - strlen(buf) - 1);
|
||||||
|
}
|
||||||
|
/* Get rid of trailing | */
|
||||||
|
if (ast_strlen_zero(buf))
|
||||||
|
strcpy(buf, "NONE|");
|
||||||
|
buf[strlen(buf)-1] = '\0';
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_answer(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
struct dundi_answer *answer;
|
||||||
|
char proto[40];
|
||||||
|
char flags[40];
|
||||||
|
char eid_str[40];
|
||||||
|
char tmp[512]="";
|
||||||
|
if (len >= 10) {
|
||||||
|
answer = (struct dundi_answer *)(value);
|
||||||
|
memcpy(tmp, answer->data, (len >= 500) ? 500 : len - 10);
|
||||||
|
dundi_eid_to_str(eid_str, sizeof(eid_str), &answer->eid);
|
||||||
|
snprintf(output, maxlen, "[%s] %d <%s/%s> from [%s]",
|
||||||
|
dundi_flags2str(flags, sizeof(flags), ntohs(answer->flags)),
|
||||||
|
ntohs(answer->weight),
|
||||||
|
proto2str(answer->protocol, proto, sizeof(proto)),
|
||||||
|
tmp, eid_str);
|
||||||
|
} else
|
||||||
|
strncpy(output, "Invalid Answer", maxlen - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_encrypted(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
char iv[33];
|
||||||
|
int x;
|
||||||
|
if ((len > 16) && !(len % 16)) {
|
||||||
|
/* Build up IV */
|
||||||
|
for (x=0;x<16;x++) {
|
||||||
|
snprintf(iv + (x << 1), 3, "%02x", ((unsigned char *)value)[x]);
|
||||||
|
}
|
||||||
|
snprintf(output, maxlen, "[IV %s] %d encrypted blocks\n", iv, len / 16);
|
||||||
|
} else
|
||||||
|
snprintf(output, maxlen, "Invalid Encrypted Datalen %d", len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_raw(char *output, int maxlen, void *value, int len)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
unsigned char *u = value;
|
||||||
|
output[maxlen - 1] = '\0';
|
||||||
|
strcpy(output, "[ ");
|
||||||
|
for (x=0;x<len;x++) {
|
||||||
|
snprintf(output + strlen(output), maxlen - strlen(output) - 1, "%02x ", u[x]);
|
||||||
|
}
|
||||||
|
strncat(output + strlen(output), "]", maxlen - strlen(output) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dundi_ie {
|
||||||
|
int ie;
|
||||||
|
char *name;
|
||||||
|
void (*dump)(char *output, int maxlen, void *value, int len);
|
||||||
|
} ies[] = {
|
||||||
|
{ DUNDI_IE_EID, "ENTITY IDENT", dump_eid },
|
||||||
|
{ DUNDI_IE_CALLED_CONTEXT, "CALLED CONTEXT", dump_string },
|
||||||
|
{ DUNDI_IE_CALLED_NUMBER, "CALLED NUMBER", dump_string },
|
||||||
|
{ DUNDI_IE_EID_DIRECT, "DIRECT EID", dump_eid },
|
||||||
|
{ DUNDI_IE_ANSWER, "ANSWER", dump_answer },
|
||||||
|
{ DUNDI_IE_TTL, "TTL", dump_short },
|
||||||
|
{ DUNDI_IE_VERSION, "VERSION", dump_short },
|
||||||
|
{ DUNDI_IE_EXPIRATION, "EXPIRATION", dump_short },
|
||||||
|
{ DUNDI_IE_UNKNOWN, "UKWN DUNDI CMD", dump_byte },
|
||||||
|
{ DUNDI_IE_CAUSE, "CAUSE", dump_cause },
|
||||||
|
{ DUNDI_IE_REQEID, "REQUEST EID", dump_eid },
|
||||||
|
{ DUNDI_IE_ENCDATA, "ENCDATA", dump_encrypted },
|
||||||
|
{ DUNDI_IE_SHAREDKEY, "SHAREDKEY", dump_raw },
|
||||||
|
{ DUNDI_IE_SIGNATURE, "SIGNATURE", dump_raw },
|
||||||
|
{ DUNDI_IE_KEYCRC32, "KEYCRC32", dump_int },
|
||||||
|
{ DUNDI_IE_HINT, "HINT", dump_hint },
|
||||||
|
{ DUNDI_IE_DEPARTMENT, "DEPARTMENT", dump_string },
|
||||||
|
{ DUNDI_IE_ORGANIZATION, "ORGANIZTN", dump_string },
|
||||||
|
{ DUNDI_IE_LOCALITY, "LOCALITY", dump_string },
|
||||||
|
{ DUNDI_IE_STATE_PROV, "STATEPROV", dump_string },
|
||||||
|
{ DUNDI_IE_COUNTRY, "COUNTRY", dump_string },
|
||||||
|
{ DUNDI_IE_EMAIL, "EMAIL", dump_string },
|
||||||
|
{ DUNDI_IE_PHONE, "PHONE", dump_string },
|
||||||
|
{ DUNDI_IE_IPADDR, "ADDRESS", dump_string },
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *dundi_ie2str(int ie)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
|
||||||
|
if (ies[x].ie == ie)
|
||||||
|
return ies[x].name;
|
||||||
|
}
|
||||||
|
return "Unknown IE";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_ies(unsigned char *iedata, int spaces, int len)
|
||||||
|
{
|
||||||
|
int ielen;
|
||||||
|
int ie;
|
||||||
|
int x;
|
||||||
|
int found;
|
||||||
|
char interp[1024];
|
||||||
|
char tmp[1024];
|
||||||
|
if (len < 2)
|
||||||
|
return;
|
||||||
|
while(len > 2) {
|
||||||
|
ie = iedata[0];
|
||||||
|
ielen = iedata[1];
|
||||||
|
/* Encrypted data is the remainder */
|
||||||
|
if (ie == DUNDI_IE_ENCDATA)
|
||||||
|
ielen = len - 2;
|
||||||
|
if (ielen + 2> len) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Total IE length of %d bytes exceeds remaining frame length of %d bytes\n", ielen + 2, len);
|
||||||
|
outputf(tmp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
found = 0;
|
||||||
|
for (x=0;x<(int)sizeof(ies) / (int)sizeof(ies[0]); x++) {
|
||||||
|
if (ies[x].ie == ie) {
|
||||||
|
if (ies[x].dump) {
|
||||||
|
ies[x].dump(interp, (int)sizeof(interp), iedata + 2, ielen);
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), " %s%-15.15s : %s\n", (spaces ? " " : "" ), ies[x].name, interp);
|
||||||
|
outputf(tmp);
|
||||||
|
} else {
|
||||||
|
if (ielen)
|
||||||
|
snprintf(interp, (int)sizeof(interp), "%d bytes", ielen);
|
||||||
|
else
|
||||||
|
strcpy(interp, "Present");
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), " %s%-15.15s : %s\n", (spaces ? " " : "" ), ies[x].name, interp);
|
||||||
|
outputf(tmp);
|
||||||
|
}
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), " %sUnknown IE %03d : Present\n", (spaces ? " " : "" ), ie);
|
||||||
|
outputf(tmp);
|
||||||
|
}
|
||||||
|
iedata += (2 + ielen);
|
||||||
|
len -= (2 + ielen);
|
||||||
|
}
|
||||||
|
outputf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)
|
||||||
|
{
|
||||||
|
char *pref[] = {
|
||||||
|
"Tx",
|
||||||
|
"Rx",
|
||||||
|
" ETx",
|
||||||
|
" Erx" };
|
||||||
|
char *commands[] = {
|
||||||
|
"ACK ",
|
||||||
|
"DPDISCOVER ",
|
||||||
|
"DPRESPONSE ",
|
||||||
|
"EIDQUERY ",
|
||||||
|
"EIDRESPONSE ",
|
||||||
|
"UNKNOWN (5)?",
|
||||||
|
"UNKNOWN (6)?",
|
||||||
|
"INVALID ",
|
||||||
|
"UNKNOWN CMD ",
|
||||||
|
"NULL ",
|
||||||
|
"REQREQ ",
|
||||||
|
"REGRESPONSE ",
|
||||||
|
"CANCEL ",
|
||||||
|
"ENCRYPT ",
|
||||||
|
"ENCREJ " };
|
||||||
|
char class2[20];
|
||||||
|
char *class;
|
||||||
|
char subclass2[20];
|
||||||
|
char *subclass;
|
||||||
|
char tmp[256];
|
||||||
|
char retries[20];
|
||||||
|
char iabuf[INET_ADDRSTRLEN];
|
||||||
|
if (ntohs(fhi->dtrans) & DUNDI_FLAG_RETRANS)
|
||||||
|
strcpy(retries, "Yes");
|
||||||
|
else
|
||||||
|
strcpy(retries, "No");
|
||||||
|
if ((ntohs(fhi->strans) & DUNDI_FLAG_RESERVED)) {
|
||||||
|
/* Ignore frames with high bit set to 1 */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((fhi->cmdresp & 0x3f) > (int)sizeof(commands)/(int)sizeof(char *)) {
|
||||||
|
snprintf(class2, (int)sizeof(class2), "(%d?)", fhi->cmdresp);
|
||||||
|
class = class2;
|
||||||
|
} else {
|
||||||
|
class = commands[(int)(fhi->cmdresp & 0x3f)];
|
||||||
|
}
|
||||||
|
snprintf(subclass2, (int)sizeof(subclass2), "%02x", fhi->cmdflags);
|
||||||
|
subclass = subclass2;
|
||||||
|
snprintf(tmp, (int)sizeof(tmp),
|
||||||
|
"%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s (%s)\n",
|
||||||
|
pref[rx],
|
||||||
|
retries, fhi->oseqno, fhi->iseqno, class, fhi->cmdresp & 0x40 ? "Response" : "Command");
|
||||||
|
outputf(tmp);
|
||||||
|
snprintf(tmp, (int)sizeof(tmp),
|
||||||
|
"%s Flags: %s STrans: %5.5d DTrans: %5.5d [%s:%d]%s\n", (rx > 1) ? " " : "",
|
||||||
|
subclass, ntohs(fhi->strans) & ~DUNDI_FLAG_RESERVED, ntohs(fhi->dtrans) & ~DUNDI_FLAG_RETRANS,
|
||||||
|
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), ntohs(sin->sin_port),
|
||||||
|
fhi->cmdresp & 0x80 ? " (Final)" : "");
|
||||||
|
outputf(tmp);
|
||||||
|
dump_ies(fhi->ies, rx > 1, datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen)
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
|
||||||
|
errorf(tmp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ied->buf[ied->pos++] = ie;
|
||||||
|
ied->buf[ied->pos++] = datalen;
|
||||||
|
memcpy(ied->buf + ied->pos, data, datalen);
|
||||||
|
ied->pos += datalen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, unsigned char *data)
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
int datalen = data ? strlen(data) + 1 : 1;
|
||||||
|
if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
|
||||||
|
errorf(tmp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ied->buf[ied->pos++] = ie;
|
||||||
|
ied->buf[ied->pos++] = datalen;
|
||||||
|
ied->buf[ied->pos++] = cause;
|
||||||
|
memcpy(ied->buf + ied->pos, data, datalen-1);
|
||||||
|
ied->pos += datalen-1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, unsigned char *data)
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
int datalen = data ? strlen(data) + 2 : 2;
|
||||||
|
if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
|
||||||
|
errorf(tmp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ied->buf[ied->pos++] = ie;
|
||||||
|
ied->buf[ied->pos++] = datalen;
|
||||||
|
flags = htons(flags);
|
||||||
|
memcpy(ied->buf + ied->pos, &flags, sizeof(flags));
|
||||||
|
ied->pos += 2;
|
||||||
|
memcpy(ied->buf + ied->pos, data, datalen-1);
|
||||||
|
ied->pos += datalen-2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen)
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
datalen += 16;
|
||||||
|
if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
|
||||||
|
errorf(tmp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ied->buf[ied->pos++] = ie;
|
||||||
|
ied->buf[ied->pos++] = datalen;
|
||||||
|
memcpy(ied->buf + ied->pos, iv, 16);
|
||||||
|
ied->pos += 16;
|
||||||
|
if (data) {
|
||||||
|
memcpy(ied->buf + ied->pos, data, datalen-16);
|
||||||
|
ied->pos += datalen-16;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, unsigned char *data)
|
||||||
|
{
|
||||||
|
char tmp[256];
|
||||||
|
int datalen = data ? strlen(data) + 11 : 11;
|
||||||
|
int x;
|
||||||
|
unsigned short myw;
|
||||||
|
if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", dundi_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
|
||||||
|
errorf(tmp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ied->buf[ied->pos++] = ie;
|
||||||
|
ied->buf[ied->pos++] = datalen;
|
||||||
|
for (x=0;x<6;x++)
|
||||||
|
ied->buf[ied->pos++] = eid->eid[x];
|
||||||
|
ied->buf[ied->pos++] = protocol;
|
||||||
|
myw = htons(flags);
|
||||||
|
memcpy(ied->buf + ied->pos, &myw, 2);
|
||||||
|
ied->pos += 2;
|
||||||
|
myw = htons(weight);
|
||||||
|
memcpy(ied->buf + ied->pos, &myw, 2);
|
||||||
|
ied->pos += 2;
|
||||||
|
memcpy(ied->buf + ied->pos, data, datalen-11);
|
||||||
|
ied->pos += datalen-11;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin)
|
||||||
|
{
|
||||||
|
return dundi_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value)
|
||||||
|
{
|
||||||
|
unsigned int newval;
|
||||||
|
newval = htonl(value);
|
||||||
|
return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value)
|
||||||
|
{
|
||||||
|
unsigned short newval;
|
||||||
|
newval = htons(value);
|
||||||
|
return dundi_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, unsigned char *str)
|
||||||
|
{
|
||||||
|
return dundi_ie_append_raw(ied, ie, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid)
|
||||||
|
{
|
||||||
|
return dundi_ie_append_raw(ied, ie, (unsigned char *)eid, sizeof(dundi_eid));
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat)
|
||||||
|
{
|
||||||
|
return dundi_ie_append_raw(ied, ie, &dat, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie)
|
||||||
|
{
|
||||||
|
return dundi_ie_append_raw(ied, ie, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dundi_set_output(void (*func)(const char *))
|
||||||
|
{
|
||||||
|
outputf = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dundi_set_error(void (*func)(const char *))
|
||||||
|
{
|
||||||
|
errorf = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen)
|
||||||
|
{
|
||||||
|
/* Parse data into information elements */
|
||||||
|
int len;
|
||||||
|
int ie;
|
||||||
|
char tmp[256];
|
||||||
|
memset(ies, 0, (int)sizeof(struct dundi_ies));
|
||||||
|
ies->ttl = -1;
|
||||||
|
ies->expiration = -1;
|
||||||
|
ies->unknowncmd = -1;
|
||||||
|
ies->cause = -1;
|
||||||
|
while(datalen >= 2) {
|
||||||
|
ie = data[0];
|
||||||
|
len = data[1];
|
||||||
|
if (len > datalen - 2) {
|
||||||
|
errorf("Information element length exceeds message size\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
switch(ie) {
|
||||||
|
case DUNDI_IE_EID:
|
||||||
|
case DUNDI_IE_EID_DIRECT:
|
||||||
|
if (len != (int)sizeof(dundi_eid)) {
|
||||||
|
errorf("Improper entity identifer, expecting 6 bytes!\n");
|
||||||
|
} else if (ies->eidcount < DUNDI_MAX_STACK) {
|
||||||
|
ies->eids[ies->eidcount] = (dundi_eid *)(data + 2);
|
||||||
|
ies->eid_direct[ies->eidcount] = (ie == DUNDI_IE_EID_DIRECT);
|
||||||
|
ies->eidcount++;
|
||||||
|
} else
|
||||||
|
errorf("Too many entities in stack!\n");
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_REQEID:
|
||||||
|
if (len != (int)sizeof(dundi_eid)) {
|
||||||
|
errorf("Improper requested entity identifer, expecting 6 bytes!\n");
|
||||||
|
} else
|
||||||
|
ies->reqeid = (dundi_eid *)(data + 2);
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_CALLED_CONTEXT:
|
||||||
|
ies->called_context = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_CALLED_NUMBER:
|
||||||
|
ies->called_number = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_ANSWER:
|
||||||
|
if (len < sizeof(struct dundi_answer)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Answer expected to be >=%d bytes long but was %d\n", (int)sizeof(struct dundi_answer), len);
|
||||||
|
errorf(tmp);
|
||||||
|
} else {
|
||||||
|
if (ies->anscount < DUNDI_MAX_ANSWERS)
|
||||||
|
ies->answers[ies->anscount++]= (struct dundi_answer *)(data + 2);
|
||||||
|
else
|
||||||
|
errorf("Ignoring extra answers!\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_TTL:
|
||||||
|
if (len != (int)sizeof(unsigned short)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Expecting ttl to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||||
|
errorf(tmp);
|
||||||
|
} else
|
||||||
|
ies->ttl = ntohs(*((unsigned short *)(data + 2)));
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_VERSION:
|
||||||
|
if (len != (int)sizeof(unsigned short)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||||
|
errorf(tmp);
|
||||||
|
} else
|
||||||
|
ies->version = ntohs(*((unsigned short *)(data + 2)));
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_EXPIRATION:
|
||||||
|
if (len != (int)sizeof(unsigned short)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
|
||||||
|
errorf(tmp);
|
||||||
|
} else
|
||||||
|
ies->expiration = ntohs(*((unsigned short *)(data + 2)));
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_KEYCRC32:
|
||||||
|
if (len != (int)sizeof(unsigned int)) {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Expecting expiration to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
|
||||||
|
errorf(tmp);
|
||||||
|
} else
|
||||||
|
ies->keycrc32 = ntohl(*((unsigned int *)(data + 2)));
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_UNKNOWN:
|
||||||
|
if (len == 1)
|
||||||
|
ies->unknowncmd = data[2];
|
||||||
|
else {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
|
||||||
|
errorf(tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_CAUSE:
|
||||||
|
if (len >= 1) {
|
||||||
|
ies->cause = data[2];
|
||||||
|
ies->causestr = data + 3;
|
||||||
|
} else {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Expected at least one byte cause, but was %d long\n", len);
|
||||||
|
errorf(tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_HINT:
|
||||||
|
if (len >= 2) {
|
||||||
|
ies->hint = (struct dundi_hint *)(data + 2);
|
||||||
|
} else {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Expected at least two byte hint, but was %d long\n", len);
|
||||||
|
errorf(tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_DEPARTMENT:
|
||||||
|
ies->q_dept = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_ORGANIZATION:
|
||||||
|
ies->q_org = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_LOCALITY:
|
||||||
|
ies->q_locality = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_STATE_PROV:
|
||||||
|
ies->q_stateprov = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_COUNTRY:
|
||||||
|
ies->q_country = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_EMAIL:
|
||||||
|
ies->q_email = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_PHONE:
|
||||||
|
ies->q_phone = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_IPADDR:
|
||||||
|
ies->q_ipaddr = data + 2;
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_ENCDATA:
|
||||||
|
/* Recalculate len as the remainder of the message, regardless of
|
||||||
|
theoretical length */
|
||||||
|
len = datalen - 2;
|
||||||
|
if ((len > 16) && !(len % 16)) {
|
||||||
|
ies->encblock = (struct dundi_encblock *)(data + 2);
|
||||||
|
ies->enclen = len - 16;
|
||||||
|
} else {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted data length %d\n", len);
|
||||||
|
errorf(tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_SHAREDKEY:
|
||||||
|
if (len == 128) {
|
||||||
|
ies->encsharedkey = (unsigned char *)(data + 2);
|
||||||
|
} else {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted shared key length %d\n", len);
|
||||||
|
errorf(tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DUNDI_IE_SIGNATURE:
|
||||||
|
if (len == 128) {
|
||||||
|
ies->encsig = (unsigned char *)(data + 2);
|
||||||
|
} else {
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Invalid encrypted signature length %d\n", len);
|
||||||
|
errorf(tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", dundi_ie2str(ie), ie, len);
|
||||||
|
outputf(tmp);
|
||||||
|
}
|
||||||
|
/* Overwrite information element with 0, to null terminate previous portion */
|
||||||
|
data[0] = 0;
|
||||||
|
datalen -= (len + 2);
|
||||||
|
data += (len + 2);
|
||||||
|
}
|
||||||
|
/* Null-terminate last field */
|
||||||
|
*data = '\0';
|
||||||
|
if (datalen) {
|
||||||
|
errorf("Invalid information element contents, strange boundary\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
87
pbx/dundi-parser.h
Executable file
87
pbx/dundi-parser.h
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Distributed Universal Number Discovery (DUNDi)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004, Digium Inc.
|
||||||
|
*
|
||||||
|
* Written by Mark Spencer <markster@digium.com>
|
||||||
|
*
|
||||||
|
* This program is Free Software distributed under the terms of
|
||||||
|
* of the GNU General Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DUNDI_PARSER_H
|
||||||
|
#define _DUNDI_PARSER_H
|
||||||
|
|
||||||
|
#include <asterisk/dundi.h>
|
||||||
|
#include <asterisk/aes.h>
|
||||||
|
|
||||||
|
#define DUNDI_MAX_STACK 512
|
||||||
|
#define DUNDI_MAX_ANSWERS 100
|
||||||
|
|
||||||
|
struct dundi_ies {
|
||||||
|
dundi_eid *eids[DUNDI_MAX_STACK + 1];
|
||||||
|
int eid_direct[DUNDI_MAX_STACK + 1];
|
||||||
|
dundi_eid *reqeid;
|
||||||
|
int eidcount;
|
||||||
|
char *called_context;
|
||||||
|
char *called_number;
|
||||||
|
struct dundi_answer *answers[DUNDI_MAX_ANSWERS + 1];
|
||||||
|
struct dundi_hint *hint;
|
||||||
|
int anscount;
|
||||||
|
int ttl;
|
||||||
|
int version;
|
||||||
|
int expiration;
|
||||||
|
int unknowncmd;
|
||||||
|
unsigned char *pubkey;
|
||||||
|
int cause;
|
||||||
|
unsigned char *q_dept;
|
||||||
|
unsigned char *q_org;
|
||||||
|
unsigned char *q_locality;
|
||||||
|
unsigned char *q_stateprov;
|
||||||
|
unsigned char *q_country;
|
||||||
|
unsigned char *q_email;
|
||||||
|
unsigned char *q_phone;
|
||||||
|
unsigned char *q_ipaddr;
|
||||||
|
unsigned char *causestr;
|
||||||
|
unsigned char *encsharedkey;
|
||||||
|
unsigned char *encsig;
|
||||||
|
unsigned long keycrc32;
|
||||||
|
struct dundi_encblock *encblock;
|
||||||
|
int enclen;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dundi_ie_data {
|
||||||
|
int pos;
|
||||||
|
unsigned char buf[8192];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Choose a different function for output */
|
||||||
|
extern void dundi_set_output(void (*output)(const char *data));
|
||||||
|
/* Choose a different function for errors */
|
||||||
|
extern void dundi_set_error(void (*output)(const char *data));
|
||||||
|
extern void dundi_showframe(struct dundi_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen);
|
||||||
|
|
||||||
|
extern const char *dundi_ie2str(int ie);
|
||||||
|
|
||||||
|
extern int dundi_ie_append_raw(struct dundi_ie_data *ied, unsigned char ie, void *data, int datalen);
|
||||||
|
extern int dundi_ie_append_addr(struct dundi_ie_data *ied, unsigned char ie, struct sockaddr_in *sin);
|
||||||
|
extern int dundi_ie_append_int(struct dundi_ie_data *ied, unsigned char ie, unsigned int value);
|
||||||
|
extern int dundi_ie_append_short(struct dundi_ie_data *ied, unsigned char ie, unsigned short value);
|
||||||
|
extern int dundi_ie_append_str(struct dundi_ie_data *ied, unsigned char ie, unsigned char *str);
|
||||||
|
extern int dundi_ie_append_eid(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid);
|
||||||
|
extern int dundi_ie_append_cause(struct dundi_ie_data *ied, unsigned char ie, unsigned char cause, unsigned char *desc);
|
||||||
|
extern int dundi_ie_append_hint(struct dundi_ie_data *ied, unsigned char ie, unsigned short flags, unsigned char *data);
|
||||||
|
extern int dundi_ie_append_answer(struct dundi_ie_data *ied, unsigned char ie, dundi_eid *eid, unsigned char protocol, unsigned short flags, unsigned short weight, unsigned char *desc);
|
||||||
|
extern int dundi_ie_append_encdata(struct dundi_ie_data *ied, unsigned char ie, unsigned char *iv, void *data, int datalen);
|
||||||
|
extern int dundi_ie_append_byte(struct dundi_ie_data *ied, unsigned char ie, unsigned char dat);
|
||||||
|
extern int dundi_ie_append(struct dundi_ie_data *ied, unsigned char ie);
|
||||||
|
extern int dundi_parse_ies(struct dundi_ies *ies, unsigned char *data, int datalen);
|
||||||
|
extern char *dundi_eid_to_str(char *s, int maxlen, dundi_eid *eid);
|
||||||
|
extern char *dundi_eid_to_str_short(char *s, int maxlen, dundi_eid *eid);
|
||||||
|
extern int dundi_str_to_eid(dundi_eid *eid, char *s);
|
||||||
|
extern int dundi_str_short_to_eid(dundi_eid *eid, char *s);
|
||||||
|
extern int dundi_eid_zero(dundi_eid *eid);
|
||||||
|
extern int dundi_eid_cmp(dundi_eid *eid1, dundi_eid *eid2);
|
||||||
|
extern char *dundi_flags2str(char *s, int maxlen, int flags);
|
||||||
|
extern char *dundi_hint2str(char *s, int maxlen, int flags);
|
||||||
|
#endif
|
3827
pbx/pbx_dundi.c
Executable file
3827
pbx/pbx_dundi.c
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user