diff options
author | Guy Harris <guy@alum.mit.edu> | 2001-11-01 21:52:44 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2001-11-01 21:52:44 +0000 |
commit | be7e31be0e61566ebad1dadf041487ce2374ba6f (patch) | |
tree | d887bc44e7e8d07cfc681e666b1e805a0f4853b9 | |
parent | f9ff2a9ab31a6b2717016ade3baa8a98ea4e204a (diff) | |
download | wireshark-be7e31be0e61566ebad1dadf041487ce2374ba6f.tar.gz wireshark-be7e31be0e61566ebad1dadf041487ce2374ba6f.tar.bz2 wireshark-be7e31be0e61566ebad1dadf041487ce2374ba6f.zip |
From David Frascone: duUpdate to Diameter dissector to load the
dictionary as an XML file rather than building it in, and various
Diameter updates.
svn path=/trunk/; revision=4122
-rw-r--r-- | Makefile.am | 14 | ||||
-rw-r--r-- | Makefile.nmake | 3 | ||||
-rw-r--r-- | dictionary.dtd | 74 | ||||
-rw-r--r-- | dictionary.xml | 647 | ||||
-rw-r--r-- | mobileipv4.xml | 62 | ||||
-rw-r--r-- | nasreq.xml | 291 | ||||
-rw-r--r-- | packet-diameter-defs.h | 80 | ||||
-rw-r--r-- | packet-diameter.c | 968 | ||||
-rw-r--r-- | sunping.xml | 22 | ||||
-rw-r--r-- | xmlstub.c | 167 | ||||
-rw-r--r-- | xmlstub.h | 1119 |
11 files changed, 3317 insertions, 130 deletions
diff --git a/Makefile.am b/Makefile.am index 37ad19285c..67addd5860 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.372 2001/10/29 21:13:07 guy Exp $ +# $Id: Makefile.am,v 1.373 2001/11/01 21:52:44 guy Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@ethereal.com> @@ -68,7 +68,8 @@ man_MANS = EXTRA_PROGRAMS = ethereal ethereal_static tethereal tethereal_static editcap mergecap dftest text2pcap EXTRA_SCRIPTS = idl2eth -sysconf_DATA = manuf +sysconf_DATA = manuf dictionary.dtd dictionary.xml mobileipv4.xml \ + nasreq.xml sunping.xml DISSECTOR_SRC = \ packet-aarp.c \ @@ -448,7 +449,9 @@ ETHEREAL_COMMON_SRC = \ x11-declarations.h \ x11-register-info.h \ xdlc.c \ - xdlc.h + xdlc.h \ + xmlstub.c \ + xmlstub.h BUILT_SOURCES = \ x11-declarations.h \ @@ -808,6 +811,11 @@ EXTRA_DIST = \ randpkt.c \ rdps.c \ TODO \ + dictionary.dtd \ + dictionary.xml \ + mobileipv4.xml \ + nasreq.xml \ + sunping.xml \ x11-fields if SETUID_INSTALL diff --git a/Makefile.nmake b/Makefile.nmake index e445554a37..b6d4d9d9c1 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -1,7 +1,7 @@ ## Makefile for building ethereal.exe with Microsoft C and nmake ## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake # -# $Id: Makefile.nmake,v 1.134 2001/10/29 21:13:07 guy Exp $ +# $Id: Makefile.nmake,v 1.135 2001/11/01 21:52:44 guy Exp $ include config.nmake include <win32.mak> @@ -247,6 +247,7 @@ ETHEREAL_COMMON_OBJECTS = \ register.obj \ util.obj \ xdlc.obj \ + xmlstub.obj \ ethereal_OBJECTS = \ $(DISSECTOR_OBJECTS) \ diff --git a/dictionary.dtd b/dictionary.dtd new file mode 100644 index 0000000000..6285108f5d --- /dev/null +++ b/dictionary.dtd @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + $Log: dictionary.dtd,v $ + Revision 1.1 2001/11/01 21:52:44 guy + From David Frascone: duUpdate to Diameter dissector to load the + dictionary as an XML file rather than building it in, and various + Diameter updates. + + Revision 1.1 2001/08/24 18:04:44 chaos + Added per Mark's request + + Revision 1.3 2001/07/31 17:43:36 chaos + Oops, forgot to turn on validity checking. Fixed some errors found with validity checking turned on + + Revision 1.2 2001/07/31 16:56:15 chaos + Lots of changes to support flags like in the draft, and to support commands + +--> +<!ELEMENT dictionary (base, application*)> +<!ELEMENT base (command*, vendor*, typedefn+, avp+)> +<!ATTLIST base + uri CDATA #IMPLIED +> + +<!ELEMENT application (command*, vendor*, typedefn*, avp*)> +<!ATTLIST application + id CDATA #REQUIRED + name CDATA #IMPLIED + uri CDATA #IMPLIED +> +<!ELEMENT command (#PCDATA)> +<!ATTLIST command + name CDATA #REQUIRED + code CDATA #REQUIRED + vendor-id IDREF #IMPLIED +> +<!ELEMENT vendor EMPTY> +<!ATTLIST vendor + vendor-id ID #REQUIRED + code CDATA #REQUIRED + name CDATA #IMPLIED +> +<!ELEMENT typedefn EMPTY> +<!ATTLIST typedefn + type-name ID #REQUIRED + type-parent IDREF #IMPLIED + description CDATA #IMPLIED +> +<!ELEMENT avp ((type | grouped), (enum*))> +<!ATTLIST avp + name ID #REQUIRED + description CDATA #IMPLIED + code CDATA #REQUIRED + may-encrypt (yes | no) "yes" + mandatory (must | may | mustnot | shouldnot) "may" + protected (must | may | mustnot | shouldnot) "may" + vendor-bit (must | may | mustnot | shouldnot) "mustnot" + vendor-id IDREF #IMPLIED + constrained (true | false) "false" +> +<!ELEMENT type EMPTY> +<!ATTLIST type + type-name IDREF #REQUIRED +> +<!ELEMENT grouped (gavp+)> +<!ELEMENT gavp EMPTY> +<!ATTLIST gavp + name IDREF #REQUIRED +> +<!ELEMENT enum EMPTY> +<!ATTLIST enum + name CDATA #REQUIRED + code CDATA #REQUIRED +> diff --git a/dictionary.xml b/dictionary.xml new file mode 100644 index 0000000000..09df2dd4d1 --- /dev/null +++ b/dictionary.xml @@ -0,0 +1,647 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE dictionary SYSTEM "dictionary.dtd" [ + <!ENTITY nasreq SYSTEM "nasreq.xml"> + <!ENTITY mobileipv4 SYSTEM "mobileipv4.xml"> + <!ENTITY sunping SYSTEM "sunping.xml"> +]> +<dictionary> + <base uri="ftp://ftp.ietf.org/internet-drafts/draft-ietf-aaa-diameter-07.txt"> + <!-- + $Log: dictionary.xml,v $ + Revision 1.1 2001/11/01 21:52:44 guy + From David Frascone: duUpdate to Diameter dissector to load the + dictionary as an XML file rather than building it in, and various + Diameter updates. + + Revision 1.7 2001/08/24 18:03:24 chaos + Mark's Changes + + Revision 1.6 2001/07/31 19:13:55 chaos + Missed a couple of MIP AVPs + + Revision 1.5 2001/07/31 19:09:22 chaos + Added Mobile-Ip and Sun Ping Extension + + Revision 1.4 2001/07/31 17:43:25 chaos + Oops, forgot to turn on validity checking. Fixed some errors found with validity checking turned on + + Revision 1.3 2001/07/31 16:56:31 chaos + Added commands, and validated with xmllint + + Revision 1.2 2001/07/31 16:29:34 chaos + Checking in some changes to verify log and ident strings + +--> + <!-- *********************** Commands ***************************** --> + <!-- Diameter Base Protocol Command Codes --> + <command name="Abort-Session" code="274" vendor-id="None"> + <!-- Maybe some avp stuff here one day --> + </command> + <command name="Accounting" code="271" vendor-id="None"/> + <command name="Capabilities-Exchange" code="257" vendor-id="None"/> + <command name="Device-Watchdog" code="280" vendor-id="None"/> + <command name="Disconnect-Peer" code="282" vendor-id="None"/> + <command name="Re-Auth" code="258" vendor-id="None"/> + <command name="Session-Termination" code="275" vendor-id="None"/> + <!-- ********************** End Commands ************************** --> + + <!-- ************************* Vendors **************************** --> + <vendor vendor-id="None" code="0" name="None"/> + <vendor vendor-id="Merit" code="61" name="Merit Networks"/> + <vendor vendor-id="Sun" code="42" name="Sun Microsystems, Inc."/> + <vendor vendor-id="USR" code="429" name="US Robotics Corp."/> + <!-- *********************** End Vendors ************************** --> + + <!-- ************************ typedefn's ************************** --> + <typedefn type-name="OctetString"/> + <!-- + The data contains arbitrary data of variable length. Unless + otherwise noted, the AVP Length field MUST be set to at least 9 + (13 if the 'V' bit is enabled). Data used to transmit (human + readable) character string data uses the UTF-8 [24] character + set and is NOT NULL-terminated. The minimum Length field MUST + be 9, but can be set to any value up to 65504 bytes. AVP Values + of this type that do not align on a 32-bit boundary MUST have + the necessary padding. + --> + <typedefn type-name="UTF8String" type-parent="OctetString"/> + <!-- + The UTF8String format is derived from the OctetString AVP Base + Format. This is a human readable string represented using the + ISO/IEC IS 10646-1 character set, encoded as an OctetString + using the UTF-8 [29] transformation format described in RFC + 2279. + + Since additional code points are added by amendments to the + 10646 standard from time to time, implementations MUST be + prepared to encounter any code point from 0x00000001 to + 0x7fffffff. Byte sequences that do not correspond to the valid + UTF-8 encoding of a code point or are outside this range are + prohibited. Note that since a code point of 0x00000000 is + prohibited, no octet will contain a value of 0x00. + + The use of control codes SHOULD be avoided. When it is + necessary to represent a newline, the control code sequence CR + LF SHOULD be used. + + The use of leading or trailing white space SHOULD be avoided. + + For code points not directly supported by user interface + hardware or software, an alternative means of entry and + display, such as hexadecimal, MAY be provided. + + For information encoded in 7-bit US-ASCII, the UTF-8 encoding + is identical to the US-ASCII encoding. + + UTF-8 may require multiple bytes to represent a single + character / code point; thus the length of a UTF8String in + octets may be different from the number of characters encoded. + + Note that the size of an UTF8String is measured in octets, not + characters. + + The UTF8String MUST not contain any octets with a value of + zero. + --> + <typedefn type-name="IPAddress" type-parent="OctetString"/> + <!-- + The IPAddress format is derived from the OctetString AVP Base + Format. It represents 32 bit (IPv4) [17] or 128 bit (IPv6) [16] + address, most significant octet first. The format of the + address (IPv4 or IPv6) is determined by the length. If the + attribute value is an IPv4 address, the AVP Length field MUST + be 12 (16 if 'V' bit is enabled), otherwise the AVP Length + field MUST be set to 24 (28 if the 'V' bit is enabled) for IPv6 + addresses. + --> + <typedefn type-name="DiameterIdentity" type-parent="OctetString"/> + <!-- + The DiameterIdentity format is derived from the OctetString AVP + Base Format. It uses the UTF-8 encoding and has the same + requirements as the UTF8String. In addition, it must follow + the Uniform Resource Identifiers (URI) syntax [29] rules + specified below: + + Diameter-Identity = fqdn [ port ] [ transport ] + [ protocol ] + + aaa-protocol = ( "diameter" | "radius" | "tacacs+" ) + + protocol = ";protocol=" aaa-protocol + ; If absent, the default AAA protocol + ; is diameter. + + fqdn = Fully Qualified Host Name + + port = ":" 1*DIGIT + ; One of the ports used to listen for + ; incoming connections. ; If absent, + ; the default Diameter port (TBD) is + ; assumed. + + transport-protocol = ( "tcp" | "sctp" | "udp" ) + + transport = ";transport=" transport-protocol + + ; One of the transports used to listen + ; for incoming connections. If absent, + ; the default SCTP [26] protocol is + ; assumed. UDP MUST NOT be used when + ; the aaa-protocol field is set to + ; diameter. + + The following are examples of valid Diameter host + identities: + + host.abc.com;transport=tcp + host.abc.com:6666;transport=tcp + aaa://host.abc.com;protocol=diameter + aaa://host.abc.com:6666;protocol=diameter + aaa://host.abc.com:6666;transport=tcp;protocol=diameter + aaa://host.abc.com:1813;transport=udp;protocol=radius + + Since multiple Diameter processes on a single host cannot + listen for incoming connections on the same port on a given + protocol, the DiameterIdentity is guaranteed to be unique per + host. + + A Diameter node MAY advertise different identities on each + connection, via the CER and CEA's Origin-Host AVP, but the same + identity MUST be used throughout the duration of a connection. + + When comparing AVPs of this format, it is necessary to add any + absent fields with the default values prior to the comparison. + For example, diameter-host.abc.com would be expanded to + aaa://diameter/diameter-host.abc.com:TBD;protocol=sctp. + --> + <typedefn type-name="IPFilterRule" type-parent="OctetString"/> + <!-- + The IPFilterRule format is derived from the OctetString AVP + Base Format. It uses the UTF-8 encoding and has the same + requirements as the UTF8String. Packets may be filtered based + on the following information that is associated with it: + + Direction (in or out) + Source and destination IP address (possibly masked) + Protocol + Source and destination port (lists or ranges) + TCP flags + IP fragment flag + IP options + ICMP types + + Rules for the appropriate direction are evaluated in order, + with the first matched rule terminating the evaluation. Each + packet is evaluated once. If no rule matches, the packet is + dropped if the last rule evaluated was a permit, and passed if + the last rule was a deny. + + IPFilterRule filters MUST follow the format: + + action dir proto from src to dst [options] + + action permit - Allow packets that match the rule. + deny - Drop packets that match the rule. + + dir "in" is from the terminal, "out" is to the + terminal. + + proto An IP protocol specified by number. The "ip" + keyword means any protocol will match. + + src and dst <address/mask> [ports] + + The <address/mask> may be specified as: + ipno An IPv4 or IPv6 number in dotted- + quad or canonical IPv6 form. Only + this exact IP number will match the + rule. + ipno/bits An IP number as above with a mask + width of the form 1.2.3.4/24. In + this case all IP numbers from + 1.2.3.0 to 1.2.3.255 will match. + The bit width MUST be valid for the + IP version and the IP number MUST + NOT have bits set beyond the mask. + + The sense of the match can be inverted by + preceding an address with the not modifier, + causing all other addresses to be matched + instead. This does not affect the selection of + port numbers. + + The keyword "any" is 0.0.0.0/0 or the IPv6 + equivalent. The keyword "assigned" is the + address or set of addresses assigned to the + terminal. The first rule SHOULD be "deny in + ip !assigned". + + With the TCP, UDP and SCTP protocols, optional + ports may be specified as: + + {port|port-port}[,port[,...]] + + The `-' notation specifies a range of ports + (including boundaries). + + Fragmented packets which have a non-zero offset + (i.e. not the first fragment) will never match + a rule which has one or more port + specifications. See the frag option for + details on matching fragmented packets. + + options: + frag Match if the packet is a fragment and this is not + the first fragment of the datagram. frag may not + be used in conjunction with either tcpflags or + TCP/UDP port specifications. + + ipoptions spec + Match if the IP header contains the comma + separated list of options specified in spec. The + supported IP options are: + + ssrr (strict source route), lsrr (loose source + route), rr (record packet route) and ts + (timestamp). The absence of a particular option + may be denoted with a `!'. + + tcpoptions spec + Match if the TCP header contains the comma + separated list of options specified in spec. The + supported TCP options are: + + mss (maximum segment size), window (tcp window + advertisement), sack (selective ack), ts (rfc1323 + timestamp) and cc (rfc1644 t/tcp connection + count). The absence of a particular option may + be denoted with a `!'. + + established + TCP packets only. Match packets that have the RST + or ACK bits set. + + setup TCP packets only. Match packets that have the SYN + bit set but no ACK bit. + + tcpflags spec + TCP packets only. Match if the TCP header + contains the comma separated list of flags + specified in spec. The supported TCP flags are: + + fin, syn, rst, psh, ack and urg. The absence of a + particular flag may be denoted with a `!'. A rule + which contains a tcpflags specification can never + match a fragmented packet which has a non-zero + offset. See the frag option for details on + matching fragmented packets. + + icmptypes types + ICMP packets only. Match if the ICMP type is in + the list types. The list may be specified as any + combination of ranges or individual types + separated by commas. The supported ICMP types + are: + + echo reply (0), destination unreachable (3), + source quench (4), redirect (5), echo request + (8), router advertisement (9), router + solicitation (10), time-to-live exceeded (11), IP + header bad (12), timestamp request (13), + timestamp reply (14), information request (15), + information reply (16), address mask request (17) + and address mask reply (18). + + There is one kind of packet that the access device MUST always + discard, that is an IP fragment with a fragment offset of one. + This is a valid packet, but it only has one use, to try to + circumvent firewalls. + + An access device that is unable to interpret or apply a deny + rule MUST terminate the session. An access device that is + unable to interpret or apply a permit rule MAY apply a more + restrictive rule. An access device MAY apply deny rules of + its own before the supplied rules, for example to protect + the access device owner's infrastructure. + + The rule syntax is a modified subset of ipfw(8) from FreeBSD, + and the ipfw.c code may provide a useful base for + implementations. + --> + <typedefn type-name="QOSFilterRule" type-parent="OctetString"/> + <!-- + The QosFilterRule format is derived from the OctetString AVP + Base Format. It uses the UTF-8 encoding and has the same + requirements as the UTF8String. Packets may be marked or + metered based on the following information that is associated + with it: + + Direction (in or out) + Source and destination IP address (possibly masked) + Protocol + Source and destination port (lists or ranges) + DSCP values (no mask or range) + + Rules for the appropriate direction are evaluated in order, + with the first matched rule terminating the evaluation. Each + packet is evaluated once. If no rule matches, the packet is + treated as best effort. + + QoSFilterRule filters MUST follow the format: + + action dir proto from src to dst [options] + + tag - Mark packet with a specific DSCP [49]. + The DSCP option MUST be included. + + meter - Meter traffic. The metering options + MUST be included. + + dir "in" is from the terminal, "out" is to the + terminal. + + proto An IP protocol specified by number. The "ip" + keyword means any protocol will match. + + src and dst <address/mask> [ports] + + The <address/mask> may be specified as: + ipno An IPv4 or IPv6 number in dotted- + quad or canonical IPv6 form. Only + this exact IP number will match the + rule. + ipno/bits An IP number as above with a mask + width of the form 1.2.3.4/24. In + this case all IP numbers from + 1.2.3.0 to 1.2.3.255 will match. + The bit width MUST be valid for the + IP version and the IP number MUST + NOT have bits set beyond the mask. + + The sense of the match can be inverted by + preceding an address with the not modifier, + causing all other addresses to be matched + instead. This does not affect the selection of + port numbers. + + The keyword "any" is 0.0.0.0/0 or the IPv6 + equivalent. The keyword "assigned" is the + address or set of addresses assigned to the + terminal. The first rule SHOULD be "deny in + ip !assigned". + + With the TCP, UDP and SCTP protocols, optional + ports may be specified as: + + {port|port-port}[,port[,...]] + + The `-' notation specifies a range of ports + (including boundaries). + + options: + + DSCP <color> + color values as defined in [49]. Exact matching + of DSCP values is required (no masks or ranges). + the "deny" can replace the color_under or + color_over values in the meter action for rate- + dependent packet drop. + + metering <rate> <color_under> <color_over> + The metering option provides Assured Forwarding, + as defined in [50], and MUST be present if the + action is set to meter. The rate option is the + throughput, in bits per second, which is used by + the access device to mark packets. Traffic above + the rate is marked with the color_over codepoint, + while traffic under the rate is marked with the + color_under codepoint. The color_under and + color_over options contain the drop preferences, + and MUST conform to the recommended codepoint + keywords described in [50] (e.g. AF13). + + The metering option also supports the strict + limit on traffic required by Expedited + Forwarding, as defined in [51]. The color_over + option may contain the keyword "drop" to prevent + forwarding of traffic that exceeds the rate + parameter. + + The rule syntax is a modified subset of ipfw(8) from FreeBSD, + and the ipfw.c code may provide a useful base for + implementations. + + --> + <typedefn type-name="MIPRegistrationRequest" type-parent="OctetString"/> + + <typedefn type-name="Integer32"/> + <!-- + 32 bit signed value, in network byte order. The AVP Length + field MUST be set to 12 (16 if the 'V' bit is enabled). + --> + <typedefn type-name="VendorId" type-parent="Integer32"/> + <typedefn type-name="AppId" type-parent="Integer32"/> + <typedefn type-name="Integer64"/> + <!-- + 64 bit signed value, in network byte order. The AVP Length + field MUST be set to 16 (20 if the 'V' bit is enabled). + --> + <typedefn type-name="Unsigned32"/> + <!-- + 32 bit unsigned value, in network byte order. The AVP Length + field MUST be set to 12 (16 if the 'V' bit is enabled). + Unsigned32 values used to transmit time data contains the four + most significant octets returned from NTP [18], in network byte + order. + --> + <typedefn type-name="Time"/> + <!-- + The Time format is derived from the Unsigned32 AVP Base Format. + This is 32 bit unsigned value containing the four most + significant octets returned from NTP [18], in network byte + order. + + This represent the number of seconds since 0h on 1 January 1900 + with respect to the Coordinated Universal Time (UTC). + + On 6h 28m 16s UTC, 7 February 2036 the time value will + overflow. NTP [18] describes a procedure to extend the time to + 2104. + --> + <typedefn type-name="Unsigned64"/> + <!-- + 64 bit unsigned value, in network byte order. The AVP Length + field MUST be set to 16 (20 if the 'V' bit is enabled). + --> + <!-- ************************* End Typedefns ************************ --> + <!-- ******************* DIAMETER BASE PROTOCOL AVPS ************************ --> + <avp name="Accounting-Interim-Interval" code="482" mandatory="must" may-encrypt="yes" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Accounting-Multi-Session-Id" code="50" mandatory="must" protected="may" may-encrypt="yes" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Accounting-Record-Number" code="485" mandatory="must" may-encrypt="yes" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Accounting-Record-Type" code="480" mandatory="must" may-encrypt="yes" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + <enum name="Event Record" code="1"/> + <enum name="Start Record" code="2"/> + <enum name="Interim Record" code="3"/> + <enum name="Stop Record" code="4"/> + </avp> + <avp name="Accounting-Session-Id" code="44" mandatory="must" protected="may" may-encrypt="yes" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Acct-Application-Id" code="259" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="AppId"/> + </avp> + <avp name="Alternate-Peer" code="275" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="Auth-Application-Id" code="258" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="AppId"/> + </avp> + <avp name="Auth-Request-Type" code="274" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + <enum name="Authenticate Only" code="1"/> + <enum name="Authorize Only" code="2"/> + <enum name="Authorize Authenticate" code="3"/> + </avp> + <avp name="Authorization-Lifetime" code="291" mandatory="must" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="Integer32"/> + </avp> + <avp name="Auth-Grace-Period" code="276" mandatory="must" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Auth-Session-State" code="277" mandatory="must" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + <enum name="State Maintained" code="0"/> + <enum name="No State Maintained" code="0"/> + </avp> + <avp name="Re-Auth-Request-Type" code="285" mandatory="must" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + <enum name="Authorize Only" code="0"/> + <enum name="Authorize Authenticate" code="1"/> + </avp> + <avp name="Destination-Host" code="293" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="Destination-Realm" code="283" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="UTF8String"/> + </avp> + <avp name="Disconnect-Cause" code="273" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + <enum name="Rebooting" code="0"/> + <enum name="Busy" code="2"/> + <enum name="Do not want to talk to you" code="2"/> + </avp> + <avp name="Error-Message" code="281" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="UTF8String"/> + </avp> + <avp name="Error-Reporting-Host" code="294" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="Failed-AVP" code="279" mandatory="must" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="OctetString"/> + </avp> + <avp name="Firmware-Revision" code="267" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Host-IP-Address" code="257" mandatory="must" protected="mustnot" may-encrypt="no" vendor-bit="mustnot"> + <type type-name="IPAddress"/> + </avp> + <avp name="Multi-Round-Time-Out" code="272" mandatory="must" may-encrypt="yes" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Origin-Host" code="264" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="Origin-Realm" code="296" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="UTF8String"/> + </avp> + <avp name="Origin-State-Id" code="278" mandatory="must" protected="mustnot" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Product-Name" code="269" mandatory="mustnot" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="UTF8String"/> + </avp> + <avp name="Proxy-Host" code="280" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="Proxy-Info" code="284" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="OctetString"/> + </avp> + <avp name="Redirect-Host" code="292" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="Redirect-Host-Usage" code="261" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + <enum name="Don't Care" code="0"/> + <enum name="All Session" code="1"/> + <enum name="All Realm" code="2"/> + <enum name="Realm and Application" code="3"/> + <enum name="All Application" code="4"/> + <enum name="All Host" code="5"/> + </avp> + <avp name="Redirect-Max-Cache-Time" code="262" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Result-Code" code="268" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Route-Record" code="282" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="Session-Id" code="263" mandatory="must" protected="mustnot" vendor-bit="mustnot"> + <type type-name="UTF8String"/> + </avp> + <avp name="Session-Binding" code="270" mandatory="must" protected="mustnot" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Session-Server-Failover" code="271" mandatory="must" protected="mustnot" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + <enum name="Refuse Service" code="0"/> + <enum name="Try Again" code="1"/> + <enum name="Allow Service" code="2"/> + <enum name="Try Again / Allow Service" code="3"/> + </avp> + <avp name="Source-Route" code="286" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="Supported-Vendor-Id" code="265" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="VendorId"/> + </avp> + <avp name="Termination-Cause" code="295" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="Unsigned32"/> + <enum name="Logout" code="1"/> + <enum name="Service Not Provided" code="2"/> + <enum name="Bad Answer" code="3"/> + <enum name="Administrative" code="4"/> + <enum name="Link Broken" code="5"/> + </avp> + <avp name="Vendor-Id" code="266" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <type type-name="VendorId"/> + </avp> + <avp name="Vendor-Specific-Application-Id" code="260" mandatory="must" may-encrypt="no" protected="mustnot" vendor-bit="mustnot"> + <grouped> + <gavp name="Vendor-Id"/> + <gavp name="Auth-Application-Id"/> + <gavp name="Acct-Application-Id"/> + </grouped> + </avp> + <avp name="Example-AVP" code="999999" mandatory="mustnot" vendor-bit="may"> + <grouped> + <gavp name="Origin-Host"/> + <gavp name="Host-IP-Address"/> + </grouped> + </avp> + <!-- ************************ END DIAMETER BASE PROTOCOL AVPS ******************* --> + </base> + + &nasreq; + &mobileipv4; + &sunping; + +</dictionary> diff --git a/mobileipv4.xml b/mobileipv4.xml new file mode 100644 index 0000000000..37566a8c57 --- /dev/null +++ b/mobileipv4.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> + + <application id="4" name="Mobile IPv4 Application" uri="ftp://ftp.ietf.org/internet-drafts/draft-ietf-aaa-diameter-mobileip-07.txt"> + + <!-- Mobile-IPv4 Application --> + <command name="AA-Mobile-Node" code="260" vendor-id="None"/> + <command name="Home-Agent-MIP" code="262" vendor-id="None"/> + + <!-- ************************** Mobile-IPv4 AVPS ********************* --> + <avp name="MIP-Filter-Rule" code="347" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="IPFilterRule"/> + </avp> + <avp name="MIP-Auth-Input-Data-Length" code="338" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="Unsigned32"/> + </avp> + <avp name="MIP-Authenticator-Length" code="339" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="Unsigned32"/> + </avp> + <avp name="MIP-Authenticator-Offset" code="340" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="Unsigned32"/> + </avp> + <avp name="MIP-FA-Challenge" code="344" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="OctetString"/> + </avp> + <avp name="MIP-Feature-Vector" code="337" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="Unsigned32"/> + </avp> + <avp name="MIP-Foreign-Agent-Host" code="330" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="MIP-Home-Agent-Address" code="334" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="IPAddress"/> + </avp> + <avp name="MIP-MN-AAA-Auth" code="322" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <grouped> + <gavp name="MIP-MN-AAA-SPI"/> + <gavp name="MIP-Auth-Input-Data-Length"/> + <gavp name="MIP-Authenticator-Length"/> + <gavp name="MIP-Authenticator-Offset"/> + </grouped> + </avp> + <avp name="MIP-MN-AAA-SPI" code="341" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="Unsigned32"/> + </avp> + <avp name="MIP-Mobile-Node-Address" code="333" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="IPAddress"/> + </avp> + <avp name="MIP-Previous-FA-Addr" code="336" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="IPAddress"/> + </avp> + <avp name="MIP-Previous-FA-Host" code="335" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="DiameterIdentity"/> + </avp> + <avp name="MIP-Reg-Request" code="320" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="MIPRegistrationRequest"/> + </avp> + <avp name="MIP-Reg-Reply" code="321" mandatory="must" vendor-bit="mustnot" may-encrypt="yes"> + <type type-name="OctetString"/> + </avp> + <!-- ************************ END Mobile-IPv4 AVPS ******************* --> + + </application> diff --git a/nasreq.xml b/nasreq.xml new file mode 100644 index 0000000000..8f0fde10f5 --- /dev/null +++ b/nasreq.xml @@ -0,0 +1,291 @@ +<?xml version="1.0" encoding="UTF-8"?> + + <application id="1" name="NASREQ Application" uri="ftp://ftp.ietf.org/internet-drafts/draft-calhoun-diameter-nasreq-06.txt"> + + <command name="AA-Request" code="260" vendor-id="None"/> + <command name="AA-Answer" code="260" vendor-id="None"/> + + <!-- ************************* RADIUS AVPs ************************ --> + <avp name="User-Name" code="1"> + <type type-name="UTF8String"/> + </avp> + <avp name="User-Password" code="2"> + <type type-name="OctetString"/> + </avp> + <avp name="CHAP-Password" code="3"> + <type type-name="OctetString"/> + </avp> + <avp name="NAS-IP-Address" code="4"> + <type type-name="IPAddress"/> + </avp> + <avp name="NAS-Port" code="5"> + <type type-name="Integer32"/> + </avp> + <avp name="Service-Type" code="6"> + <type type-name="Unsigned32"/> + <enum name="Labels" code="3"/> + <enum name="RSVP" code="1"/> + <enum name="TOS" code="2"/> + </avp> + <avp name="Framed-Protocol" code="7"> + <type type-name="Unsigned32"/> + <enum name="ARA" code="3"/> + <enum name="Ascend-ARA" code="255"/> + <enum name="COMB" code="260"/> + <enum name="EURAW" code="257"/> + <enum name="EUUI" code="258"/> + <enum name="FR" code="261"/> + <enum name="Gandalf" code="4"/> + <enum name="MPP" code="256"/> + <enum name="PPP" code="1"/> + <enum name="SLIP" code="2"/> + <enum name="X25" code="259"/> + <enum name="Xylogics" code="5"/> + </avp> + <avp name="Framed-IP-Address" code="8"> + <type type-name="IPAddress"/> + </avp> + <avp name="Framed-IP-Netmask" code="9"> + <type type-name="IPAddress"/> + </avp> + <avp name="Framed-Routing" code="10"> + <type type-name="Unsigned32"/> + <enum name="Broadcast" code="1"/> + <enum name="Broadcast-Listen" code="3"/> + <enum name="Listen" code="2"/> + <enum name="None" code="0"/> + </avp> + <avp name="Filter-Id" code="11"> + <type type-name="UTF8String"/> + </avp> + <avp name="Framed-MTU" code="12"> + <type type-name="Integer32"/> + </avp> + <avp name="Framed-Compression" code="13"> + <type type-name="Unsigned32"/> + <enum name="IPX-Header-Compression" code="2"/> + <enum name="None" code="0"/> + <enum name="Van-Jacobson-TCP-IP" code="1"/> + </avp> + <avp name="Login-IP-Host" code="14"> + <type type-name="IPAddress"/> + </avp> + <avp name="Login-Service" code="15"> + <type type-name="Unsigned32"/> + <enum name="LAT" code="4"/> + <enum name="PortMaster" code="3"/> + <enum name="Rlogin" code="1"/> + <enum name="TCP-Clear" code="2"/> + <enum name="Telnet" code="0"/> + <enum name="X25-PAD" code="5"/> + <enum name="X25-T3POS" code="6"/> + </avp> + <avp name="Login-TCP-Port" code="16"> + <type type-name="Integer32"/> + </avp> + <avp name="Old-Password" code="17"> + <type type-name="OctetString"/> + </avp> + <avp name="Reply-Message" code="18"> + <type type-name="UTF8String"/> + </avp> + <avp name="Callback-Number" code="19"> + <type type-name="OctetString"/> + </avp> + <avp name="Callback-Id" code="20"> + <type type-name="OctetString"/> + </avp> + <avp name="Framed-Route" code="22"> + <type type-name="UTF8String"/> + </avp> + <avp name="Framed-IPX-Network" code="23"> + <type type-name="OctetString"/> + </avp> + <avp name="State" code="24"> + <type type-name="OctetString"/> + </avp> + <avp name="Class" code="25"> + <type type-name="OctetString"/> + </avp> + <avp name="Vendor-Specific" code="26"> + <type type-name="Unsigned32"/> + <!-- Should vendors be enum'ed? --> + </avp> + <avp name="Session-Timeout" code="27"> + <type type-name="Integer32"/> + </avp> + <avp name="Idle-Timeout" code="28"> + <type type-name="Integer32"/> + </avp> + <avp name="Termination-Action" code="29"> + <type type-name="Unsigned32"/> + <enum name="Default" code="0"/> + <enum name="RADIUS-Request" code="1"/> + </avp> + <avp name="Called-Station-Id" code="30"> + <type type-name="OctetString"/> + </avp> + <avp name="Calling-Station-Id" code="31"> + <type type-name="OctetString"/> + </avp> + <avp name="NAS-Identifier" code="32"> + <type type-name="OctetString"/> + </avp> + <avp name="Proxy-State" code="33"> + <type type-name="OctetString"/> + </avp> + <avp name="Login-LAT-Service" code="34"> + <type type-name="OctetString"/> + </avp> + <avp name="Login-LAT-Node" code="35"> + <type type-name="OctetString"/> + </avp> + <avp name="Login-LAT-Group" code="36"> + <type type-name="OctetString"/> + </avp> + <avp name="Framed-AppleTalk-Link" code="37"> + <type type-name="Integer32"/> + </avp> + <avp name="Framed-AppleTalk-Network" code="38"> + <type type-name="Integer32"/> + </avp> + <avp name="Framed-AppleTalk-Zone" code="39"> + <type type-name="OctetString"/> + </avp> + <avp name="Acct-Status-Type" code="40"> + <type type-name="Unsigned32"/> + <enum name="Accounting-Off" code="8"/> + <enum name="Accounting-On" code="7"/> + <enum name="Alive" code="3"/> + <enum name="Cancel" code="6"/> + <enum name="Modem-Start" code="4"/> + <enum name="Modem-Stop" code="5"/> + <enum name="Start" code="1"/> + <enum name="Stop" code="2"/> + </avp> + <avp name="Acct-Delay-Time" code="41"> + <type type-name="Integer32"/> + </avp> + <avp name="Acct-Input-Octets" code="42"> + <type type-name="Integer32"/> + </avp> + <avp name="Acct-Output-Octets" code="43"> + <type type-name="Integer32"/> + </avp> + <avp name="Acct-Session-Id" code="44" mandatory="must"> + <type type-name="OctetString"/> + </avp> + <avp name="Acct-Authentic" code="45"> + <type type-name="Unsigned32"/> + <enum name="Local" code="2"/> + <enum name="None" code="0"/> + <enum name="RADIUS" code="1"/> + </avp> + <avp name="Acct-Session-Time" code="46"> + <type type-name="Integer32"/> + </avp> + <avp name="Acct-Input-Packets" code="47"> + <type type-name="Integer32"/> + </avp> + <avp name="Acct-Output-Packets" code="48"> + <type type-name="Integer32"/> + </avp> + <avp name="Acct-Terminate-Cause" code="49"> + <type type-name="Unsigned32"/> + <enum name="Admin-Reboot" code="7"/> + <enum name="Admin-Reset" code="6"/> + <enum name="Callback" code="16"/> + <enum name="Host-Request" code="18"/> + <enum name="Idle-Timeout" code="4"/> + <enum name="Lost-Carrier" code="2"/> + <enum name="Lost-Service" code="3"/> + <enum name="NAS-Error" code="9"/> + <enum name="NAS-Reboot" code="11"/> + <enum name="NAS-Request" code="10"/> + <enum name="Port-Error" code="8"/> + <enum name="Port-Preempted" code="13"/> + <enum name="Port-Suspended" code="14"/> + <enum name="Port-Unneeded" code="12"/> + <enum name="Service-Unavailable" code="15"/> + <enum name="Session-Timeout" code="5"/> + <enum name="User-Error" code="17"/> + <enum name="User-Request" code="1"/> + </avp> + <avp name="Acct-Multi-Session-Id" code="50"> + <type type-name="OctetString"/> + </avp> + <avp name="Acct-Link-Count" code="51"> + <type type-name="Integer32"/> + </avp> + <avp name="CHAP-Challenge" code="60"> + <type type-name="OctetString"/> + </avp> + <avp name="NAS-Port-Type" code="61"> + <type type-name="Unsigned32"/> + <enum name="Async" code="0"/> + <enum name="HDLC-Clear-Channel" code="7"/> + <enum name="ISDN-Async-v110" code="4"/> + <enum name="ISDN-Async-v120" code="3"/> + <enum name="ISDN-Sync" code="2"/> + <enum name="PIAFS" code="6"/> + <enum name="Sync" code="1"/> + <enum name="Virtual" code="5"/> + <enum name="X25" code="8"/> + <enum name="X75" code="9"/> + </avp> + <avp name="Port-Limit" code="62"> + <type type-name="Integer32"/> + </avp> + <avp name="Login-LAT-Port" code="63"> + <type type-name="OctetString"/> + </avp> + <avp name="Tunnel-Type" code="64"> + <type type-name="Unsigned32"/> + <enum name="PPTP" code="1"/> + <enum name="L2F" code="2"/> + <enum name="L2TP" code="3"/> + <enum name="ATMP" code="4"/> + <enum name="VTP" code="5"/> + <enum name="AH" code="6"/> + <enum name="IP-IP-Encap" code="7"/> + <enum name="MIN-IP-IP" code="8"/> + <enum name="ESP" code="9"/> + <enum name="GRE" code="10"/> + <enum name="DVS" code="11"/> + <enum name="IP-IP" code="12"/> + </avp> + <avp name="Tunnel-Medium-Type" code="65"> + <type type-name="Unsigned32"/> + <enum name="IPv4" code="1"/> + <enum name="IPv6" code="2"/> + <enum name="NSAP" code="3"/> + <enum name="HDLC" code="4"/> + <enum name="BBN" code="5"/> + <enum name="IEEE-802" code="6"/> + <enum name="E-163" code="7"/> + <enum name="E-164" code="8"/> + <enum name="F-69" code="9"/> + <enum name="X-121" code="10"/> + <enum name="IPX" code="11"/> + <enum name="Appletalk-802" code="12"/> + <enum name="Decnet4" code="13"/> + <enum name="Vines" code="14"/> + <enum name="E-164-NSAP" code="15"/> + </avp> + <avp name="Tunnel-Client-Endpoint" code="66"> + <type type-name="OctetString"/> + </avp> + <avp name="Tunnel-Server-Endpoint" code="67"> + <type type-name="OctetString"/> + </avp> + <avp name="Tunnel-Connection-ID" code="68"> + <type type-name="OctetString"/> + </avp> + <avp name="Tunnel-Password" code="69"> + <type type-name="OctetString"/> + </avp> + <avp name="Tunnel-Assignment-Id" code="82"> + <type type-name="OctetString"/> + </avp> + + </application> diff --git a/packet-diameter-defs.h b/packet-diameter-defs.h index 14458f1b0b..ace74dae4f 100644 --- a/packet-diameter-defs.h +++ b/packet-diameter-defs.h @@ -1,8 +1,11 @@ /* * Filename: packet-diameter-defs.h - * WARNING: This file was automatically generated by dict2h.pl. Modifications - * will be erased by next invocation of dictionary parser. * + * This file contains the static definitions of the Diameter base protocol + * AVPs. If libxml is in the LD_LIBRARY_PATH, and dictionary.xml exists, + * then it will not be used. + * + * $Id: packet-diameter-defs.h,v 1.6 2001/11/01 21:52:44 guy Exp $ * Generated: Fri Feb 23 13:04:15 2001 */ @@ -12,26 +15,6 @@ /* Type to string table */ - -static value_string diameter_avp_type_vals[]={ - { 1, "OctetString" }, - { 2, "Integer32" }, - { 3, "Integer64" }, - { 4, "Unsigned32" }, - { 5, "Unsigned64" }, - { 6, "Float32" }, - { 7, "Float64" }, - { 8, "Float128" }, - { 9, "Grouped" }, - { 10, "IpAddress" }, - { 11, "Time" }, - { 12, "UTF8String" }, - { 13, "DiameterIdentity" }, - { 14, "Enumerated" }, - { 15, "IPFilterRule" }, - { 16, "QOSFilterRule" }, - {0, (char *)NULL} -}; /* Attribute to String tables */ static value_string diameter_service_type_vals[]={ {5, "Outbound"}, @@ -99,6 +82,7 @@ static value_string diameter_vendor_specific_vendors[]= { {529, "Ascend"}, {1584, "Bay Networks"}, {2636, "Juniper Networks"}, + {5925, "ipUnplugged"}, {0,NULL} }; @@ -258,7 +242,23 @@ static value_string diameter_termination_cause_vals[]= { {0,NULL} }; -static struct avp_info diameter_avps[] = { +static value_string diameter_mip_algorithm_type[] = { + {1, "MD5 Prefix/Suffix"}, + {2, "HMAC-MD5"}, + {3, "HMAC-SHA1"}, + {0, NULL} +}; + +static value_string diameter_mip_replay_type[] = { + {1, "None"}, + {2, "Nonce"}, + {3, "Timestamp"}, + {0, NULL} +}; + + + +static struct old_avp_info old_diameter_avps[] = { /* Radius Attributes */ { 1, "User-Name", DIAMETER_UTF8STRING, (value_string *)NULL}, { 2, "User-Password", DIAMETER_OCTET_STRING, (value_string *)NULL}, @@ -349,7 +349,7 @@ static struct avp_info diameter_avps[] = { { 278, "Origin-State-Id", DIAMETER_UNSIGNED32, (value_string *)NULL}, { 269, "Product-Name", DIAMETER_UTF8STRING, (value_string *)NULL}, { 280, "Proxy-Host", DIAMETER_IDENTITY, (value_string *)NULL}, - { 284, "Proxy-Info", DIAMETER_OCTET_STRING,(value_string *)NULL}, + { 284, "Proxy-Info", DIAMETER_GROUPED, (value_string *)NULL}, { 292, "Redirect-Host", DIAMETER_IDENTITY, (value_string *)NULL}, { 261, "Redirect-Host-Usage", DIAMETER_ENUMERATED, diameter_redirect_host_usage_vals}, { 262, "Redirect-Max-Cache-Time", DIAMETER_UNSIGNED32, (value_string *)NULL}, @@ -363,7 +363,34 @@ static struct avp_info diameter_avps[] = { { 295, "Termination-Cause", DIAMETER_ENUMERATED, diameter_termination_cause_vals}, { 266, "Vendor-Id", DIAMETER_ENUMERATED, diameter_vendor_specific_vendors}, { 260, "Vendor-Specific-Application-Id", DIAMETER_GROUPED, (value_string *)NULL}, - {0, (char *)NULL, 0, (value_string*)NULL} +/* Diameter Mobile IP AVPs */ + { 318, "MIP-FA-to-HA-SPI", DIAMETER_UNSIGNED32, (value_string *)NULL}, + { 319, "MIP-FA-to-MN-SPI", DIAMETER_UNSIGNED32, (value_string *)NULL}, + { 320, "MIP-Reg-Request", DIAMETER_MIP_REG_REQ, (value_string *)NULL}, + { 321, "MIP-Reg-Reply", DIAMETER_OCTET_STRING, (value_string *)NULL}, + { 322, "MIP-MN-AAA-Auth", DIAMETER_GROUPED, (value_string *)NULL}, + { 325, "MIP-MN-to-FA-KEY", DIAMETER_GROUPED, (value_string *)NULL}, + { 326, "MIP-FA-to-MN-KEY", DIAMETER_GROUPED, (value_string *)NULL}, + { 328, "MIP-FA-to-HA-KEY", DIAMETER_GROUPED, (value_string *)NULL}, + { 329, "MIP-HA-to-FA-KEY", DIAMETER_GROUPED, (value_string *)NULL}, + { 330, "MIP-Foreign-Agent-Host", DIAMETER_IDENTITY, (value_string *)NULL}, + { 331, "MIP-MN-to-HA-KEY", DIAMETER_GROUPED, (value_string *)NULL}, + { 333, "MIP-Mobile-Node-Address", DIAMETER_IP_ADDRESS, (value_string *)NULL}, + { 334, "MIP-Home-Agent-Address", DIAMETER_IP_ADDRESS, (value_string *)NULL}, + { 335, "MIP-Key-Material", DIAMETER_OCTET_STRING, (value_string *)NULL}, + { 337, "MIP-Feature-Vector", DIAMETER_UNSIGNED32, (value_string *)NULL}, + { 338, "MIP-Auth-Input-Data-Length", DIAMETER_UNSIGNED32, (value_string *)NULL}, + { 339, "MIP-Authenticator-Length", DIAMETER_UNSIGNED32, (value_string *)NULL}, + { 340, "MIP-Authenticator-Offset", DIAMETER_UNSIGNED32, (value_string *)NULL}, + { 341, "MIP-MN-AAA-SPI", DIAMETER_UNSIGNED32, (value_string *)NULL}, + { 342, "MIP-PEER-SPI", DIAMETER_UNSIGNED32, (value_string *)NULL}, + { 343, "MIP-Session-Key", DIAMETER_OCTET_STRING, (value_string *)NULL}, + { 344, "MIP-FA-Challenge", DIAMETER_OCTET_STRING, (value_string *)NULL}, + { 345, "MIP-Algorithm-Type", DIAMETER_ENUMERATED, diameter_mip_algorithm_type}, + { 346, "MIP-Algorithm-Type", DIAMETER_ENUMERATED, diameter_mip_replay_type}, + { 347, "MIP-Filter-Rule", DIAMETER_IP_FILTER_RULE, (value_string *)NULL}, + { 398, "MIP-Key-Lifetime", DIAMETER_UNSIGNED32, (value_string *)NULL}, +{0, (char *)NULL, 0, (value_string*)NULL} }; @@ -378,6 +405,9 @@ static value_string diameter_command_code_vals[] = { {282, "Disconnect-Peer"}, {258, "Re-Auth"}, {275, "Session-Termination"}, + /* Mip Protocol */ + {262, "Home-Agent-MIP"}, + {260, "AA-Mobile-Node"}, {0, (char *)NULL} }; diff --git a/packet-diameter.c b/packet-diameter.c index 0469da20ab..4ee8100345 100644 --- a/packet-diameter.c +++ b/packet-diameter.c @@ -1,7 +1,7 @@ /* packet-diameter.c - * Routines for DIAMETER packet disassembly + * Routines for Diameter packet disassembly * - * $Id: packet-diameter.c,v 1.27 2001/10/29 21:13:07 guy Exp $ + * $Id: packet-diameter.c,v 1.28 2001/11/01 21:52:44 guy Exp $ * * Copyright (c) 2001 by David Frascone <dave@frascone.com> * @@ -42,11 +42,13 @@ #include <ctype.h> #include <time.h> #include <glib.h> +#include <filesystem.h> +#include "xmlstub.h" #include "packet.h" #include "resolv.h" #include "prefs.h" -/* This must be defined before we include packet-diameter-defs.h s*/ +/* This must be defined before we include packet-diameter-defs.h */ /* Valid data types */ typedef enum { @@ -68,17 +70,85 @@ typedef enum { DIAMETER_IDENTITY, /* OctetString */ DIAMETER_ENUMERATED, /* Integer 32 */ DIAMETER_IP_FILTER_RULE, /* OctetString */ - DIAMETER_QOS_FILTER_RULE /* OctetString */ + DIAMETER_QOS_FILTER_RULE, /* OctetString */ + DIAMETER_MIP_REG_REQ, /* OctetString */ + DIAMETER_VENDOR_ID, /* Integer32 */ + DIAMETER_APPLICATION_ID } diameterDataType; -typedef struct avp_info { + +static value_string TypeValues[]={ + { DIAMETER_OCTET_STRING, "OctetString" }, + { DIAMETER_INTEGER32, "Integer32" }, + { DIAMETER_INTEGER64, "Integer64" }, + { DIAMETER_UNSIGNED32, "Unsigned32" }, + { DIAMETER_UNSIGNED64, "Unsigned64" }, + { DIAMETER_FLOAT32, "Float32" }, + { DIAMETER_FLOAT64, "Float64" }, + { DIAMETER_FLOAT128, "Float128" }, + { DIAMETER_GROUPED, "Grouped" }, + { DIAMETER_IP_ADDRESS, "IpAddress" }, + { DIAMETER_TIME, "Time" }, + { DIAMETER_UTF8STRING, "UTF8String" }, + { DIAMETER_IDENTITY, "DiameterIdentity" }, + { DIAMETER_ENUMERATED, "Enumerated" }, + { DIAMETER_IP_FILTER_RULE, "IPFilterRule" }, + { DIAMETER_QOS_FILTER_RULE, "QOSFilterRule" }, + { DIAMETER_MIP_REG_REQ, "MIPRegistrationRequest"}, + { DIAMETER_VENDOR_ID, "VendorId"}, + { DIAMETER_APPLICATION_ID, "AppId"}, + {0, (char *)NULL} +}; + +typedef struct value_name { + guint32 value; + gchar *name; + struct value_name *next; +} ValueName; + +typedef struct old_avp_info { guint32 code; gchar *name; diameterDataType type; value_string *values; +} oldAvpInfo; + +typedef struct avp_info { + guint32 code; + gchar *name; + gchar *vendorName; + diameterDataType type; + ValueName *values; + struct avp_info *next; } avpInfo; +typedef struct command_code { + guint32 code; + gchar *name; + gchar *vendorString; + struct command_code *next; +} CommandCode; + +typedef struct vendor_id { + guint32 id; + gchar *name; + gchar *longName; + struct vendor_id *next; +} VendorId; + +typedef struct application_id { + guint32 id; + gchar *name; + struct application_id *next; +} ApplicationId; + +static avpInfo *avpListHead=NULL; +static VendorId *vendorListHead=NULL; +static CommandCode *commandListHead=NULL; +static ApplicationId *ApplicationIdHead=NULL; + + #include "packet-diameter-defs.h" #define NTP_TIME_DIFF (2208988800UL) @@ -147,6 +217,9 @@ static gint ett_diameter_avpinfo = -1; static char gbl_diameterString[200]; static int gbl_diameterTcpPort=TCP_PORT_DIAMETER; static int gbl_diameterSctpPort=SCTP_PORT_DIAMETER; +#define DIAMETER_DIR "diameter" +#define DICT_FN "dictionary.xml" +static gchar *gbl_diameterDictionary = NULL; typedef struct _e_diameterhdr { guint32 versionLength; @@ -162,8 +235,6 @@ typedef struct _e_avphdr { guint32 avp_vendorId; /* optional */ } e_avphdr; -#define AUTHENTICATOR_LENGTH 12 - /* Diameter Header Flags */ /* RPrrrrrrCCCCCCCCCCCCCCCCCCCCCCCC */ #define DIAM_FLAGS_R 0x80 @@ -195,39 +266,616 @@ typedef struct _e_avphdr { #define AVP_FLAGS_RESERVED 0x1f /* 00011111 -- V M P X X X X X */ #define MIN_AVP_SIZE (sizeof(e_avphdr) - sizeof(guint32)) -#define MIN_DIAMETER_SIZE (sizeof(e_diameterhdr) + MIN_AVP_SIZE) +#define MIN_DIAMETER_SIZE (sizeof(e_diameterhdr)) static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +/* + * This routine will do a push-parse of the passed in + * filename. This was taken almost verbatum from + * the xmlsoft examples. + */ +static xmlDocPtr +xmlParseFilePush( char *filename, int checkValid) { + FILE *f; + xmlDocPtr doc=NULL; + int valid=0; + int res, size = 1024; + char chars[1024]; + xmlParserCtxtPtr ctxt; + + /* I wonder what kind of a performance hit this is? */ + *XmlStub.xmlDoValidityCheckingDefaultValue = checkValid; + + f = fopen(filename, "r"); + if (f == NULL) { + g_warning("Diameter: Unable to open %s", filename); + return NULL; + } + + res = fread(chars, 1, 4, f); + if (res > 0) { + ctxt = XmlStub.xmlCreatePushParserCtxt(NULL, NULL, + chars, res, filename); + while ((res = fread(chars, 1, size-1, f)) > 0) { + XmlStub.xmlParseChunk(ctxt, chars, res, 0); + } + XmlStub.xmlParseChunk(ctxt, chars, 0, 1); + doc = ctxt->myDoc; + valid=ctxt->valid; + XmlStub.xmlFreeParserCtxt(ctxt); + } + fclose(f); + + /* Check valid */ + if (!valid) { + g_warning( "Error! Invalid xml in %s! Failed DTD check!", + filename); + return NULL; + } + return doc; +} /* xmlParseFilePush */ + +/* + * This routine will add a static avp to the avp list. It is + * only called when the XML dictionary fails to load properly. + */ +static int +addStaticAVP(int code, gchar *name, diameterDataType type, value_string *values) +{ + avpInfo *entry; + ValueName *vEntry=NULL; + int i; + + /* Parse our values array, if we have one */ + if (values) { + for (i=0; values[i].strptr != NULL; i++) { + char *valueName=NULL, *valueCode=NULL; + ValueName *ve = NULL; + + ve = g_malloc(sizeof(ValueName)); + ve->name = strdup(values[i].strptr); + ve->value = values[i].value; + ve->next = vEntry; + vEntry = ve; + } + } /* if values */ + + /* And, create the entry */ + entry = (avpInfo *)g_malloc(sizeof(avpInfo)); + entry->name = g_strdup(name); + entry->code = code; + entry->vendorName = NULL; + entry->type = type; + entry->values = vEntry; + if (vEntry) + entry->type = DIAMETER_INTEGER32; + + return (0); + +} /* addStaticAVP */ + +/* + * This routine will parse an XML avp entry, and add it to our + * avp list. If any values are present in the avp, it will + * add them too. + */ +static int +xmlParseAVP(xmlDocPtr doc, xmlNodePtr cur) +{ + char *name=NULL, *description=NULL, *code=NULL, *mayEncrypt=NULL, + *mandatory=NULL, *protected=NULL, *vendorBit=NULL, *vendorName = NULL, + *constrained=NULL; + char *type=NULL; + avpInfo *entry; + guint32 avpType=0; + ValueName *vEntry=NULL; + int i; + + /* First, get our properties */ + name = XmlStub.xmlGetProp(cur, "name"); + description = XmlStub.xmlGetProp(cur, "description"); + code = XmlStub.xmlGetProp(cur, "code"); + mayEncrypt = XmlStub.xmlGetProp(cur, "may-encrypt"); + mandatory = XmlStub.xmlGetProp(cur, "mandatory"); + protected = XmlStub.xmlGetProp(cur, "protected"); + vendorBit = XmlStub.xmlGetProp(cur, "vendor-bit"); + vendorName = XmlStub.xmlGetProp(cur, "vendor-id"); + constrained = XmlStub.xmlGetProp(cur, "constrained"); + + cur = cur->xmlChildrenNode; + + while (cur != NULL ) { + if (!strcasecmp((char *)cur->name, "type")) { + type = XmlStub.xmlGetProp(cur, "type-name"); + } + if (!strcasecmp((char *)cur->name, "enum")) { + char *valueName=NULL, *valueCode=NULL; + ValueName *ve = NULL; + valueName = XmlStub.xmlGetProp(cur, "name"); + valueCode = XmlStub.xmlGetProp(cur, "code"); + + if (!valueName || !valueCode) { + g_warning( "Error, bad value on avp %s", name); + return (-1); + } + + ve = g_malloc(sizeof(ValueName)); + ve->name = strdup(valueName); + ve->value = atol(valueCode); + + ve->next = vEntry; + vEntry = ve; + } + if (!strcasecmp((char *)cur->name, "grouped")) { + /* WORK Recurse here for grouped AVPs */ + type = "grouped"; + } + cur=cur->next; + } /* while */ + + /* + * Check for the AVP Type. + */ + if (type) { + for (i = 0; TypeValues[i].strptr; i++) { + if (!strcasecmp(type, TypeValues[i].strptr)) { + avpType = TypeValues[i].value; + break; + } + } + + if (TypeValues[i].strptr == NULL) { + g_warning( "Invalid Type field in dictionary! avp %s (%s)", name, type); + return (-1); + } + } else if (!vEntry) { + g_warning("Missing type/enum field in dictionary avpName=%s", + name); + return (-1); + } + + /* WORK - Handle flags -- for validation later */ + + + /* And, create the entry */ + entry = (avpInfo *)g_malloc(sizeof(avpInfo)); + entry->name = g_strdup(name); + entry->code = atol(code); + if (vendorName) + entry->vendorName = g_strdup(vendorName); + else + entry->vendorName = NULL; + entry->type = avpType; + entry->values = vEntry; + if (vEntry) + entry->type = DIAMETER_INTEGER32; + + /* And, add it to the list */ + entry->next = avpListHead; + avpListHead = entry; + + return (0); +} /* xmlParseAVP */ + +/* + * This routine will add a command to the list of commands. + */ +static int +addCommand(int code, char *name, char *vendorId) +{ + CommandCode *entry; + + /* + * Allocate the memory required for the dictionary. + */ + entry = (CommandCode *) g_malloc(sizeof (CommandCode)); + + if (entry == NULL) { + g_warning("Unable to allocate memory"); + return (-1); + } + + /* + * Allocate memory for the AVPName and copy the name to the + * structure + */ + entry->name = g_strdup(name); + entry->code = code; + if (vendorId) + entry->vendorString = g_strdup(vendorId); + else + entry->vendorString = NULL; + + /* Add the entry to the list */ + entry->next = commandListHead; + commandListHead = entry; + + return 0; +} /* addCommand */ + +/* + * This routine will parse the XML command, and add it to our + * list of commands. + */ +static int +xmlParseCommand(xmlDocPtr doc, xmlNodePtr cur) +{ + guint32 vendorId = 0; + char *name, *code, *vendorIdString; + + /* + * Get the Attributes + */ + name = XmlStub.xmlGetProp(cur, "name"); + code = XmlStub.xmlGetProp(cur, "code"); + if (!name || !code) { + g_warning("Invalid command. Name or code missing!"); + return -1; + } + vendorIdString = XmlStub.xmlGetProp(cur, "vendor-id"); + + if (!vendorIdString || !strcasecmp(vendorIdString, "None")) { + vendorIdString = NULL; + } + + return (addCommand(atoi(code), name, vendorIdString)); +} /* xmlParseCommand */ + +/* This routine adds an application to the name<-> id table */ +static int +dictionaryAddApplication(char *name, int id) +{ + ApplicationId *entry; + + if (!name || (id <= 0)) { + g_warning( "Diameter Error: Inavlid application (name=%p, id=%d)", + name, id); + return (-1); + } /* Sanity Checks */ + + entry = g_malloc(sizeof(ApplicationId)); + if (!entry) { + g_warning( "Unable to allocate memory"); + return (-1); + } + + entry->name = g_strdup(name); + entry->id = id; + + /* Add it to the list */ + entry->next = ApplicationIdHead; + ApplicationIdHead = entry; + + return 0; +} /* dictionaryAddApplication */ + +/* + * This routine will add a vendor to the vendors list + */ +static int +addVendor(int id, gchar *name, gchar *longName) +{ + VendorId *vendor; + + /* add entry */ + vendor=g_malloc(sizeof(VendorId)); + if (!vendor) { + return (-1); + } + + vendor->id = id; + vendor->name = g_strdup(name); + vendor->longName = g_strdup(longName); + vendor->next = vendorListHead; + vendorListHead = vendor; + + return 0; +} /* addVendor */ + +/* + * This routine will pars in a XML vendor entry. + */ +static int +xmlParseVendor(xmlDocPtr doc, xmlNodePtr cur) +{ + char *name=NULL, *code=NULL, *id=NULL; + + /* First, get our properties */ + id = XmlStub.xmlGetProp(cur, "vendor-id"); + name = XmlStub.xmlGetProp(cur, "name"); + code = XmlStub.xmlGetProp(cur, "code"); + + if (!id || !name || !code) { + g_warning( "Invalid vendor section. vendor-id, name, and code must be specified"); + return -1; + } + + return (addVendor(atoi(code), id, name)); +} /* addVendor */ + +/* + * This routine will either parse in the base protocol, or an application. + */ +static int +xmlDictionaryParseSegment(xmlDocPtr doc, xmlNodePtr cur, int base) +{ + if (!base) { + char *name; + char *id; + + /* Add our application */ + id = XmlStub.xmlGetProp(cur, "id"); + name = XmlStub.xmlGetProp(cur, "name"); + + if (!name || !id) { + /* ERROR!!! */ + g_warning("Diameter: Invalid application!: name=\"%s\", id=\"%s\"", + name?name:"NULL", id?id:"NULL"); + return -1; + } + + /* Add the application */ + if (dictionaryAddApplication(name, atol(id)) != 0) { + /* ERROR! */ + return -1; + } + } + + + /* + * Get segment values + */ + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if (!strcasecmp((char *)cur->name, "avp")) { + /* we have an avp!!! */ + xmlParseAVP(doc, cur); + } else if (!strcasecmp((char *)cur->name, "vendor")) { + /* we have a vendor */ + xmlParseVendor(doc, cur); + /* For now, ignore typedefn and text */ + } else if (!strcasecmp((char *)cur->name, "command")) { + /* Found a command */ + xmlParseCommand(doc,cur); + } else if (!strcasecmp((char *)cur->name, "text")) { + } else if (!strcasecmp((char *)cur->name, "comment")) { + } else if (!strcasecmp((char *)cur->name, "typedefn")) { + /* WORK -- parse in valid types . . . */ + } else { + /* IF we got here, we're an error */ + g_warning("Error! expecting an avp or a typedefn (got \"%s\")", + cur->name); + return (-1); + } + cur = cur->next; + } /* while */ + return 0; +} /* xmlDictionaryParseSegment */ + +/* + * The main xml parse routine. This will walk through an XML + * dictionary that has been parsed by libxml. + */ +static int +xmlDictionaryParse(xmlDocPtr doc, xmlNodePtr cur) +{ + /* We should expect a base protocol, followed by multiple applicaitons */ + while (cur != NULL) { + if (!strcasecmp((char *)cur->name, "base")) { + /* Base protocol. Descend and parse */ + xmlDictionaryParseSegment(doc, cur, 1); + } else if (!strcasecmp((char *)cur->name, "application")) { + /* Application. Descend and parse */ + xmlDictionaryParseSegment(doc, cur, 0); + } else if (!strcasecmp((char *)cur->name, "text")) { + /* Ignore text */ + } else { + g_warning( "Diameter: XML Expecting a base or an application (got \"%s\")", + cur->name); + return (-1); + } + cur = cur->next; + } + + return 0; + +} /* xmlDictionaryParse */ + +/* + * This routine will call libxml to parse in the dictionary. + */ +static int +loadXMLDictionary() +{ + xmlDocPtr doc; + xmlNodePtr cur; + + /* + * build an XML tree from a the file; + */ + XmlStub.xmlKeepBlanksDefault(0); /* Strip leading and trailing blanks */ + XmlStub.xmlSubstituteEntitiesDefault(1); /* Substitute entities automagically */ + doc = xmlParseFilePush(gbl_diameterDictionary, 1); /* Parse the XML (do validity checks)*/ + + /* Check for invalid xml */ + if (doc == NULL) { + g_warning("Diameter: Unable to parse xmldictionary %s", + gbl_diameterDictionary); + return -1; + } + + /* + * Check the document is of the right kind + */ + cur = XmlStub.xmlDocGetRootElement(doc); + if (cur == NULL) { + g_warning("Diameter: Error: \"%s\": empty document", + gbl_diameterDictionary); + XmlStub.xmlFreeDoc(doc); + return -1; + } + if (XmlStub.xmlStrcmp(cur->name, (const xmlChar *) "dictionary")) { + g_warning("Diameter: Error: \"%s\": document of the wrong type, root node != dictionary", + gbl_diameterDictionary); + XmlStub.xmlFreeDoc(doc); + return -1; + } + + /* + * Ok, the dictionary has been parsed by libxml, and is valid. + * All we have to do now is read in our information. + */ + if (xmlDictionaryParse(doc, cur->xmlChildrenNode) != 0) { + /* Error has already been printed */ + return -1; + } + + /* Once we're done parsing, free up the xml memory */ + XmlStub.xmlFreeDoc(doc); + + return 0; + +} /* loadXMLDictionary */ + +/* + * Fallback routine. In the event of ANY error when loading the XML + * dictionary, this routine will populate the new avp list structures + * with the old static data from packet-diameter-defs.h + */ +static void +initializeDictionaryDefaults() +{ + int i; + + /* Add static vendors to list */ + for(i=0; diameter_vendor_specific_vendors[i].strptr; i++) { + addVendor(diameter_vendor_specific_vendors[i].value, + diameter_vendor_specific_vendors[i].strptr, + diameter_vendor_specific_vendors[i].strptr); + } + /* Add static commands to list. */ + for(i=0; diameter_command_code_vals[i].strptr; i++) { + addCommand(diameter_command_code_vals[i].value, + diameter_command_code_vals[i].strptr, NULL); + } + + /* Add static AVPs to list */ + for (i=0; old_diameter_avps[i].name; i++) { + addStaticAVP(old_diameter_avps[i].code, + old_diameter_avps[i].name, + old_diameter_avps[i].type, + old_diameter_avps[i].values); + } + +} /* initializeDictionaryDefaults */ + +/* + * This routine will attempt to load the XML dictionary, and on + * failure, will call initializeDictionaryDefaults to load in + * our static dictionary. + */ +static void +initializeDictionary() +{ + /* + * Using ugly ordering here. If loadLibXML succeeds, then + * loadXMLDictionary will be called. This is one of the few times when + * I think this is prettier than the nested if alternative. + */ + if (loadLibXML() || + (loadXMLDictionary() != 0)) { + /* Something failed. Use the static dictionary */ + g_warning("Diameter: Using static dictionary! (Unable to use XML)"); + initializeDictionaryDefaults(); + } +} /* initializeDictionary */ + + + +/* + * These routines manipulate the diameter structures. + */ + +/* return command string, based on the code */ +static gchar * +diameter_command_to_str(guint32 commandCode) +{ + CommandCode *probe; + static gchar buffer[64]; + + for (probe=commandListHead; probe; probe=probe->next) { + if (commandCode == probe->code) { + return probe->name; + } + } + + snprintf(buffer, sizeof(buffer), + "Cmd-0x%08x", commandCode); + return buffer; +}/*diameter_command_to_str */ +/* return vendor string, based on the id */ +static gchar * +diameter_vendor_to_str(guint32 vendorId) { + VendorId *probe; + static gchar buffer[64]; + + for (probe=vendorListHead; probe; probe=probe->next) { + if (vendorId == probe->id) { + return probe->longName; + } + } + + snprintf(buffer, sizeof(buffer), + "Vendor 0x%08x", vendorId); + return buffer; +} /*diameter_vendor_to_str */ +/* return application string, based on the id */ +static gchar * +diameter_app_to_str(guint32 vendorId) { + ApplicationId *probe; + static gchar buffer[64]; + for (probe=ApplicationIdHead; probe; probe=probe->next) { + if (vendorId == probe->id) { + return probe->name; + } + } -/* Diameter Manipulation Routines (mess with our strucutres) */ + snprintf(buffer, sizeof(buffer), + "AppId 0x%08x", vendorId); + return buffer; +} /*diameter_app_to_str */ +/* return an avp type, based on the code */ diameterDataType diameter_avp_get_type(guint32 avpCode){ - int i; - for (i=0; diameter_avps[i].name; i++) { - if (avpCode == diameter_avps[i].code) { + avpInfo *probe; + + for (probe=avpListHead; probe; probe=probe->next) { + if (avpCode == probe->code) { /* We found it! */ - return diameter_avps[i].type; + return probe->type; } } + /* If we don't find it, assume it's data */ - g_warning("DIAMETER: Unable to find type for avpCode %d!", avpCode); + g_warning("Diameter: Unable to find type for avpCode %d!", avpCode); return DIAMETER_OCTET_STRING; } /* diameter_avp_get_type */ +/* return an avp name from the code */ static gchar * diameter_avp_get_name(guint32 avpCode) { static gchar buffer[64]; + avpInfo *probe; - int i; - for (i=0; diameter_avps[i].name; i++) { - if (avpCode == diameter_avps[i].code) { + for (probe=avpListHead; probe; probe=probe->next) { + if (avpCode == probe->code) { /* We found it! */ - return diameter_avps[i].name; + return probe->name; } } /* If we don't find it, build a name string */ @@ -239,13 +887,18 @@ diameter_avp_get_value(guint32 avpCode, guint32 avpValue) { static gchar buffer[64]; - int i; - for (i=0; diameter_avps[i].name; i++) { - if (avpCode == diameter_avps[i].code) { - /* We found the code. Now find the value! */ - if (!diameter_avps[i].values) - break; - return val_to_str(avpValue, diameter_avps[i].values , "Unknown Value: 0x%08x"); + avpInfo *probe; + + for (probe=avpListHead; probe; probe=probe->next) { + if (avpCode == probe->code) { + ValueName *vprobe; + for(vprobe=probe->values; vprobe; vprobe=vprobe->next) { + if (avpValue == vprobe->value) { + return vprobe->name; + } + } + sprintf(buffer, "Unknown Value: 0x%08x", avpValue); + return buffer; } } /* If we don't find the avp, build a value string */ @@ -296,6 +949,17 @@ static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree gchar commandString[64], vendorString[64]; gint i; guint bpos; + static int initialized=FALSE; + + /* + * Only parse in dictionary if there are diameter packets to + * dissect. + */ + if (!initialized) { + /* Read in our dictionary, if it exists. */ + initializeDictionary(); + initialized=TRUE; + } /* Make entries in Protocol column and Info column on summary display */ if (check_col(pinfo->fd, COL_PROTOCOL)) @@ -315,7 +979,7 @@ static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree if (dh.vendorId) { strcpy(vendorString, - val_to_str(dh.vendorId, diameter_vendor_specific_vendors, "Unknown Vendor: %08x")); + diameter_vendor_to_str(dh.vendorId)); } else { strcpy(vendorString, "None"); } @@ -345,7 +1009,7 @@ static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree } /* Set up our commandString */ - strcpy(commandString, val_to_str(commandCode, diameter_command_code_vals, "Unknown Command: 0x%08x")); + strcpy(commandString, diameter_command_to_str(commandCode)); if (flags & DIAM_FLAGS_R) strcat(commandString, "-Request"); else @@ -353,7 +1017,7 @@ static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree /* Short packet. Should have at LEAST one avp */ if (pktLength < MIN_DIAMETER_SIZE) { - g_warning("DIAMETER: Packet too short: %d bytes less than min size (%d bytes))", + g_warning("Diameter: Packet too short: %d bytes less than min size (%d bytes))", pktLength, MIN_DIAMETER_SIZE); BadPacket = TRUE; } @@ -361,17 +1025,16 @@ static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree /* And, check our reserved flags/version */ if ((flags & DIAM_FLAGS_RESERVED) || (version != 1)) { - g_warning("DIAMETER: Bad packet: Bad Flags(0x%x) or Version(%u)", + g_warning("Diameter: Bad packet: Bad Flags(0x%x) or Version(%u)", flags, version); BadPacket = TRUE; } if (check_col(pinfo->fd, COL_INFO)) { col_add_fstr(pinfo->fd, COL_INFO, - "%s%s%s%s: %s vendor=%s (hop-id=%d) (end-id=%d) RPE=%d%d%d", + "%s%s%s: %s vendor=%s (hop-id=%d) (end-id=%d) RPE=%d%d%d", (BadPacket)?"***** Bad Packet!: ":"", (flags & DIAM_FLAGS_P)?"Proxyable ":"", - (flags & DIAM_FLAGS_R)?"Request":"Answer", (flags & DIAM_FLAGS_E)?" Error":"", commandString, vendorString, dh.hopByHopId, dh.endToEndId, @@ -421,12 +1084,12 @@ static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree /* Command Code */ proto_tree_add_uint_format(diameter_tree, hf_diameter_code, - tvb, offset, 3, commandCode, "Command Code: %s", commandString); + tvb, offset, 3, commandCode, "Command Code: %s", commandString); offset += 3; /* Vendor Id */ proto_tree_add_uint_format(diameter_tree,hf_diameter_vendor_id, - tvb, offset, 4, dh.vendorId, "Vendor-Id: %s", vendorString); + tvb, offset, 4, dh.vendorId, "Vendor-Id: %s", vendorString); offset += 4; /* Hop-by-hop Identifier */ @@ -464,6 +1127,64 @@ static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree } /* dissect_diameter */ /* + * Call the mip_dissector, after saving our pinfo variables + * so it doesn't write to our column display. + */ +static void +safe_dissect_mip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + size_t offset, size_t length) +{ + static dissector_handle_t mip_handle; + static int mipInitialized=FALSE; + tvbuff_t *mip_tvb; + address save_dl_src; + address save_dl_dst; + address save_net_src; + address save_net_dst; + address save_src; + address save_dst; + gboolean save_in_error_pkt; + + if (!mipInitialized) { + mip_handle = find_dissector("mip"); + mipInitialized=TRUE; + } + + mip_tvb = tvb_new_subset(tvb, offset, + MIN(length, tvb_length(tvb)-offset), + length); + + /* The contained packet is a MIP registration request; + dissect it with the MIP dissector. */ + col_set_writable(pinfo->fd, FALSE); + + /* Also, save the current values of the addresses, and restore + them when we're finished dissecting the contained packet, so + that the address columns in the summary don't reflect the + contained packet, but reflect this packet instead. */ + save_dl_src = pinfo->dl_src; + save_dl_dst = pinfo->dl_dst; + save_net_src = pinfo->net_src; + save_net_dst = pinfo->net_dst; + save_src = pinfo->src; + save_dst = pinfo->dst; + save_in_error_pkt = pinfo->in_error_pkt; + + call_dissector(mip_handle, mip_tvb, pinfo, tree); + + /* Restore the "we're inside an error packet" flag. */ + pinfo->in_error_pkt = save_in_error_pkt; + pinfo->dl_src = save_dl_src; + pinfo->dl_dst = save_dl_dst; + pinfo->net_src = save_net_src; + pinfo->net_dst = save_net_dst; + pinfo->src = save_src; + pinfo->dst = save_dst; + + +} /* safe_dissect_mip */ + +/* * This function will dissect the AVPs in a diameter packet. It handles * all normal types, and even recursively calls itself for grouped AVPs */ @@ -482,6 +1203,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree size_t offset = 0 ; char dataBuffer[4096]; tvbuff_t *group_tvb; + tvbuff_t *mip_tvb; proto_tree *group_tree; proto_item *grouptf; proto_item *avptf; @@ -514,7 +1236,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree /* Check for short packet */ if (packetLength < (long)MIN_AVP_SIZE) { - g_warning("DIAMETER: AVP Payload too short: %d bytes less than min size (%d bytes))", + g_warning("Diameter: AVP Payload too short: %d bytes less than min size (%d bytes))", packetLength, MIN_AVP_SIZE); BadPacket = TRUE; /* Don't even bother trying to parse a short packet. */ @@ -562,7 +1284,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree if (vendorId) { strcpy(vendorString, - val_to_str(vendorId, diameter_vendor_specific_vendors, "Unknown Vendor: %08x")); + diameter_vendor_to_str(vendorId)); } else { vendorString[0]='\0'; } @@ -570,7 +1292,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree /* Check for bad length */ if (avpLength < MIN_AVP_SIZE || ((long)avpLength > packetLength)) { - g_warning("DIAMETER: AVP payload size invalid: avp_length: %d bytes, " + g_warning("Diameter: AVP payload size invalid: avp_length: %d bytes, " "min: %d bytes, packetLen: %d", avpLength, MIN_AVP_SIZE, packetLength); BadPacket = TRUE; @@ -578,7 +1300,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree /* Check for bad flags */ if (flags & AVP_FLAGS_RESERVED) { - g_warning("DIAMETER: Invalid AVP: Reserved bit set. flags = 0x%x," + g_warning("Diameter: Invalid AVP: Reserved bit set. flags = 0x%x," " resFl=0x%x", flags, AVP_FLAGS_RESERVED); /* For now, don't set bad packet, since I'm accidentally setting a wrong bit */ @@ -597,14 +1319,14 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree /* Check for out of bounds */ if (packetLength < 0) { - g_warning("DIAMETER: Bad AVP: Bad new length (%d bytes) ", + g_warning("Diameter: Bad AVP: Bad new length (%d bytes) ", packetLength); BadPacket = TRUE; } /* Make avp Name & type */ - strcpy(avpTypeString, val_to_str(diameter_avp_get_type(avph.avp_code), diameter_avp_type_vals, - "Unknown-Type: 0x%08x")); + strcpy(avpTypeString, val_to_str(diameter_avp_get_type(avph.avp_code), TypeValues, + "Unknown-Type: 0x%08x")); strcpy(avpNameString, diameter_avp_get_name(avph.avp_code)); avptf = proto_tree_add_text(avp_tree, tvb, @@ -618,7 +1340,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree if (avpi_tree !=NULL) { /* Command Code */ proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_code, - tvb, offset, 4, avph.avp_code, "AVP Code: %s", avpNameString); + tvb, offset, 4, avph.avp_code, "AVP Code: %s", avpNameString); offset += 4; tf = proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_flags, tvb, @@ -775,6 +1497,36 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree "Value: 0x%08x (%u): %s", data, data, valstr); } break; + case DIAMETER_VENDOR_ID: + { + guint32 data; + + memcpy(&data, dataBuffer, 4); + data = ntohl(data); + valstr = diameter_vendor_to_str(data); + proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32, + tvb, offset, avpDataLength, data, + "%s (0x%08x)", valstr, data); + } + break; + case DIAMETER_APPLICATION_ID: + { + guint32 data; + + memcpy(&data, dataBuffer, 4); + data = ntohl(data); + valstr = diameter_app_to_str(data); + proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32, + tvb, offset, avpDataLength, data, + "%s (0x%08x)", valstr, data); + } + break; + case DIAMETER_MIP_REG_REQ: + + /* Make a new tvb */ + safe_dissect_mip(tvb, pinfo, avpi_tree, offset, avpDataLength); + break; + default: case DIAMETER_OCTET_STRING: proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes, @@ -794,36 +1546,35 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree void proto_reg_handoff_diameter(void) { - static int Initialized=FALSE; - static int TcpPort=0; - static int SctpPort=0; + static int Initialized=FALSE; + static int TcpPort=0; + static int SctpPort=0; - if (Initialized) { - dissector_delete("tcp.port", TcpPort, dissect_diameter); - dissector_delete("sctp.port", SctpPort, dissect_diameter); - } else { - Initialized=TRUE; - } + if (Initialized) { + dissector_delete("tcp.port", TcpPort, dissect_diameter); + dissector_delete("sctp.port", SctpPort, dissect_diameter); + } else { + Initialized=TRUE; + } - /* set port for future deletes */ - TcpPort=gbl_diameterTcpPort; - SctpPort=gbl_diameterSctpPort; + /* set port for future deletes */ + TcpPort=gbl_diameterTcpPort; + SctpPort=gbl_diameterSctpPort; - strcpy(gbl_diameterString, "Diameter Protocol"); + strcpy(gbl_diameterString, "Diameter Protocol"); - /* g_warning ("Diameter: Adding tcp dissector to port %d", - gbl_diameterTcpPort); */ - dissector_add("tcp.port", gbl_diameterTcpPort, dissect_diameter, - proto_diameter); - dissector_add("sctp.port", gbl_diameterSctpPort, - dissect_diameter, proto_diameter); + /* g_warning ("Diameter: Adding tcp dissector to port %d", + gbl_diameterTcpPort); */ + dissector_add("tcp.port", gbl_diameterTcpPort, dissect_diameter, + proto_diameter); + dissector_add("sctp.port", gbl_diameterSctpPort, + dissect_diameter, proto_diameter); } /* registration with the filtering engine */ void proto_register_diameter(void) { - static hf_register_info hf[] = { { &hf_diameter_version, { "Version", "diameter.version", FT_UINT8, BASE_HEX, NULL, 0x00, @@ -831,34 +1582,34 @@ proto_register_diameter(void) { &hf_diameter_length, { "Length","diameter.length", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL }}, - + { &hf_diameter_flags, { "Flags", "diameter.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, { &hf_diameter_flags_request, - { "Request", "diameter.flags.request", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_R, + { "Request", "diameter.flags.request", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_R, "", HFILL }}, { &hf_diameter_flags_proxyable, - { "Proxyable", "diameter.flags.proxyable", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_P, + { "Proxyable", "diameter.flags.proxyable", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_P, "", HFILL }}, { &hf_diameter_flags_error, - { "Error","diameter.flags.error", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_E, + { "Error","diameter.flags.error", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_E, "", HFILL }}, { &hf_diameter_flags_reserved3, - { "Reserved","diameter.flags.reserved3", FT_BOOLEAN, 8, TFS(&reserved_set), - DIAM_FLAGS_RESERVED3, "", HFILL }}, + { "Reserved","diameter.flags.reserved3", FT_BOOLEAN, 8, TFS(&reserved_set), + DIAM_FLAGS_RESERVED3, "", HFILL }}, { &hf_diameter_flags_reserved4, - { "Reserved","diameter.flags.reserved4", FT_BOOLEAN, 8, TFS(&reserved_set), - DIAM_FLAGS_RESERVED4, "", HFILL }}, + { "Reserved","diameter.flags.reserved4", FT_BOOLEAN, 8, TFS(&reserved_set), + DIAM_FLAGS_RESERVED4, "", HFILL }}, { &hf_diameter_flags_reserved5, - { "Reserved","diameter.flags.reserved5", FT_BOOLEAN, 8, TFS(&reserved_set), - DIAM_FLAGS_RESERVED5, "", HFILL }}, + { "Reserved","diameter.flags.reserved5", FT_BOOLEAN, 8, TFS(&reserved_set), + DIAM_FLAGS_RESERVED5, "", HFILL }}, { &hf_diameter_flags_reserved6, - { "Reserved","diameter.flags.reserved6", FT_BOOLEAN, 8, TFS(&reserved_set), - DIAM_FLAGS_RESERVED6, "", HFILL }}, + { "Reserved","diameter.flags.reserved6", FT_BOOLEAN, 8, TFS(&reserved_set), + DIAM_FLAGS_RESERVED6, "", HFILL }}, { &hf_diameter_flags_reserved7, - { "Reserved","diameter.flags.reserved7", FT_BOOLEAN, 8, TFS(&reserved_set), - DIAM_FLAGS_RESERVED7, "", HFILL }}, + { "Reserved","diameter.flags.reserved7", FT_BOOLEAN, 8, TFS(&reserved_set), + DIAM_FLAGS_RESERVED7, "", HFILL }}, { &hf_diameter_code, { "Command Code","diameter.code", FT_UINT24, BASE_DEC, @@ -872,7 +1623,7 @@ proto_register_diameter(void) { &hf_diameter_endtoendid, { "End-to-End Identifier", "diameter.endtoendid", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, - + { &hf_diameter_avp_code, { "AVP Code","diameter.avp.code", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, @@ -885,29 +1636,29 @@ proto_register_diameter(void) { "AVP Flags","diameter.avp.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }}, { &hf_diameter_avp_flags_vendor_specific, - { "Vendor-Specific", "diameter.flags.vendorspecific", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_V, + { "Vendor-Specific", "diameter.flags.vendorspecific", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_V, "", HFILL }}, { &hf_diameter_avp_flags_mandatory, - { "Mandatory", "diameter.flags.mandatory", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_M, + { "Mandatory", "diameter.flags.mandatory", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_M, "", HFILL }}, { &hf_diameter_avp_flags_protected, - { "Protected","diameter.avp.flags.protected", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_P, + { "Protected","diameter.avp.flags.protected", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_P, "", HFILL }}, { &hf_diameter_avp_flags_reserved3, - { "Reserved","diameter.avp.flags.reserved3", FT_BOOLEAN, 8, TFS(&reserved_set), - AVP_FLAGS_RESERVED3, "", HFILL }}, + { "Reserved","diameter.avp.flags.reserved3", FT_BOOLEAN, 8, TFS(&reserved_set), + AVP_FLAGS_RESERVED3, "", HFILL }}, { &hf_diameter_avp_flags_reserved4, - { "Reserved","diameter.avp.flags.reserved4", FT_BOOLEAN, 8, TFS(&reserved_set), - AVP_FLAGS_RESERVED4, "", HFILL }}, + { "Reserved","diameter.avp.flags.reserved4", FT_BOOLEAN, 8, TFS(&reserved_set), + AVP_FLAGS_RESERVED4, "", HFILL }}, { &hf_diameter_avp_flags_reserved5, - { "Reserved","diameter.avp.flags.reserved5", FT_BOOLEAN, 8, TFS(&reserved_set), - AVP_FLAGS_RESERVED5, "", HFILL }}, + { "Reserved","diameter.avp.flags.reserved5", FT_BOOLEAN, 8, TFS(&reserved_set), + AVP_FLAGS_RESERVED5, "", HFILL }}, { &hf_diameter_avp_flags_reserved6, - { "Reserved","diameter.avp.flags.reserved6", FT_BOOLEAN, 8, TFS(&reserved_set), - AVP_FLAGS_RESERVED6, "", HFILL }}, + { "Reserved","diameter.avp.flags.reserved6", FT_BOOLEAN, 8, TFS(&reserved_set), + AVP_FLAGS_RESERVED6, "", HFILL }}, { &hf_diameter_avp_flags_reserved7, - { "Reserved","diameter.avp.flags.reserved7", FT_BOOLEAN, 8, TFS(&reserved_set), - AVP_FLAGS_RESERVED7, "", HFILL }}, + { "Reserved","diameter.avp.flags.reserved7", FT_BOOLEAN, 8, TFS(&reserved_set), + AVP_FLAGS_RESERVED7, "", HFILL }}, { &hf_diameter_avp_vendor_id, { "AVP Vendor Id","diameter.avp.vendorId", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, @@ -926,7 +1677,7 @@ proto_register_diameter(void) { &hf_diameter_avp_data_bytes, { "AVP Data","diameter.avp.data.bytes", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }}, - + { &hf_diameter_avp_data_string, { "AVP Data","diameter.avp.data.string", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, @@ -951,21 +1702,36 @@ proto_register_diameter(void) module_t *diameter_module; proto_diameter = proto_register_protocol (gbl_diameterString, - "DIAMETER", "diameter"); + "Diameter", "diameter"); proto_register_field_array(proto_diameter, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); /* Register a configuration option for port */ diameter_module = prefs_register_protocol(proto_diameter, - proto_reg_handoff_diameter); + proto_reg_handoff_diameter); prefs_register_uint_preference(diameter_module, "tcp.port", - "DIAMETER TCP Port", - "Set the TCP port for DIAMETER messages", - 10, - &gbl_diameterTcpPort); + "Diameter TCP Port", + "Set the TCP port for Diameter messages", + 10, + &gbl_diameterTcpPort); prefs_register_uint_preference(diameter_module, "sctp.port", - "DIAMETER SCTP Port", - "Set the SCTP port for DIAMETER messages", - 10, - &gbl_diameterSctpPort); -} + "Diameter SCTP Port", + "Set the SCTP port for Diameter messages", + 10, + &gbl_diameterSctpPort); + /* + * Build our default dictionary filename + */ + if (! gbl_diameterDictionary) { + gbl_diameterDictionary = (gchar *) g_malloc(strlen(get_datafile_dir()) + + 1 + strlen(DICT_FN) + 1); /* slash + fn + null */ + sprintf(gbl_diameterDictionary, "%s" G_DIR_SEPARATOR_S "%s", + get_datafile_dir(), DICT_FN ); + } + /* Now register its preferences so it can be changed. */ + prefs_register_string_preference(diameter_module, "dictionary.name", + "Diameter XML Dictionary", + "Set the dictionary used for Diameter messages", + &gbl_diameterDictionary); + +} /* proto_register_diameter */ diff --git a/sunping.xml b/sunping.xml new file mode 100644 index 0000000000..fa3cbc96f2 --- /dev/null +++ b/sunping.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> + <application id="555" name="Sun Ping Application" uri="ftp://ftp.ietf.org/internet-drafts/draft-calhoun-diameter-sun-ping-02.txt"> + <!-- *********************** Commands ***************************** --> + <!-- Sun Ping Extension --> + <command name="Ping" code="511" vendor-id="Sun"/> + <!-- ********************** End Commands ************************** --> + <!-- ************************ Sun Ping Extension AVPS ******************* --> + <avp name="Ping-Timestamp-Secs" code="1" vendor-id="Sun" mandatory="mustnot" vendor-bit="must"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Ping-Timestamp-Usecs" code="2" vendor-id="Sun" mandatory="mustnot" vendor-bit="must"> + <type type-name="Unsigned32"/> + </avp> + <avp name="Ping-Timestamp" code="3" vendor-id="Sun" mandatory="mustnot" vendor-bit="must"> + <grouped> + <gavp name="Ping-Timestamp-Secs"/> + <gavp name="Ping-Timestamp-Usecs"/> + </grouped> + </avp> + <!-- ********************** End Sun Ping Extension AVPS ***************** --> + <!-- ************************ Sun PING Extension AVPs ***************************--> + </application> diff --git a/xmlstub.c b/xmlstub.c new file mode 100644 index 0000000000..ffa589cd2e --- /dev/null +++ b/xmlstub.c @@ -0,0 +1,167 @@ +/* xmlstub.c + * Routines to parse XML files using libxml2. This stub + * exists so that the library can be loaded on systems that + * have it. + * + * $Id: xmlstub.c,v 1.1 2001/11/01 21:52:44 guy Exp $ + * + * Copyright (c) 2001 by David Frascone <dave@frascone.com> + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998-2001 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <glib.h> +#include <gmodule.h> + +/* XML Stub routines */ +#define IN_XMLSTUB +#include "xmlstub.h" + +/* + * This routine will dynamically load libxml2 and will populate the + * XmlStub pointer structure. + * + * On any error, it will return non-zero, and it should be assumed that + * the current platform does not have dynamic library support, or does + * not have libxml2 installed. + */ +int +loadLibXML() +{ + GModule *handle; + gpointer symbol; + int error=FALSE; + + if (XmlStubInitialized) { + /* Did you ever get the feeling you've been here before? */ + + /* + * This is not thread safe. With threads, we'd need to + * synchronize all this so two threads can't initialize at once. + */ + return 0; + } + + /* Check to see if gmodule is supported */ + if (!g_module_supported()) { + g_warning("XMLStub: Modules are not supported. Not initializing XML Stub"); + return (-1); + } + + /* open the dll. Is this named something different + * under windows? Perhaps we should check . . . + */ + if ((handle = g_module_open(XML_LIBRARY, G_MODULE_BIND_LAZY)) == NULL) { + g_warning("XMLStub: Unable to open module " XML_LIBRARY); + return (-1); + } + + /* + * Now that the library is open, copy all our relevant + * function pointers and integer pointers into our structure. + */ + if (!g_module_symbol(handle, "xmlParseFile", &symbol)) { + g_warning("Unable to find \"xmlParseFile\""); + error=TRUE; + } + XmlStub.xmlParseFile= (xmlDocPtr(*)(const char *))symbol; + + if (!g_module_symbol(handle, "xmlStrcmp", &symbol)) { + g_warning("Unable to find \"xmlStrcmp\""); + error=TRUE; + } + XmlStub.xmlStrcmp= (int (*)(const xmlChar *, const xmlChar *))symbol; + + if (!g_module_symbol(handle, "xmlCreatePushParserCtxt", &symbol)) { + g_warning("Unable to find \"xmlCreatePushParserCtxt\""); + error=TRUE; + } + XmlStub.xmlCreatePushParserCtxt=(xmlParserCtxtPtr (*) + (xmlSAXHandlerPtr, void *, const char *, + int, const char *)) symbol; + + if (!g_module_symbol(handle, "xmlParseChunk", &symbol)) { + g_warning("Unable to find \"xmlParseChunk\""); + error=TRUE; + } + XmlStub.xmlParseChunk=(int (*)(xmlParserCtxtPtr, const char *, int, int))symbol; + + if (!g_module_symbol(handle, "xmlFreeParserCtxt", &symbol)) { + g_warning("Unable to find \"xmlFreeParserCtxt\""); + error=TRUE; + } + XmlStub.xmlFreeParserCtxt=(void (*)(xmlParserCtxtPtr))symbol; + + if (!g_module_symbol(handle, "xmlDocGetRootElement", &symbol)) { + g_warning("Unable to find \"xmlDocGetRootElement\""); + error=TRUE; + } + XmlStub.xmlDocGetRootElement=(xmlNodePtr(*)(xmlDocPtr))symbol; + + if (!g_module_symbol(handle, "xmlFreeDoc", &symbol)) { + g_warning("Unable to find \"xmlFreeDoc\""); + error=TRUE; + } + XmlStub.xmlFreeDoc=(void (*)(xmlDocPtr))symbol; + + if (!g_module_symbol(handle, "xmlNodeListGetString", &symbol)) { + g_warning("Unable to find \"xmlNodeListGetString\""); + error=TRUE; + } + XmlStub.xmlNodeListGetString=(char * (*)(xmlDocPtr, xmlNodePtr, int))symbol; + + if (!g_module_symbol(handle, "xmlGetProp", &symbol)) { + g_warning("Unable to find \"xmlGetProp\""); + error=TRUE; + } + XmlStub.xmlGetProp=(char * (*)(xmlNodePtr, char *))symbol; + + if (!g_module_symbol(handle, "xmlKeepBlanksDefault", &symbol)) { + g_warning("Unable to find \"xmlKeepBlanksDefault\""); + error=TRUE; + } + XmlStub.xmlKeepBlanksDefault=(int(*)(int))symbol; + + if (!g_module_symbol(handle, "xmlSubstituteEntitiesDefault", &symbol)) { + g_warning("Unable to find \"xmlSubstituteEntitiesDefault\""); + error=TRUE; + } + XmlStub.xmlSubstituteEntitiesDefault=(int(*)(int))symbol; + + if (!g_module_symbol(handle, "xmlDoValidityCheckingDefaultValue", &symbol)) { + g_warning("Unable to find \"xmlDoValidityCheckingDefaultValue\""); + error=TRUE; + } + XmlStub.xmlDoValidityCheckingDefaultValue = (int *)symbol; + + /* + * Return if any of the above functions set our error flag. + * A flag was used, instead of returning immediately, so + * that *all* unresolved symbols would be printed. + */ + if (error) { + g_module_close(handle); + return (-1); + } + /* Set our global so that we don't try to load twice */ + XmlStubInitialized=1; + + return 0; /* Success! */ + +} /* loadLibXML */ diff --git a/xmlstub.h b/xmlstub.h new file mode 100644 index 0000000000..ee2a856670 --- /dev/null +++ b/xmlstub.h @@ -0,0 +1,1119 @@ +/* + * This is part of tree.h from the libxml2 distribution. It is used + * for structure reference when dynamically linking to libxml. + * + * The GPL agreement for this file and for libxml2 can be found at + * http://www.xmlsoft.org + */ + +#include "config.h" + +/****************** From xml headers ************************************/ + +/* + * use those to be sure nothing nasty will happen if + * your library and includes mismatch + */ +#ifndef LIBXML2_COMPILING_MSCCDEF +extern void xmlCheckVersion(int version); +#endif /* LIBXML2_COMPILING_MSCCDEF */ +#define LIBXML_DOTTED_VERSION "2.3.8" +#define LIBXML_VERSION 20308 +#define LIBXML_VERSION_STRING "20308" +#define LIBXML_TEST_VERSION xmlCheckVersion(20308); + +/* + * Whether the trio support need to be configured in + */ +#if 0 +#define WITH_TRIO +#else +#define WITHOUT_TRIO +#endif + +/* + * Whether the FTP support is configured in + */ +#if 1 +#define LIBXML_FTP_ENABLED +#else +#define LIBXML_FTP_DISABLED +#endif + +/* + * Whether the HTTP support is configured in + */ +#if 1 +#define LIBXML_HTTP_ENABLED +#else +#define LIBXML_HTTP_DISABLED +#endif + +/* + * Whether the HTML support is configured in + */ +#if 1 +#define LIBXML_HTML_ENABLED +#else +#define LIBXML_HTML_DISABLED +#endif + +/* + * Whether the SGML Docbook support is configured in + */ +#if 1 +#define LIBXML_DOCB_ENABLED +#else +#define LIBXML_DOCB_DISABLED +#endif + +/* + * Whether XPath is configured in + */ +#if 1 +#define LIBXML_XPATH_ENABLED +#else +#define LIBXML_XPATH_DISABLED +#endif + +/* + * Whether XPointer is configured in + */ +#if 1 +#define LIBXML_XPTR_ENABLED +#else +#define LIBXML_XPTR_DISABLED +#endif + +/* + * Whether XInclude is configured in + */ +#if 1 +#define LIBXML_XINCLUDE_ENABLED +#else +#define LIBXML_XINCLUDE_DISABLED +#endif + +/* + * Whether iconv support is available + */ +#ifndef WIN32 +#if 1 +#define LIBXML_ICONV_ENABLED +#include <iconv.h> +#else +#define LIBXML_ICONV_DISABLED +#endif +#endif + +/* + * Whether Debugging module is configured in + */ +#if 1 +#define LIBXML_DEBUG_ENABLED +#else +#define LIBXML_DEBUG_DISABLED +#endif + +/* + * Whether the memory debugging is configured in + */ +#if 0 +#define DEBUG_MEMORY_LOCATION +#endif + +#ifndef LIBXML_DLL_IMPORT +#if defined(WIN32) && !defined(STATIC) +#define LIBXML_DLL_IMPORT __declspec(dllimport) +#else +#define LIBXML_DLL_IMPORT +#endif +#endif + +#ifdef __GNUC__ +#ifdef HAVE_ANSIDECL_H +#include <ansidecl.h> +#endif +#ifndef ATTRIBUTE_UNUSED +#define ATTRIBUTE_UNUSED +#endif +#else +#define ATTRIBUTE_UNUSED +#endif + + +#define XML_XML_NAMESPACE \ + (const xmlChar *) "http://www.w3.org/XML/1998/namespace" + +/* + * The different element types carried by an XML tree + * + * NOTE: This is synchronized with DOM Level1 values + * See http://www.w3.org/TR/REC-DOM-Level-1/ + * + * Actually this had diverged a bit, and now XML_DOCUMENT_TYPE_NODE should + * be deprecated to use an XML_DTD_NODE. + */ +typedef enum { + XML_ELEMENT_NODE= 1, + XML_ATTRIBUTE_NODE= 2, + XML_TEXT_NODE= 3, + XML_CDATA_SECTION_NODE= 4, + XML_ENTITY_REF_NODE= 5, + XML_ENTITY_NODE= 6, + XML_PI_NODE= 7, + XML_COMMENT_NODE= 8, + XML_DOCUMENT_NODE= 9, + XML_DOCUMENT_TYPE_NODE= 10, + XML_DOCUMENT_FRAG_NODE= 11, + XML_NOTATION_NODE= 12, + XML_HTML_DOCUMENT_NODE= 13, + XML_DTD_NODE= 14, + XML_ELEMENT_DECL= 15, + XML_ATTRIBUTE_DECL= 16, + XML_ENTITY_DECL= 17, + XML_NAMESPACE_DECL= 18, + XML_XINCLUDE_START= 19, + XML_XINCLUDE_END= 20 +#ifdef LIBXML_DOCB_ENABLED + ,XML_DOCB_DOCUMENT_NODE= 21 +#endif +} xmlElementType; + +/* + * Size of an internal character representation. + * + * We use 8bit chars internal representation for memory efficiency, + * Note that with 8 bits wide xmlChars one can still use UTF-8 to handle + * correctly non ISO-Latin input. + */ + +typedef unsigned char xmlChar; + +#ifndef WIN32 +#ifndef CHAR +#define CHAR xmlChar +#endif +#endif + +#define BAD_CAST (xmlChar *) + +/* + * a DTD Notation definition + */ + +typedef struct _xmlNotation xmlNotation; +typedef xmlNotation *xmlNotationPtr; +struct _xmlNotation { + const xmlChar *name; /* Notation name */ + const xmlChar *PublicID; /* Public identifier, if any */ + const xmlChar *SystemID; /* System identifier, if any */ +}; + +/* + * a DTD Attribute definition + */ + +typedef enum { + XML_ATTRIBUTE_CDATA = 1, + XML_ATTRIBUTE_ID, + XML_ATTRIBUTE_IDREF , + XML_ATTRIBUTE_IDREFS, + XML_ATTRIBUTE_ENTITY, + XML_ATTRIBUTE_ENTITIES, + XML_ATTRIBUTE_NMTOKEN, + XML_ATTRIBUTE_NMTOKENS, + XML_ATTRIBUTE_ENUMERATION, + XML_ATTRIBUTE_NOTATION +} xmlAttributeType; + +typedef enum { + XML_ATTRIBUTE_NONE = 1, + XML_ATTRIBUTE_REQUIRED, + XML_ATTRIBUTE_IMPLIED, + XML_ATTRIBUTE_FIXED +} xmlAttributeDefault; + +typedef struct _xmlEnumeration xmlEnumeration; +typedef xmlEnumeration *xmlEnumerationPtr; +struct _xmlEnumeration { + struct _xmlEnumeration *next; /* next one */ + const xmlChar *name; /* Enumeration name */ +}; + +typedef struct _xmlAttribute xmlAttribute; +typedef xmlAttribute *xmlAttributePtr; +struct _xmlAttribute { +#ifndef XML_WITHOUT_CORBA + void *_private; /* for Corba, must be first ! */ +#endif + xmlElementType type; /* XML_ATTRIBUTE_DECL, must be second ! */ + const xmlChar *name; /* Attribute name */ + struct _xmlNode *children; /* NULL */ + struct _xmlNode *last; /* NULL */ + struct _xmlDtd *parent; /* -> DTD */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + struct _xmlAttribute *nexth; /* next in hash table */ + xmlAttributeType atype; /* The attribute type */ + xmlAttributeDefault def; /* the default */ + const xmlChar *defaultValue; /* or the default value */ + xmlEnumerationPtr tree; /* or the enumeration tree if any */ + const xmlChar *prefix; /* the namespace prefix if any */ + const xmlChar *elem; /* Element holding the attribute */ +}; + +/* + * a DTD Element definition. + */ +typedef enum { + XML_ELEMENT_CONTENT_PCDATA = 1, + XML_ELEMENT_CONTENT_ELEMENT, + XML_ELEMENT_CONTENT_SEQ, + XML_ELEMENT_CONTENT_OR +} xmlElementContentType; + +typedef enum { + XML_ELEMENT_CONTENT_ONCE = 1, + XML_ELEMENT_CONTENT_OPT, + XML_ELEMENT_CONTENT_MULT, + XML_ELEMENT_CONTENT_PLUS +} xmlElementContentOccur; + +typedef struct _xmlElementContent xmlElementContent; +typedef xmlElementContent *xmlElementContentPtr; +struct _xmlElementContent { + xmlElementContentType type; /* PCDATA, ELEMENT, SEQ or OR */ + xmlElementContentOccur ocur; /* ONCE, OPT, MULT or PLUS */ + const xmlChar *name; /* Element name */ + struct _xmlElementContent *c1; /* first child */ + struct _xmlElementContent *c2; /* second child */ + struct _xmlElementContent *parent; /* parent */ +}; + +typedef enum { + XML_ELEMENT_TYPE_UNDEFINED = 0, + XML_ELEMENT_TYPE_EMPTY = 1, + XML_ELEMENT_TYPE_ANY, + XML_ELEMENT_TYPE_MIXED, + XML_ELEMENT_TYPE_ELEMENT +} xmlElementTypeVal; + +typedef struct _xmlElement xmlElement; +typedef xmlElement *xmlElementPtr; +struct _xmlElement { +#ifndef XML_WITHOUT_CORBA + void *_private; /* for Corba, must be first ! */ +#endif + xmlElementType type; /* XML_ELEMENT_DECL, must be second ! */ + const xmlChar *name; /* Element name */ + struct _xmlNode *children; /* NULL */ + struct _xmlNode *last; /* NULL */ + struct _xmlDtd *parent; /* -> DTD */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + xmlElementTypeVal etype; /* The type */ + xmlElementContentPtr content; /* the allowed element content */ + xmlAttributePtr attributes; /* List of the declared attributes */ + const xmlChar *prefix; /* the namespace prefix if any */ +}; + +/* + * An XML namespace. + * Note that prefix == NULL is valid, it defines the default namespace + * within the subtree (until overriden). + * + * XML_GLOBAL_NAMESPACE is now deprecated for good + * xmlNsType is unified with xmlElementType + */ + +#define XML_LOCAL_NAMESPACE XML_NAMESPACE_DECL +typedef xmlElementType xmlNsType; + +typedef struct _xmlNs xmlNs; +typedef xmlNs *xmlNsPtr; +struct _xmlNs { + struct _xmlNs *next; /* next Ns link for this node */ + xmlNsType type; /* global or local */ + const xmlChar *href; /* URL for the namespace */ + const xmlChar *prefix; /* prefix for the namespace */ +}; + +/* + * An XML DtD, as defined by <!DOCTYPE. + */ +typedef struct _xmlDtd xmlDtd; +typedef xmlDtd *xmlDtdPtr; +struct _xmlDtd { +#ifndef XML_WITHOUT_CORBA + void *_private; /* for Corba, must be first ! */ +#endif + xmlElementType type; /* XML_DTD_NODE, must be second ! */ + const xmlChar *name; /* Name of the DTD */ + struct _xmlNode *children; /* the value of the property link */ + struct _xmlNode *last; /* last child link */ + struct _xmlDoc *parent; /* child->parent link */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + /* End of common part */ + void *notations; /* Hash table for notations if any */ + void *elements; /* Hash table for elements if any */ + void *attributes; /* Hash table for attributes if any */ + void *entities; /* Hash table for entities if any */ + const xmlChar *ExternalID; /* External identifier for PUBLIC DTD */ + const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC DTD */ + void *pentities; /* Hash table for param entities if any */ +}; + +/* + * A attribute of an XML node. + */ +typedef struct _xmlAttr xmlAttr; +typedef xmlAttr *xmlAttrPtr; +struct _xmlAttr { +#ifndef XML_WITHOUT_CORBA + void *_private; /* for Corba, must be first ! */ +#endif + xmlElementType type; /* XML_ATTRIBUTE_NODE, must be second ! */ + const xmlChar *name; /* the name of the property */ + struct _xmlNode *children; /* the value of the property */ + struct _xmlNode *last; /* NULL */ + struct _xmlNode *parent; /* child->parent link */ + struct _xmlAttr *next; /* next sibling link */ + struct _xmlAttr *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + xmlNs *ns; /* pointer to the associated namespace */ + xmlAttributeType atype; /* the attribute type if validating */ +}; + +/* + * An XML ID instance. + */ + +typedef struct _xmlID xmlID; +typedef xmlID *xmlIDPtr; +struct _xmlID { + struct _xmlID *next; /* next ID */ + const xmlChar *value; /* The ID name */ + xmlAttrPtr attr; /* The attribut holding it */ +}; + +/* + * An XML IDREF instance. + */ + +typedef struct _xmlRef xmlRef; +typedef xmlRef *xmlRefPtr; +struct _xmlRef { + struct _xmlRef *next; /* next Ref */ + const xmlChar *value; /* The Ref name */ + xmlAttrPtr attr; /* The attribut holding it */ +}; + +/* + * A buffer structure + */ + +typedef enum { + XML_BUFFER_ALLOC_DOUBLEIT, + XML_BUFFER_ALLOC_EXACT +} xmlBufferAllocationScheme; + +typedef struct _xmlBuffer xmlBuffer; +typedef xmlBuffer *xmlBufferPtr; +struct _xmlBuffer { + xmlChar *content; /* The buffer content UTF8 */ + unsigned int use; /* The buffer size used */ + unsigned int size; /* The buffer size */ + xmlBufferAllocationScheme alloc; /* The realloc method */ +}; + +/* + * A node in an XML tree. + */ +typedef struct _xmlNode xmlNode; +typedef xmlNode *xmlNodePtr; +struct _xmlNode { +#ifndef XML_WITHOUT_CORBA + void *_private; /* for Corba, must be first ! */ +#endif + xmlElementType type; /* type number, must be second ! */ + const xmlChar *name; /* the name of the node, or the entity */ + struct _xmlNode *children; /* parent->childs link */ + struct _xmlNode *last; /* last child link */ + struct _xmlNode *parent; /* child->parent link */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + xmlNs *ns; /* pointer to the associated namespace */ +#ifndef XML_USE_BUFFER_CONTENT + xmlChar *content; /* the content */ +#else + xmlBufferPtr content; /* the content in a buffer */ +#endif + + /* End of common part */ + struct _xmlAttr *properties;/* properties list */ + xmlNs *nsDef; /* namespace definitions on this node */ +}; + +/* + * An XML document. + */ +typedef struct _xmlDoc xmlDoc; +typedef xmlDoc *xmlDocPtr; +struct _xmlDoc { +#ifndef XML_WITHOUT_CORBA + void *_private; /* for Corba, must be first ! */ +#endif + xmlElementType type; /* XML_DOCUMENT_NODE, must be second ! */ + char *name; /* name/filename/URI of the document */ + struct _xmlNode *children; /* the document tree */ + struct _xmlNode *last; /* last child link */ + struct _xmlNode *parent; /* child->parent link */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* autoreference to itself */ + + /* End of common part */ + int compression;/* level of zlib compression */ + int standalone; /* standalone document (no external refs) */ + struct _xmlDtd *intSubset; /* the document internal subset */ + struct _xmlDtd *extSubset; /* the document external subset */ + struct _xmlNs *oldNs; /* Global namespace, the old way */ + const xmlChar *version; /* the XML version string */ + const xmlChar *encoding; /* external initial encoding, if any */ + void *ids; /* Hash table for ID attributes if any */ + void *refs; /* Hash table for IDREFs attributes if any */ + const xmlChar *URL; /* The URI for that document */ + int charset; /* encoding of the in-memory content + actually an xmlCharEncoding */ +}; + +/** + * Predefined values for some standard encodings + * Libxml don't do beforehand translation on UTF8, ISOLatinX + * It also support UTF16 (LE and BE) by default. + * + * Anything else would have to be translated to UTF8 before being + * given to the parser itself. The BOM for UTF16 and the encoding + * declaration are looked at and a converter is looked for at that + * point. If not found the parser stops here as asked by the XML REC + * Converter can be registered by the user using xmlRegisterCharEncodingHandler + * but the currentl form doesn't allow stateful transcoding (a serious + * problem agreed !). If iconv has been found it will be used + * automatically and allow stateful transcoding, the simplest is then + * to be sure to enable icon and to provide iconv libs for the encoding + * support needed. + */ +typedef enum { + XML_CHAR_ENCODING_ERROR= -1, /* No char encoding detected */ + XML_CHAR_ENCODING_NONE= 0, /* No char encoding detected */ + XML_CHAR_ENCODING_UTF8= 1, /* UTF-8 */ + XML_CHAR_ENCODING_UTF16LE= 2, /* UTF-16 little endian */ + XML_CHAR_ENCODING_UTF16BE= 3, /* UTF-16 big endian */ + XML_CHAR_ENCODING_UCS4LE= 4, /* UCS-4 little endian */ + XML_CHAR_ENCODING_UCS4BE= 5, /* UCS-4 big endian */ + XML_CHAR_ENCODING_EBCDIC= 6, /* EBCDIC uh! */ + XML_CHAR_ENCODING_UCS4_2143=7, /* UCS-4 unusual ordering */ + XML_CHAR_ENCODING_UCS4_3412=8, /* UCS-4 unusual ordering */ + XML_CHAR_ENCODING_UCS2= 9, /* UCS-2 */ + XML_CHAR_ENCODING_8859_1= 10,/* ISO-8859-1 ISO Latin 1 */ + XML_CHAR_ENCODING_8859_2= 11,/* ISO-8859-2 ISO Latin 2 */ + XML_CHAR_ENCODING_8859_3= 12,/* ISO-8859-3 */ + XML_CHAR_ENCODING_8859_4= 13,/* ISO-8859-4 */ + XML_CHAR_ENCODING_8859_5= 14,/* ISO-8859-5 */ + XML_CHAR_ENCODING_8859_6= 15,/* ISO-8859-6 */ + XML_CHAR_ENCODING_8859_7= 16,/* ISO-8859-7 */ + XML_CHAR_ENCODING_8859_8= 17,/* ISO-8859-8 */ + XML_CHAR_ENCODING_8859_9= 18,/* ISO-8859-9 */ + XML_CHAR_ENCODING_2022_JP= 19,/* ISO-2022-JP */ + XML_CHAR_ENCODING_SHIFT_JIS=20,/* Shift_JIS */ + XML_CHAR_ENCODING_EUC_JP= 21,/* EUC-JP */ + XML_CHAR_ENCODING_ASCII= 22 /* pure ASCII */ +} xmlCharEncoding; + +/** + * xmlCharEncodingInputFunc: + * @out: a pointer ot an array of bytes to store the UTF-8 result + * @outlen: the lenght of @out + * @in: a pointer ot an array of chars in the original encoding + * @inlen: the lenght of @in + * + * Take a block of chars in the original encoding and try to convert + * it to an UTF-8 block of chars out. + * + * Returns the number of byte written, or -1 by lack of space, or -2 + * if the transcoding failed. + * The value of @inlen after return is the number of octets consumed + * as the return value is positive, else unpredictiable. + * The value of @outlen after return is the number of ocetes consumed. + */ +typedef int (* xmlCharEncodingInputFunc)(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen); + + +/** + * xmlCharEncodingOutputFunc: + * @out: a pointer ot an array of bytes to store the result + * @outlen: the lenght of @out + * @in: a pointer ot an array of UTF-8 chars + * @inlen: the lenght of @in + * + * Take a block of UTF-8 chars in and try to convert it to an other + * encoding. + * Note: a first call designed to produce heading info is called with + * in = NULL. If stateful this should also initialize the encoder state + * + * Returns the number of byte written, or -1 by lack of space, or -2 + * if the transcoding failed. + * The value of @inlen after return is the number of octets consumed + * as the return value is positive, else unpredictiable. + * The value of @outlen after return is the number of ocetes consumed. + */ +typedef int (* xmlCharEncodingOutputFunc)(unsigned char* out, int *outlen, + const unsigned char* in, int *inlen); + + +/* + * Block defining the handlers for non UTF-8 encodings. + * If iconv is supported, there is two extra fields + */ + +typedef struct _xmlCharEncodingHandler xmlCharEncodingHandler; +typedef xmlCharEncodingHandler *xmlCharEncodingHandlerPtr; +struct _xmlCharEncodingHandler { + char *name; + xmlCharEncodingInputFunc input; + xmlCharEncodingOutputFunc output; +#ifdef LIBXML_ICONV_ENABLED + iconv_t iconv_in; + iconv_t iconv_out; +#endif /* LIBXML_ICONV_ENABLED */ +}; + +typedef int (*xmlInputMatchCallback) (char const *filename); +typedef void * (*xmlInputOpenCallback) (char const *filename); +typedef int (*xmlInputReadCallback) (void * context, char * buffer, int len); +typedef void (*xmlInputCloseCallback) (void * context); + +typedef struct _xmlParserInputBuffer xmlParserInputBuffer; +typedef xmlParserInputBuffer *xmlParserInputBufferPtr; +struct _xmlParserInputBuffer { + void* context; + xmlInputReadCallback readcallback; + xmlInputCloseCallback closecallback; + + xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */ + + xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 */ + xmlBufferPtr raw; /* if encoder != NULL buffer for raw input */ +}; + + +/* + * Those are the functions and datatypes for the library output + * I/O structures. + */ + +typedef int (*xmlOutputMatchCallback) (char const *filename); +typedef void * (*xmlOutputOpenCallback) (char const *filename); +typedef int (*xmlOutputWriteCallback) (void * context, const char * buffer, + int len); +typedef void (*xmlOutputCloseCallback) (void * context); + +typedef struct _xmlOutputBuffer xmlOutputBuffer; +typedef xmlOutputBuffer *xmlOutputBufferPtr; +struct _xmlOutputBuffer { + void* context; + xmlOutputWriteCallback writecallback; + xmlOutputCloseCallback closecallback; + + xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */ + + xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 or ISOLatin */ + xmlBufferPtr conv; /* if encoder != NULL buffer for output */ + int written; /* total number of byte written */ +}; + +#define XML_DEFAULT_VERSION "1.0" + +/** + * an xmlParserInput is an input flow for the XML processor. + * Each entity parsed is associated an xmlParserInput (except the + * few predefined ones). This is the case both for internal entities + * - in which case the flow is already completely in memory - or + * external entities - in which case we use the buf structure for + * progressive reading and I18N conversions to the internal UTF-8 format. + */ + +typedef void (* xmlParserInputDeallocate)(xmlChar *); +typedef struct _xmlParserInput xmlParserInput; +typedef xmlParserInput *xmlParserInputPtr; +struct _xmlParserInput { + /* Input buffer */ + xmlParserInputBufferPtr buf; /* UTF-8 encoded buffer */ + + const char *filename; /* The file analyzed, if any */ + const char *directory; /* the directory/base of teh file */ + const xmlChar *base; /* Base of the array to parse */ + const xmlChar *cur; /* Current char being parsed */ + const xmlChar *end; /* end of the arry to parse */ + int length; /* length if known */ + int line; /* Current line */ + int col; /* Current column */ + int consumed; /* How many xmlChars already consumed */ + xmlParserInputDeallocate free; /* function to deallocate the base */ + const xmlChar *encoding; /* the encoding string for entity */ + const xmlChar *version; /* the version string for entity */ + int standalone; /* Was that entity marked standalone */ +}; + +/** + * the parser can be asked to collect Node informations, i.e. at what + * place in the file they were detected. + * NOTE: This is off by default and not very well tested. + */ +typedef struct _xmlParserNodeInfo xmlParserNodeInfo; +typedef xmlParserNodeInfo *xmlParserNodeInfoPtr; + +struct _xmlParserNodeInfo { + const struct _xmlNode* node; + /* Position & line # that text that created the node begins & ends on */ + unsigned long begin_pos; + unsigned long begin_line; + unsigned long end_pos; + unsigned long end_line; +}; + +typedef struct _xmlParserNodeInfoSeq xmlParserNodeInfoSeq; +typedef xmlParserNodeInfoSeq *xmlParserNodeInfoSeqPtr; +struct _xmlParserNodeInfoSeq { + unsigned long maximum; + unsigned long length; + xmlParserNodeInfo* buffer; +}; + +/* + * Validation state added for non-determinist content model + */ +typedef struct _xmlValidState xmlValidState; +typedef xmlValidState *xmlValidStatePtr; + +/** + * an xmlValidCtxt is used for error reporting when validating + */ + +typedef void (*xmlValidityErrorFunc) (void *ctx, const char *msg, ...); +typedef void (*xmlValidityWarningFunc) (void *ctx, const char *msg, ...); + +typedef struct _xmlValidCtxt xmlValidCtxt; +typedef xmlValidCtxt *xmlValidCtxtPtr; +struct _xmlValidCtxt { + void *userData; /* user specific data block */ + xmlValidityErrorFunc error; /* the callback in case of errors */ + xmlValidityWarningFunc warning; /* the callback in case of warning */ + + /* Node analysis stack used when validating within entities */ + xmlNodePtr node; /* Current parsed Node */ + int nodeNr; /* Depth of the parsing stack */ + int nodeMax; /* Max depth of the parsing stack */ + xmlNodePtr *nodeTab; /* array of nodes */ + + int finishDtd; /* finished validating the Dtd ? */ + xmlDocPtr doc; /* the document */ + int valid; /* temporary validity check result */ + + /* state state used for non-determinist content validation */ + xmlValidState *vstate; /* current state */ + int vstateNr; /* Depth of the validation stack */ + int vstateMax; /* Max depth of the validation stack */ + xmlValidState *vstateTab; /* array of validation states */ +}; + +typedef struct _xmlLink xmlLink; +typedef xmlLink *xmlLinkPtr; + +typedef struct _xmlList xmlList; +typedef xmlList *xmlListPtr; + +typedef void (*xmlListDeallocator) (xmlLinkPtr lk); +typedef int (*xmlListDataCompare) (const void *data0, const void *data1); +typedef int (*xmlListWalker) (const void *data, const void *user); + +/* + * ALl notation declarations are stored in a table + * there is one table per DTD + */ + +typedef struct _xmlHashTable xmlNotationTable; +typedef xmlNotationTable *xmlNotationTablePtr; + +/* + * ALl element declarations are stored in a table + * there is one table per DTD + */ + +typedef struct _xmlHashTable xmlElementTable; +typedef xmlElementTable *xmlElementTablePtr; + +/* + * ALl attribute declarations are stored in a table + * there is one table per DTD + */ + +typedef struct _xmlHashTable xmlAttributeTable; +typedef xmlAttributeTable *xmlAttributeTablePtr; + +/* + * ALl IDs attributes are stored in a table + * there is one table per document + */ + +typedef struct _xmlHashTable xmlIDTable; +typedef xmlIDTable *xmlIDTablePtr; + +/* + * ALl Refs attributes are stored in a table + * there is one table per document + */ + +typedef struct _xmlHashTable xmlRefTable; +typedef xmlRefTable *xmlRefTablePtr; + +/* helper */ +xmlChar * xmlSplitQName2 (const xmlChar *name, + xmlChar **prefix); + +/** + * The parser is now working also as a state based parser + * The recursive one use the stagte info for entities processing + */ +typedef enum { + XML_PARSER_EOF = -1, /* nothing is to be parsed */ + XML_PARSER_START = 0, /* nothing has been parsed */ + XML_PARSER_MISC, /* Misc* before int subset */ + XML_PARSER_PI, /* Whithin a processing instruction */ + XML_PARSER_DTD, /* within some DTD content */ + XML_PARSER_PROLOG, /* Misc* after internal subset */ + XML_PARSER_COMMENT, /* within a comment */ + XML_PARSER_START_TAG, /* within a start tag */ + XML_PARSER_CONTENT, /* within the content */ + XML_PARSER_CDATA_SECTION, /* within a CDATA section */ + XML_PARSER_END_TAG, /* within a closing tag */ + XML_PARSER_ENTITY_DECL, /* within an entity declaration */ + XML_PARSER_ENTITY_VALUE, /* within an entity value in a decl */ + XML_PARSER_ATTRIBUTE_VALUE, /* within an attribute value */ + XML_PARSER_SYSTEM_LITERAL, /* within a SYSTEM value */ + XML_PARSER_EPILOG, /* the Misc* after the last end tag */ + XML_PARSER_IGNORE /* within an IGNORED section */ +} xmlParserInputState; + +/** + * The parser context. + * NOTE This doesn't completely defines the parser state, the (current ?) + * design of the parser uses recursive function calls since this allow + * and easy mapping from the production rules of the specification + * to the actual code. The drawback is that the actual function call + * also reflect the parser state. However most of the parsing routines + * takes as the only argument the parser context pointer, so migrating + * to a state based parser for progressive parsing shouldn't be too hard. + */ +typedef struct _xmlParserCtxt xmlParserCtxt; +typedef xmlParserCtxt *xmlParserCtxtPtr; +struct _xmlParserCtxt { + struct _xmlSAXHandler *sax; /* The SAX handler */ + void *userData; /* For SAX interface only, used by DOM build */ + xmlDocPtr myDoc; /* the document being built */ + int wellFormed; /* is the document well formed */ + int replaceEntities; /* shall we replace entities ? */ + const xmlChar *version; /* the XML version string */ + const xmlChar *encoding; /* the declared encoding, if any */ + int standalone; /* standalone document */ + int html; /* an HTML(1)/Docbook(2) document */ + + /* Input stream stack */ + xmlParserInputPtr input; /* Current input stream */ + int inputNr; /* Number of current input streams */ + int inputMax; /* Max number of input streams */ + xmlParserInputPtr *inputTab; /* stack of inputs */ + + /* Node analysis stack only used for DOM building */ + xmlNodePtr node; /* Current parsed Node */ + int nodeNr; /* Depth of the parsing stack */ + int nodeMax; /* Max depth of the parsing stack */ + xmlNodePtr *nodeTab; /* array of nodes */ + + int record_info; /* Whether node info should be kept */ + xmlParserNodeInfoSeq node_seq; /* info about each node parsed */ + + int errNo; /* error code */ + + int hasExternalSubset; /* reference and external subset */ + int hasPErefs; /* the internal subset has PE refs */ + int external; /* are we parsing an external entity */ + + int valid; /* is the document valid */ + int validate; /* shall we try to validate ? */ + xmlValidCtxt vctxt; /* The validity context */ + + xmlParserInputState instate; /* current type of input */ + int token; /* next char look-ahead */ + + char *directory; /* the data directory */ + + /* Node name stack */ + xmlChar *name; /* Current parsed Node */ + int nameNr; /* Depth of the parsing stack */ + int nameMax; /* Max depth of the parsing stack */ + xmlChar * *nameTab; /* array of nodes */ + + long nbChars; /* number of xmlChar processed */ + long checkIndex; /* used by progressive parsing lookup */ + int keepBlanks; /* ugly but ... */ + int disableSAX; /* SAX callbacks are disabled */ + int inSubset; /* Parsing is in int 1/ext 2 subset */ + xmlChar * intSubName; /* name of subset */ + xmlChar * extSubURI; /* URI of external subset */ + xmlChar * extSubSystem; /* SYSTEM ID of external subset */ + + /* xml:space values */ + int * space; /* Should the parser preserve spaces */ + int spaceNr; /* Depth of the parsing stack */ + int spaceMax; /* Max depth of the parsing stack */ + int * spaceTab; /* array of space infos */ + + int depth; /* to prevent entity substitution loops */ + xmlParserInputPtr entity; /* used to check entities boundaries */ + int charset; /* encoding of the in-memory content + actually an xmlCharEncoding */ + int nodelen; /* Those two fields are there to */ + int nodemem; /* Speed up large node parsing */ + int pedantic; /* signal pedantic warnings */ + void *_private; /* For user data, libxml won't touch it */ + + int loadsubset; /* should the external subset be loaded */ +}; + +/** + * a SAX Locator. + */ +typedef struct _xmlSAXLocator xmlSAXLocator; +typedef xmlSAXLocator *xmlSAXLocatorPtr; +struct _xmlSAXLocator { + const xmlChar *(*getPublicId)(void *ctx); + const xmlChar *(*getSystemId)(void *ctx); + int (*getLineNumber)(void *ctx); + int (*getColumnNumber)(void *ctx); +}; + +/* + * The different valid entity types + */ +typedef enum { + XML_INTERNAL_GENERAL_ENTITY = 1, + XML_EXTERNAL_GENERAL_PARSED_ENTITY = 2, + XML_EXTERNAL_GENERAL_UNPARSED_ENTITY = 3, + XML_INTERNAL_PARAMETER_ENTITY = 4, + XML_EXTERNAL_PARAMETER_ENTITY = 5, + XML_INTERNAL_PREDEFINED_ENTITY = 6 +} xmlEntityType; + +/* + * An unit of storage for an entity, contains the string, the value + * and the linkind data needed for the linking in the hash table. + */ + +typedef struct _xmlEntity xmlEntity; +typedef xmlEntity *xmlEntityPtr; +struct _xmlEntity { +#ifndef XML_WITHOUT_CORBA + void *_private; /* for Corba, must be first ! */ +#endif + xmlElementType type; /* XML_ENTITY_DECL, must be second ! */ + const xmlChar *name; /* Attribute name */ + struct _xmlNode *children; /* NULL */ + struct _xmlNode *last; /* NULL */ + struct _xmlDtd *parent; /* -> DTD */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + xmlChar *orig; /* content without ref substitution */ + xmlChar *content; /* content or ndata if unparsed */ + int length; /* the content length */ + xmlEntityType etype; /* The entity type */ + const xmlChar *ExternalID; /* External identifier for PUBLIC */ + const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC Entity */ + + struct _xmlEntity *nexte; /* unused */ + const xmlChar *URI; /* the full URI as computed */ +}; + +/* + * ALl entities are stored in an hash table + * there is 2 separate hash tables for global and parmeter entities + */ + +typedef struct _xmlHashTable xmlEntitiesTable; +typedef xmlEntitiesTable *xmlEntitiesTablePtr; + +/* + * External functions : + */ + +/** + * a SAX handler is bunch of callbacks called by the parser when processing + * of the input generate data or structure informations. + */ + +typedef xmlParserInputPtr (*resolveEntitySAXFunc) (void *ctx, + const xmlChar *publicId, const xmlChar *systemId); +typedef void (*internalSubsetSAXFunc) (void *ctx, const xmlChar *name, + const xmlChar *ExternalID, const xmlChar *SystemID); +typedef void (*externalSubsetSAXFunc) (void *ctx, const xmlChar *name, + const xmlChar *ExternalID, const xmlChar *SystemID); +typedef xmlEntityPtr (*getEntitySAXFunc) (void *ctx, + const xmlChar *name); +typedef xmlEntityPtr (*getParameterEntitySAXFunc) (void *ctx, + const xmlChar *name); +typedef void (*entityDeclSAXFunc) (void *ctx, + const xmlChar *name, int type, const xmlChar *publicId, + const xmlChar *systemId, xmlChar *content); +typedef void (*notationDeclSAXFunc)(void *ctx, const xmlChar *name, + const xmlChar *publicId, const xmlChar *systemId); +typedef void (*attributeDeclSAXFunc)(void *ctx, const xmlChar *elem, + const xmlChar *name, int type, int def, + const xmlChar *defaultValue, xmlEnumerationPtr tree); +typedef void (*elementDeclSAXFunc)(void *ctx, const xmlChar *name, + int type, xmlElementContentPtr content); +typedef void (*unparsedEntityDeclSAXFunc)(void *ctx, + const xmlChar *name, const xmlChar *publicId, + const xmlChar *systemId, const xmlChar *notationName); +typedef void (*setDocumentLocatorSAXFunc) (void *ctx, + xmlSAXLocatorPtr loc); +typedef void (*startDocumentSAXFunc) (void *ctx); +typedef void (*endDocumentSAXFunc) (void *ctx); +typedef void (*startElementSAXFunc) (void *ctx, const xmlChar *name, + const xmlChar **atts); +typedef void (*endElementSAXFunc) (void *ctx, const xmlChar *name); +typedef void (*attributeSAXFunc) (void *ctx, const xmlChar *name, + const xmlChar *value); +typedef void (*referenceSAXFunc) (void *ctx, const xmlChar *name); +typedef void (*charactersSAXFunc) (void *ctx, const xmlChar *ch, + int len); +typedef void (*ignorableWhitespaceSAXFunc) (void *ctx, + const xmlChar *ch, int len); +typedef void (*processingInstructionSAXFunc) (void *ctx, + const xmlChar *target, const xmlChar *data); +typedef void (*commentSAXFunc) (void *ctx, const xmlChar *value); +typedef void (*cdataBlockSAXFunc) (void *ctx, const xmlChar *value, int len); +typedef void (*warningSAXFunc) (void *ctx, const char *msg, ...); +typedef void (*errorSAXFunc) (void *ctx, const char *msg, ...); +typedef void (*fatalErrorSAXFunc) (void *ctx, const char *msg, ...); +typedef int (*isStandaloneSAXFunc) (void *ctx); +typedef int (*hasInternalSubsetSAXFunc) (void *ctx); +typedef int (*hasExternalSubsetSAXFunc) (void *ctx); + +typedef struct _xmlSAXHandler xmlSAXHandler; +typedef xmlSAXHandler *xmlSAXHandlerPtr; +struct _xmlSAXHandler { + internalSubsetSAXFunc internalSubset; + isStandaloneSAXFunc isStandalone; + hasInternalSubsetSAXFunc hasInternalSubset; + hasExternalSubsetSAXFunc hasExternalSubset; + resolveEntitySAXFunc resolveEntity; + getEntitySAXFunc getEntity; + entityDeclSAXFunc entityDecl; + notationDeclSAXFunc notationDecl; + attributeDeclSAXFunc attributeDecl; + elementDeclSAXFunc elementDecl; + unparsedEntityDeclSAXFunc unparsedEntityDecl; + setDocumentLocatorSAXFunc setDocumentLocator; + startDocumentSAXFunc startDocument; + endDocumentSAXFunc endDocument; + startElementSAXFunc startElement; + endElementSAXFunc endElement; + referenceSAXFunc reference; + charactersSAXFunc characters; + ignorableWhitespaceSAXFunc ignorableWhitespace; + processingInstructionSAXFunc processingInstruction; + commentSAXFunc comment; + warningSAXFunc warning; + errorSAXFunc error; + fatalErrorSAXFunc fatalError; + getParameterEntitySAXFunc getParameterEntity; + cdataBlockSAXFunc cdataBlock; + externalSubsetSAXFunc externalSubset; +}; + +/** + * External entity loaders types + */ +typedef xmlParserInputPtr (*xmlExternalEntityLoader)(const char *URL, + const char *ID, + xmlParserCtxtPtr context); + +/* + * Compatibility naming layer with libxml1 + */ +#ifndef xmlChildrenNode +#define xmlChildrenNode children +#define xmlRootNode children +#endif + + +/*********************Xml routines and function pointers */ +#ifdef IN_XMLSTUB +#define XML_EXTERN +#else +#define XML_EXTERN extern +#endif + +typedef struct { + /* Functions */ + xmlDocPtr (*xmlParseFile)(const char *filename); + int (*xmlStrcmp)(const xmlChar *str1, const xmlChar *str2); + xmlParserCtxtPtr (*xmlCreatePushParserCtxt)(xmlSAXHandlerPtr, void *, const char *, + int, const char *); + int (*xmlParseChunk)(xmlParserCtxtPtr, const char *, int, int); + void (*xmlFreeParserCtxt)(xmlParserCtxtPtr); + xmlNodePtr (*xmlDocGetRootElement)(xmlDocPtr); + void (*xmlFreeDoc)(xmlDocPtr); + char *(*xmlNodeListGetString)(xmlDocPtr, xmlNodePtr, int); + char *(*xmlGetProp)(xmlNodePtr, char *); + int (*xmlKeepBlanksDefault)(int); + int (*xmlSubstituteEntitiesDefault)(int); + + /* Variables */ + int *xmlDoValidityCheckingDefaultValue; + +} XML_STUB; + +XML_EXTERN XML_STUB XmlStub; +XML_EXTERN int XmlStubInitialized; + +#ifdef WIN32 +/* We're in windows, use the windows filename */ +#define XML_LIBRARY "libxml2.dll" +#else +#define XML_LIBRARY "libxml2.so" +#endif + +/* + * This needs to be called before the library is used. It + * returns zero on success. Any non-zero return means that + * either dynamic libraries are not supported, or that libxml + * is not installed on the current system. (Or it's not in + * the LD path) + */ +int loadLibXML(); + + + |