git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4033 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2-netsec
Mark Spencer 21 years ago
parent 8405193cff
commit 06dfca5d24

@ -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.
;
;
; 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
; 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
;
exten => _9011.,1,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
exten => _9011.,1,Macro(dundi-e164,${EXTEN:4})
exten => _9011.,n,Dial(${TRUNK}/${EXTEN:${TRUNKMSD}})
[trunkld]
;
; 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]
;

@ -199,6 +199,15 @@ context=default
auth=rsa
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
; secret used for connections with that given authentication name.

@ -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.

@ -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

@ -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
#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)
$(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) $< -o $@

@ -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;
}

@ -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

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save