From c8a5f498155ba7e89273a6882e29291fcd66dc8b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 4 May 2011 12:22:55 +0000 Subject: [PATCH] dead --- src/upnp/Makefile.am | 61 -- src/upnp/draft-cheshire-nat-pmp.txt | 1160 --------------------------- src/upnp/test_upnp.c | 110 --- src/upnp/upnp.c | 721 ----------------- src/upnp/upnp.h | 80 -- src/upnp/upnp_init.c | 208 ----- src/upnp/upnp_ip.c | 47 -- src/upnp/upnp_ip.h | 40 - src/upnp/upnp_util.c | 152 ---- src/upnp/upnp_util.h | 68 -- src/upnp/upnp_xmlnode.c | 487 ----------- src/upnp/upnp_xmlnode.h | 92 --- 12 files changed, 3226 deletions(-) delete mode 100644 src/upnp/Makefile.am delete mode 100644 src/upnp/draft-cheshire-nat-pmp.txt delete mode 100644 src/upnp/test_upnp.c delete mode 100644 src/upnp/upnp.c delete mode 100644 src/upnp/upnp.h delete mode 100644 src/upnp/upnp_init.c delete mode 100644 src/upnp/upnp_ip.c delete mode 100644 src/upnp/upnp_ip.h delete mode 100644 src/upnp/upnp_util.c delete mode 100644 src/upnp/upnp_util.h delete mode 100644 src/upnp/upnp_xmlnode.c delete mode 100644 src/upnp/upnp_xmlnode.h diff --git a/src/upnp/Makefile.am b/src/upnp/Makefile.am deleted file mode 100644 index 83ccf5b46..000000000 --- a/src/upnp/Makefile.am +++ /dev/null @@ -1,61 +0,0 @@ -INCLUDES = -I$(top_srcdir)/src/include - -if MINGW - WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -endif - -if USE_COVERAGE - AM_CFLAGS = -fprofile-arcs -ftest-coverage -endif - -lib_LTLIBRARIES = libgnunetupnp.la - -libgnunetupnp_la_SOURCES = \ - upnp.c upnp.h \ - upnp_ip.c upnp_ip.h \ - upnp_util.c upnp_util.h \ - upnp_xmlnode.c upnp_xmlnode.h -libgnunetupnp_la_CFLAGS = \ - -I$(top_scrdir)/include \ - @LIBCURL_CPPFLAGS@ @XML_CPPFLAGS@ -libgnunetupnp_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) @EXT_LIBS@ @XML_LIBS@ @LIBCURL@ -libgnunetupnp_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 0:0:0 - - -bin_PROGRAMS = \ - gnunet-upnp \ - gnunet-service-upnp - -gnunet_upnp_SOURCES = \ - gnunet-upnp.c -gnunet_upnp_LDADD = \ - $(top_builddir)/src/upnp/libgnunetupnp.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) - -gnunet_service_upnp_SOURCES = \ - gnunet-service-upnp.c -gnunet_service_upnp_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) - - -check_PROGRAMS = \ - test_upnp - -if !DISABLE_TEST_RUN -TESTS = $(check_PROGRAMS) -endif - -test_upnp_SOURCES = \ - test_upnp.c -test_upnp_LDADD = \ - $(top_builddir)/src/transport/libgnunetupnp.la \ - $(top_builddir)/src/util/libgnunetutil.la - - -# EXTRA_DIST = test_upnp_data.conf diff --git a/src/upnp/draft-cheshire-nat-pmp.txt b/src/upnp/draft-cheshire-nat-pmp.txt deleted file mode 100644 index 727b5fad7..000000000 --- a/src/upnp/draft-cheshire-nat-pmp.txt +++ /dev/null @@ -1,1160 +0,0 @@ -Document: draft-cheshire-nat-pmp-02.txt Stuart Cheshire -Internet-Draft Marc Krochmal -Category: Standards Track Apple Computer, Inc. -Expires 14th March 2007 Kiren Sekar - Sharpcast, Inc. - 14th September 2006 - - NAT Port Mapping Protocol (NAT-PMP) - - - -Status of this Memo - - By submitting this Internet-Draft, each author represents that any - applicable patent or other IPR claims of which he or she is aware - have been or will be disclosed, and any of which he or she becomes - aware will be disclosed, in accordance with Section 6 of BCP 79. - For the purposes of this document, the term "BCP 79" refers - exclusively to RFC 3979, "Intellectual Property Rights in IETF - Technology", published March 2005. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF), its areas, and its working groups. Note that - other groups may also distribute working documents as Internet- - Drafts. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - The list of current Internet-Drafts can be accessed at - http://www.ietf.org/1id-abstracts.html - - The list of Internet-Draft Shadow Directories can be accessed at - http://www.ietf.org/shadow.html - - -Abstract - - This document describes a protocol for automating the process of - creating Network Address Translation (NAT) port mappings. Included - in the protocol is a method for retrieving the public IP address of - a NAT gateway, thus allowing a client to make this public IP address - and port number known to peers that may wish to communicate with it. - This protocol is implemented in current Apple products including - Mac OS X, Bonjour for Windows, and AirPort wireless base stations. - - - - - - - - - - -Expires 14th March 2007 Cheshire, et al. [Page 1] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -1. Introduction - - Network Address Translation (NAT) is a method of sharing one public - internet address with a number of devices. This document is focused - on what "IP Network Address Translator (NAT) Terminology and - Considerations" [RFC 2663] calls "NAPTs" (Network Address/Port - Translators). A full description of NAT is beyond the scope of this - document. The following brief overview will cover the aspects - relevant to this port mapping protocol. For more information on - NAT, see "Traditional IP Network Address Translator" [RFC 3022]. - - NATs have one or more public IP addresses. A private network is set - up behind the NAT. Devices behind the NAT are assigned private - addresses and the private address of the NAT device is used as the - gateway. - - When a packet from any device behind the NAT is sent to an address on - the public internet, the packet first passes through the NAT box. The - NAT box looks at the source port and address. In some cases, a NAT - will also keep track of the destination port and address. The NAT - then creates a mapping from the private address and private port to a - public address and public port if a mapping does not already exist. - The NAT box replaces the private address and port number in the - packet with the public entries from the mapping and sends the packet - on to the next gateway. - - When a packet from any address on the internet is received on the - NAT's public side, the NAT will look up the destination port (public - port) in the list of mappings. If an entry is found, it will contain - the private address and port that the packet should be sent to. The - NAT gateway will then rewrite the destination address and port with - those from the mapping. The packet will then be forwarded to the new - destination addresses. If the packet did not match any mapping, the - packet will most likely be dropped. Various NATs implement different - strategies to handle this. The important thing to note is that if - there is no mapping, the NAT does not know which private address the - packet should be sent to. - - Mappings are usually created automatically as a result of observing - outbound traffic. There are a few exceptions. Some NATs may allow - manually-created permanent mappings that map a public port to a - specific private IP address and port. Such a mapping allows incoming - connections to the device with that private address. Some NATs also - implement a default mapping where any inbound traffic that does not - match a mapping will always be forwarded to a specific private - address. Both types of mappings are usually set up manually through - some configuration tool. - - Without these manually-created inbound port mappings, clients behind - the NAT would be unable to receive inbound connections, which - represents a loss of connectivity when compared to the original - - -Expires 14th March 2007 Cheshire, et al. [Page 2] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - - Internet architecture [ETEAISD]. For those who view this loss of - connectivity as a bad thing, NAT-PMP allows clients to operate much - more like a host directly connected to the unrestricted public - Internet, with an unrestricted public IP address. NAT-PMP allows - client hosts to communicate with the NAT gateway to request the - creation of inbound mappings on demand. Having created a NAT mapping - to allow inbound connections, the client can then record its public - IP address and public port number in a public registry (e.g. the - world-wide Domain Name System) or otherwise make it accessible to - peers that wish to communicate with it. - - -2. Conventions and Terminology Used in this Document - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in "Key words for use in - RFCs to Indicate Requirement Levels" [RFC 2119]. - - -3. Protocol and Packet Format - - NAT Port Mapping Protocol runs over UDP. Every packet starts with an - 8 bit version followed by an 8 bit operation code. - - This document specifies version 0 of the protocol. Any NAT-PMP - gateway implementing this version of the protocol, receiving a - packet with a version number other than 0, MUST return result code 1 - (Unsupported Version). - - Opcodes between 0 and 127 are client requests. Opcodes from 128 to - 255 are server responses. Responses always contain a 16 bit result - code in network byte order. A result code of zero indicates success. - Responses also contain a 32 bit unsigned integer corresponding to the - number of seconds since the NAT gateway was rebooted or since its - port mapping state was reset. - - This protocol SHOULD only be used when the client determines that - its primary IPv4 address is in one of the private IP address ranges - defined in "Address Allocation for Private Internets" [RFC 1918]. - This includes the address ranges 10/8, 172.16/12, and 192.168/16. - - Clients always send their Port Mapping Protocol requests to their - default gateway, as learned via DHCP [RFC 2131], or similar means. - This protocol is designed for small home networks, with a single - logical link (subnet) where the client's default gateway is also the - NAT translator for that network. For more complicated networks where - the NAT translator is some device other than the client's default - gateway, this protocol is not appropriate. - - - - -Expires 14th March 2007 Cheshire, et al. [Page 3] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -3.1 Requests and Responses - - NAT gateways are often low-cost devices, with limited memory and - CPU speed. For this reason, to avoid making excessive demands on - the NAT gateway, clients machines SHOULD NOT issue multiple requests - simultaneously in parallel. If a client needs to perform multiple - requests (e.g. on boot, wake from sleep, network connection, etc.) - it SHOULD queue them and issue them serially one at a time. Once the - NAT gateway responds to one request the client machine may issue the - next. In the case of a fast NAT gateway, the client may be able to - complete requests at a rate of hundreds per second. In the case of - a slow NAT gateway that takes perhaps half a second to respond to - a NAT-PMP request, the client SHOULD respect this and allow the - NAT gateway to operate at the pace it can manage, and not overload - it by issuing requests faster than the rate it's answering them. - - To determine the puclic IP address or request a port mapping, - a NAT-PMP client sends its request packet to port 5351 of its - configured gateway address, and waits 250ms for a response. If no - NAT-PMP response is received from the gateway after 250ms, the client - retransmits its request and waits 500ms. The client SHOULD repeat - this process with the interval between attempts doubling each time. - If, after sending its 9th attempt (and then waiting for 64 seconds), - the client has still received no response, then it SHOULD conclude - that this gateway does not support NAT Port Mapping Protocol and - MAY log an error message indicating this fact. In addition, if the - NAT-PMP client receives an "ICMP Port Unreachable" message from the - gateway for port 5351 then it can skip any remaining retransmissions - and conclude immediately that the gateway does not support NAT-PMP. - - As a performance optimization the client MAY record this information - and use it to suppress further attempts to use NAT-PMP, but the - client should not retain this information for too long. In - particular, any event that may indicate a potential change of gateway - or a change in gateway configuration (hardware link change - indication, change of gateway MAC address, acquisition of new DHCP - lease, receipt of NAT-PMP announcement packet from gateway, etc.) - should cause the client to discard its previous information regarding - the gateway's lack of NAT-PMP support, and send its next NAT-PMP - request packet normally. - - -3.2 Determining the Public Address - - To determine the public address, the client behind the NAT sends the - following UDP payload to port 5351 of the configured gateway address: - - 0 1 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Vers = 0 | OP = 0 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -Expires 14th March 2007 Cheshire, et al. [Page 4] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - - A compatible NAT gateway MUST generate a response with the following - format: - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Vers = 0 | OP = 128 + 0 | Result Code | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Seconds Since Start of Epoch | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Public IP Address (a.b.c.d) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - This response indicates that the NAT gateway implements this version - of the protocol and returns the public IP address of the NAT gateway. - If the result code is non-zero, the value of Public IP Address is - undefined (MUST be set to zero on transmission, and MUST be ignored - on reception). - - The NAT gateway MUST fill in the "Seconds Since Start of Epoch" field - with the time elapsed since its port mapping table was initialized on - startup or reset for any other reason (see Section 3.6 "Seconds Since - Start of Epoch"). - - Upon receiving the response packet, the client MUST check the source - IP address, and silently discard the packet if the address is not the - address of the gateway to which the request was sent. - - -3.2.1 Announcing Address Changes - - When the public IP address of the NAT changes, the NAT gateway MUST - send a gratuitous response to the link-local multicast address - 224.0.0.1, port 5351 with the packet format above to notify clients - of the new public IP address. To accommodate packet loss, the - NAT gateway SHOULD multicast 10 address change notifications. - The interval between the first two notifications SHOULD be 250ms, - and the interval between each subsequent notification SHOULD double. - - Upon receiving a gratuitous address change announcement packet, - the client MUST check the source IP address, and silently discard - the packet if the address is not the address of the client's - current configured gateway. This is to guard against inadvertent - misconfigurations where there may be more than one NAT gateway - active on the network. - - - - - - - - -Expires 14th March 2007 Cheshire, et al. [Page 5] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -3.3 Creating a Mapping - - To create a mapping, the client sends a UDP packet to port 5351 - of the gateway's private IP address with the following format: - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Vers = 0 | OP = x | Reserved (MUST be zero) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Private Port | Requested Public Port | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Requested Port Mapping Lifetime in Seconds | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Opcodes supported: - 1 - Map UDP - 2 - Map TCP - - The Reserved field MUST be set to zero on transmission and MUST - be ignored on reception. - - The Private Port is set to the local port on which the client is - listening. - - The Requested Public Port SHOULD usually be set to the same value as - the local Private Port, or zero if the client has no preference for - what port is assigned. However, the gateway is not obliged to assign - the port requested, and may choose not to, either for policy reasons - (e.g. port 80 is reserved and clients may not request it) or because - that port has already been assigned to some other client. Because - of this, some product developers have questioned the value of having - the Requested Public Port field at all. The reason is for failure - recovery. Most low-cost home NAT gateways do not record temporary - port mappings in persistent storage, so if the gateway crashes or is - rebooted, all the mappings are lost. A renewal packet is formatted - identically to an initial mapping request packet, except that for - renewals the client sets the Requested Public Port field to the - port the gateway actually assigned, rather than the port the client - originally wanted. When a freshly-rebooted NAT gateway receives a - renewal packet from a client, it appears to the gateway just like - an ordinary initial request for a port mapping, except that in this - case the Requested Public Port is likely to be one that the NAT - gateway *is* willing to allocate (it allocated it to this client - right before the reboot, so it should presumably be willing to - allocate it again). - - The RECOMMENDED Port Mapping Lifetime is 3600 seconds. - - - - - -Expires 14th March 2007 Cheshire, et al. [Page 6] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - - After sending the port mapping request, the client then waits for the - NAT gateway to respond. If after 250ms, the gateway doesn't respond, - the client SHOULD re-issue its request as described above in Section - 3.1 "Requests and Responses". - - The NAT gateway responds with the following packet format: - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Vers = 0 | OP = 128 + x | Result Code | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Seconds Since Start of Epoch | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Private Port | Mapped Public Port | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Port Mapping Lifetime in Seconds | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - The 'x' in the OP field MUST match what the client requested. Some - NAT gateways are incapable of creating a UDP port mapping without - also creating a corresponding TCP port mapping, and vice versa, and - these gateways MUST NOT implement NAT Port Mapping Protocol until - this deficiency is fixed. A NAT gateway which implements this - protocol MUST be able to create TCP-only and UDP-only port mappings. - - If a NAT gateway silently creates a pair of mappings for a client - that only requested one mapping, then it may expose that client to - receiving inbound UDP packets or inbound TCP connection requests - that it did not ask for and does not want. - - While a NAT gateway MUST NOT automatically create mappings for TCP - when the client requests UDP, and vice versa, the NAT gateway MUST - reserve the companion port so the same client can choose to map it - in the future. For example, if a client requests to map TCP port 80, - as long as the client maintains the lease for that TCP port mapping, - another client with a different IP address MUST NOT be able to - successfully acquire the mapping for UDP port 80. - - The client normally requests the public port matching the private - port. If that public port is not available, the NAT gateway MUST - return a public port that is available or return an error code if - no ports are available. - - The source address of the packet MUST be used for the private address - in the mapping. This protocol is not intended to facilitate one - device behind a NAT creating mappings for other devices. If there - are legacy devices that require inbound mappings, permanent mappings - can be created manually by the administrator, just as they are today. - - - - -Expires 14th March 2007 Cheshire, et al. [Page 7] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - - If a mapping already exists for a given private port on a given local - client (whether that mapping was created explicitly using NAT-PMP, - implicitly as a result of an outgoing TCP SYN packet, or manually by - a human administrator) and that client requests another mapping for - the same private port (possibly requesting a different public port) - then the mapping request should succeed, returning the already- - assigned public port. This is necessary to handle the case where - a client requests a mapping with requested public port X, and is - granted a mapping with actual public port Y, but the acknowledgement - packet gets lost. When the client retransmits its mapping request, - it should get back the same positive acknowledgement as was sent (and - lost) the first time. - - The NAT gateway SHOULD NOT accept mapping requests destined to the - NAT gateway's public IP address or received on its public network - interface. Only packets received on the private interface(s) with - a destination address matching the private address(es) of the NAT - gateway should be allowed. - - The NAT gateway MUST fill in the "Seconds Since Start of Epoch" field - with the time elapsed since its port mapping table was initialized on - startup or reset for any other reason (see Section 3.6 "Seconds Since - Start of Epoch"). - - The Port Mapping Lifetime is an unsigned integer in seconds. The NAT - gateway MAY reduce the lifetime from what the client requested. The - NAT gateway SHOULD NOT offer a lease lifetime greater than that - requested by the client. - - Upon receiving the response packet, the client MUST check the source - IP address, and silently discard the packet if the address is not the - address of the gateway to which the request was sent. - - The client SHOULD begin trying to renew the mapping halfway to expiry - time, like DHCP. The renewal packet should look exactly the same as - a request packet, except that the client SHOULD set the requested - public port to what the NAT gateway previously mapped, not what the - client originally requested. As described above, this enables the - gateway to automatically recover its mapping state after a crash or - reboot. - - -3.4 Destroying a Mapping - - A mapping may be destroyed in a variety of ways. If a client fails - to renew a mapping, then when its lifetime expires the mapping MUST - be automatically deleted. In the common case where the gateway - device is a combined DHCP server and NAT gateway, when a client's - DHCP address lease expires, the gateway device MAY automatically - delete any mappings belonging to that client. Otherwise a new client - being assigned the same IP address could receive unexpected inbound - - -Expires 14th March 2007 Cheshire, et al. [Page 8] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - - UDP packets or inbound TCP connection requests that it did not ask - for and does not want. - - A client MAY also send an explicit packet to request deletion of a - mapping that is no longer needed. A client requests explicit - deletion of a mapping by sending a message to the NAT gateway - requesting the mapping, with the Requested Lifetime in Seconds set - to 0. The requested public port MUST be set to zero by the client - on sending, and MUST be ignored by the gateway on reception. - - When a mapping is destroyed successfully as a result of the client - explicitly requesting the deletion, the NAT gateway MUST send a - response packet which is formatted as defined in section 3.3 - "Creating a Mapping". The response MUST contain a result code of 0, - the private port as indicated in the deletion request, a public port - of 0, and a lifetime of 0. The NAT gateway MUST respond to a request - to destroy a mapping that does not exist as if the request were - successful. This is because of the case where the acknowledgement is - lost, and the client retransmits its request to delete the mapping. - In this case the second request to delete the mapping MUST return the - same response packet as the first request. - - If the deletion request was unsuccessful, the response MUST contain a - non-zero result code and the requested mapping; the lifetime is - undefined (MUST be set to zero on transmission, and MUST be ignored - on reception). If the client attempts to delete a port mapping which - was manually assigned by some kind of configuration tool, the NAT - gateway MUST respond with a 'Not Authorized' error, result code 2. - - When a mapping is destroyed as a result of its lifetime expiring or - for any other reason, if the NAT gateway's internal state indicates - that there are still active TCP connections traversing that now- - defunct mapping, then the NAT gateway SHOULD send appropriately- - constructed TCP RST (reset) packets both to the local client and to - the remote peer on the Internet to terminate that TCP connection. - - A client can request the explicit deletion of all its UDP or TCP - mappings by sending the same deletion request to the NAT gateway - with public port, private port, and lifetime set to 0. A client MAY - choose to do this when it first acquires a new IP address in order to - protect itself from port mappings that were performed by a previous - owner of the IP address. After receiving such a deletion request, - the gateway MUST delete all its UDP or TCP port mappings (depending - on the opcode). The gateway responds to such a deletion request with - a response as described above, with the private port set to zero. If - the gateway is unable to delete a port mapping, for example, because - the mapping was manually configured by the administrator, the gateway - MUST still delete as many port mappings as possible, but respond with - a non-zero result code. The exact result code to return depends on - the cause of the failure. If the gateway is able to successfully - delete all port mappings as requested, it MUST respond with a result - code of 0. - -Expires 14th March 2007 Cheshire, et al. [Page 9] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -3.5 Result Codes - - Currently defined result codes: - 0 - Success - 1 - Unsupported Version - 2 - Not Authorized/Refused - (e.g. box supports mapping, but user has turned feature off) - 3 - Network Failure - (e.g. NAT box itself has not obtained a DHCP lease) - 4 - Out of resources - (NAT box cannot create any more mappings at this time) - 5 - Unsupported opcode - - If the result code is non-zero, the format of the packet following - the result code may be truncated. For example, if the client sends a - request to the server with an opcode of 17 and the server does not - recognize that opcode, the server SHOULD respond with a message where - the opcode is 17 + 128 and the result code is 5 (opcode not - supported). Since the server does not understand the format of - opcode 17, it may not know what to place after the result code. In - some cases, relevant data may follow the opcode to identify the - operation that failed. For example, a client may request a mapping - but that mapping may fail due to resource exhaustion. The server - SHOULD respond with the result code to indicate resource exhaustion - (4) followed by the requested port mapping so the client may identify - which operation failed. - - Clients MUST be able to properly handle result codes not defined in - this document. Undefined results codes MUST be treated as fatal - errors of the request. - - -3.6 Seconds Since Start of Epoch - - Every packet sent by the NAT gateway includes a "Seconds since start - of epoch" field (SSSOE). If the NAT gateway resets or loses the - state of its port mapping table, due to reboot, power failure, or any - other reason, it MUST reset its epoch time and begin counting SSSOE - from 0 again. Whenever a client receives any packet from the NAT - gateway, either gratuitously or in response to a client request, the - client computes its own conservative estimate of the expected SSSOE - value by taking the SSSOE value in the last packet it received from - the gateway and adding 7/8 (87.5%) of the time elapsed since that - packet was received. If the SSSOE in the newly received packet is - less than the client's conservative estimate by more than one second, - then the client concludes that the NAT gateway has undergone a reboot - or other loss of port mapping state, and the client MUST immediately - renew all its active port mapping leases as described in Section 3.7 - "Recreating Mappings On NAT Gateway Reboot". - - - - -Expires 14th March 2007 Cheshire, et al. [Page 10] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -3.7 Recreating Mappings On NAT Gateway Reboot - - The NAT gateway MAY store mappings in persistent storage so when it - is powered off or rebooted, it remembers the port mapping state of - the network. - - However, maintaining this state is not essential for correct - operation. When the NAT gateway powers on or clears its port mapping - state as the result of a configuration change, it MUST reset the - epoch time and re-announce its IP address as described in Section - 3.2.1 "Announcing Address Changes". Reception of this packet where - time has apparently gone backwards serves as a hint to clients - on the network that they SHOULD immediately send renewal packets - (to immediately recreate their mappings) instead of waiting until - the originally scheduled time for those renewals. Clients who miss - receiving those gateway announcement packets for any reason will - still renew their mappings at the originally scheduled time and cause - their mappings to be recreated; it will just take a little longer for - these clients. - - A mapping renewal packet is formatted identically to an original - mapping request; from the point of view of the client it is a - renewal of an existing mapping, but from the point of view of the - freshly-rebooted NAT gateway it appears as a new mapping request. - - This self-healing property of the protocol is very important. - - The remarkable reliability of the Internet as a whole derives - in large part from the fact that important state is held in the - endpoints, not in the network itself [ETEAISD]. Power-cycling an - Ethernet switch results only in a brief interruption in the flow - of packets; established TCP connections through that switch are not - broken, merely delayed for a few seconds. Indeed, an old Ethernet - switch can even be replaced with a new one, and as long as the cables - are transferred over reasonably quickly, after the upgrade all the - TCP connections that were previously going though the old switch will - be unbroken and now going through the new one. The same is true of - IP routers, wireless base stations, etc. The one exception is NAT - gateways. Because the port mapping state is required for the NAT - gateway to know where to forward inbound packets, loss of that state - breaks connectivity through the NAT gateway. By allowing clients to - detect when this loss of NAT gateway state has occurred, and recreate - it on demand, we turn hard state in the network into soft state, and - allow it to be recovered automatically when needed. - - Without this automatic recreation of soft state in the NAT gateway, - reliable long-term networking would not be achieved. As mentioned - above, the reliability of the Internet does not come from trying - to build a perfect network in which errors never happen, but from - accepting that in any sufficiently large system there will always be - some component somewhere that's failing, and designing mechanisms - - -Expires 14th March 2007 Cheshire, et al. [Page 11] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - - that can handle those failures and recover. To illustrate this point - with an example, consider the following scenario: Imagine a network - security camera that has a web interface and accepts incoming - connections from web browser clients. Imagine this network security - camera uses NAT-PMP or a similar protocol to set up an inbound - port mapping in the NAT gateway so that it can receive incoming - connections from clients the other side of the NAT gateway. - Now, this camera may well operate for weeks, months, or even years. - During that time it's possible that the NAT gateway could experience - a power failure or be rebooted. The user could upgrade the NAT - gateway's firmware, or even replace the entire NAT gateway device - with a newer model. The general point is that if the camera operates - for a long enough period of time, some kind of disruption to the NAT - gateway becomes inevitable. The question is not whether the NAT - gateway will lose its port mappings, but when, and how often. - If the network camera and devices like it on the network can detect - when the NAT gateway has lost its port mappings, and recreate them - automatically, then these disruptions are self-correcting and - invisible to the end user. If, on the other hand, the disruptions are - not self-correcting, and after a NAT gateway reboot the user has to - manually reset or reboot all the other devices on the network too, - then these disruptions are *very* visible to the end user. This - aspect of the design is what makes the difference between a protocol - that keeps on working indefinitely over a time scale of months or - years, and a protocol that works in brief testing, but in the real - world is continually failing and requiring manual intervention to get - it going again. - - When a client renews its port mappings as the result of receiving - a packet where the "Seconds since start of epoch" field (SSSOE) - indicates that a reboot or similar loss of state has occurred, - the client MUST first delay by a random amount of time selected - with uniform random distribution in the range 0 to 5 seconds, and - then send its first port mapping request. After that request is - acknowledged by the gateway, the client may then send its second - request, and so on, as rapidly as the gateway allows. The requests - SHOULD be issued serially, one at a time; the client SHOULD NOT issue - multiple requests simultaneously in parallel. - - The discussion in this section focusses on recreating inbound port - mappings after loss of NAT gateway state, because that is the more - serious problem. Losing port mappings for outgoing connections - destroys those currently active connections, but does not prevent - clients from establishing new outgoing connections. In contrast, - losing inbound port mappings not only destroys all existing inbound - connections, but also prevents the reception of any new inbound - connections until the port mapping is recreated. Accordingly, - we consider recovery of inbound port mappings the more important - priority. However, clients that want outgoing connections to survive - a NAT gateway reboot can also achieve that using NAT-PMP. After - initiating an outbound TCP connection (which will cause the NAT - - -Expires 14th March 2007 Cheshire, et al. [Page 12] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - - gateway to establish an implicit port mapping) the client should send - the NAT gateway a port mapping request for the source port of its TCP - connection, which will cause the NAT gateway to send a response - giving the public port it allocated for that mapping. The client can - then store this information, and use later to recreate the mapping - if it determines that the NAT gateway has lost its mapping state. - - -3.8 NAT Gateways with NAT Function Disabled - - Note that *only* devices currently acting in the role of NAT gateway - should participate in NAT-PMP protocol exchanges with clients. - A network device that is capable of NAT (and NAT-PMP), but is - currently configured not to perform that function, (e.g. it is - acting as a traditional IP router, forwarding packets without - modifying them), MUST NOT respond to NAT-PMP requests from clients, - or send spontaneous NAT-PMP address-change announcements. - - In particular, a network device not currently acting in the role of - NAT gateway should not even respond to NAT-PMP requests by returning - an error code such as "2 - Not Authorized/Refused", since to do so - is misleading to clients -- it suggests that NAT port mapping is - necessary on this network for the client to successfully receive - inbound connections, but is not available because the administrator - has chosen to disable that functionality. - - Clients should also be careful to avoid making unfounded assumptions, - such as the assumption that if the client has an IPv4 address in - one of the RFC 1918 private IP address ranges then that means - NAT necessarily must be in use. Net 10/8 has enough addresses - to build a private network with millions of hosts and thousands - of interconnected subnets, all without any use of NAT. Many - organizations have built such private networks that benefit from - using standard TCP/IP technology, but by choice do not connect - to the public Internet. The purpose of NAT-PMP is to mitigate some - of the damage caused by NAT. It would be an ironic and unwanted - side-effect of this protocol if it were to lead well-meaning but - misguided developers to create products that refuse to work on a - private network *unless* they can find a NAT gateway to talk to. - Consequently, a client finding that NAT-PMP is not available on its - network should not give up, but should proceed on the assumption - that the network may be a traditional routed IP network, with no - address translation being used. This assumption may not always be - true, but it is better than the alternative of falsely assuming - the worst and not even trying to use normal (non-NAT) IP networking. - - If a network device not currently acting in the role of NAT gateway - receives UDP packets addressed to port 5351, it SHOULD respond - immediately with an "ICMP Port Unreachable" message to tell the - client that it needn't continue with timeouts and retransmissions, - and it should assume that NAT-PMP is not available and not needed - on this network. - -Expires 14th March 2007 Cheshire, et al. [Page 13] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -4. UNSAF Considerations - - The document "IAB Considerations for UNSAF Across NAT" [RFC 3424] - covers a number of issues when working with NATs. RFC 3424 outlines - some requirements for any document that attempts to work around - problems associated with NATs. This section addresses those - requirements. - - -4.1 Scope - - This protocol addresses the needs of TCP and UDP transport peers that - are separated from the public internet by exactly one NAT. Such - peers must have access to some form of directory server for - registering the public IP address and port at which they can be - reached. - - -4.2 Transition Plan - - Any client making use of this protocol SHOULD implement IPv6 support. - If a client supports IPv6 and is running on a device with a global - IPv6 address, that IPv6 address SHOULD be preferred to the IPv4 - public address using this NAT mapping protocol. In case other - clients do not have IPv6 connectivity, both the IPv4 and IPv6 - addresses SHOULD be registered with whatever form of directory server - is used. Preference SHOULD be given to IPv6 addresses when - available. By implementing support for IPv6 and using this protocol - for IPv4, vendors can ship products today that will work under both - scenarios. As IPv6 is more widely deployed, clients of this protocol - following these recommendations will transparently make use of IPv6. - - -4.3 Failure Cases - - Aside from NATs that do not implement this protocol, there are a - number of situations where this protocol may not work. - - -4.3.1 NAT Behind NAT - - Some people's primary IP address, assigned by their ISP, may itself - be a NAT address. In addition, some people may have a public IP - address, but may then double NAT themselves, perhaps by choice or - perhaps by accident. Although it might be possible in principle for - one NAT gateway to recursively request a mapping from the next one, - this document does not advocate that and does not try to prescribe - how it would be done. - - It would be a lot of work to implement nested NAT port mapping - correctly, and there are a number of reasons why the end result might - - -Expires 14th March 2007 Cheshire, et al. [Page 14] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - - not be as useful as we might hope. Consider the case of an ISP that - offers each of its customers only a single NAT address. This ISP - could instead have chosen to provide each customer with a single - public IP address, or, if the ISP insists on running NAT, it could - have chosen to allow each customer a reasonable number of addresses, - enough for each customer device to have its own NAT address directly - from the ISP. If instead this ISP chooses to allow each customer - just one and only one NAT address, forcing said customer to run - nested NAT in order to use more than one device, it seems unlikely - that such an ISP would be so obliging as to provide a NAT service - that supports NAT Port Mapping Protocol. Supposing that such an ISP - did wish to offer its customers NAT service with NAT-PMP so as to - give them the ability to receive inbound connections, this ISP could - easily choose to allow each client to request a reasonable number of - DHCP addresses from that gateway. Remember that Net 10/8 [RFC 1918] - allows for over 16 million addresses, so NAT addresses are not in any - way in short supply. A single NAT gateway with 16 million available - addresses is likely to run out of packet forwarding capacity before - it runs out of private addresses to hand out. In this way the ISP - could offer single-level NAT with NAT-PMP, obviating the need to - support nested NAT-PMP. In addition, an ISP that is motivated to - provide their customers with unhindered access to the Internet by - allowing incoming as well as outgoing connections has better ways - to offer this service. Such an ISP could offer its customers real - public IP addresses instead of NAT addresses, or could even choose - to offer its customers full IPv6 connectivity, where no mapping or - translation is required at all. - - -4.3.2 NATs with Multiple Public IP Addresses - - If a NAT maps private addresses to multiple public addresses, - then it SHOULD pick one of those addresses as the one it will - support for inbound connections, and for the purposes of this - protocol it SHOULD act as if that address were its only address. - - -4.3.3 NATs and Routed Private Networks - - In some cases, a large network may be subnetted. Some sites - may install a NAT gateway and subnet the private network. - Such subnetting breaks this protocol because the router address - is not necessarily the address of the device performing NAT. - - Addressing this problem is not a high priority. Any site with the - resources to set up such a configuration should have the resources to - add manual mappings or attain a range of globally unique addresses. - - Not all NATs will support this protocol. In the case where a client - is run behind a NAT that does not support this protocol, the software - relying on the functionality of this protocol may be unusable. - - -Expires 14th March 2007 Cheshire, et al. [Page 15] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -4.3.4 Communication Between Hosts Behind the Same NAT - - NAT gateways supporting NAT-PMP should also implement "hairpin - translation". Hairpin translation means supporting communication - between two local clients being served by the same NAT gateway. - - Suppose device A is listening on private address and port 10.0.0.2:80 - for incoming connections. Using NAT-PMP, device A has obtained a - mapping to public address and port x.x.x.x:80, and has recorded this - public address and port in a public directory of some kind. For - example, it could have created a DNS SRV record containing this - information, and recorded it, using DNS Dynamic Update [RFC 3007], in - a publicly accessible DNS server. Suppose then that device B, behind - the same NAT gateway as device A, but unknowing or uncaring of this - fact, retrieves device A's DNS SRV record and attempts to open a TCP - connection to x.x.x.x:80. The outgoing packets addressed to this - public Internet address will be sent to the NAT gateway for - translation and forwarding. Having translated the source address and - port number on the outgoing packet, the NAT gateway needs to be smart - enough to recognize that the destination address is in fact itself, - and then feed this packet back into its packet reception engine, to - perform the destination port mapping lookup to translate and forward - this packet to device A at address and port 10.0.0.2:80. - -4.3.5 Non UDP/TCP Transport Traffic - - Any communication over transport protocols other than TCP and UDP - will not be served by this protocol. Examples are Generic Routing - Encapsulation (GRE), Authentication Header (AH) and Encapsulating - Security Payload (ESP). - -4.4 Long Term Solution - - As IPv6 is deployed, clients of this protocol supporting IPv6 will be - able to bypass this protocol and the NAT when communicating with - other IPv6 devices. In order to ensure this transition, any client - implementing this protocol SHOULD also implement IPv6 and use this - solution only when IPv6 is not available to both peers. - -4.5 Existing Deployed NATs - - Existing deployed NATs will not support this protocol. This protocol - will only work with NATs that are upgraded to support it. - - - - - - - - - - -Expires 14th March 2007 Cheshire, et al. [Page 16] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -5. Security Considerations - - As discussed in section 3.2 "Determining the Public Address", only - clients on the private side of the NAT may create port mappings, and - only on behalf of themselves. By using IP address spoofing, it's - possible for one client to delete the port mappings of another - client. It's also possible for one client to create port mappings on - behalf of another client. The best way to deal with this - vulnerability is to use IPSec [RFC 2401]. - - Since allowing incoming connections is often a policy decision, any - NAT gateway implementing this protocol SHOULD have an administrative - mechanism to disable it. - - Some people view the property that NATs block inbound connections as - a security benefit which is undermined by this protocol. The authors - of this document have a different point of view. In the days before - NAT, all hosts had unique public IP addresses, and had unhindered - ability to communicate with any other host on the Internet. When NAT - came along it broke this unhindered connectivity, relegating many - hosts to second-class status, unable to receive inbound connections. - This protocol goes some way to undo some of that damage. The purpose - of a NAT gateway should be to allow several hosts to share a single - address, not to simultaneously impede those host's ability to - communicate freely. Security is most properly provided by end-to-end - cryptographic security, and/or by explicit firewall functionality, as - appropriate. Blocking of certain connections should occur only as a - result of explicit and intentional firewall policy, not as an - accidental side-effect of some other technology. - - -6. IANA Considerations - - No IANA services are required by this document. - - -7. Acknowledgments - - The concepts described in this document have been explored, developed - and implemented with help from Bob Bradley, Josh Graessley, Rob - Newberry, Roger Pantos, John Saxton, and James Woodyatt. - - -8. Deployment History - - NAT-PMP client software first became available to the public - through Apple's Darwin Open Source code in August 2004. - NAT-PMP implementations began shipping to end users in large - volumes (i.e. millions) with the launch of Mac OS X 10.4 Tiger - and Bonjour for Windows 1.0 in April 2005. - - - -Expires 14th March 2007 Cheshire, et al. [Page 17] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - - The NAT-PMP client in Mac OS X 10.4 Tiger and Bonjour for Windows - exists as part of the mDNSResponder system service. When a client - advertises a service using Wide Area Bonjour [DNS-SD], and the - machine is behind a NAT-PMP-capable NAT gateway, then if the machine - is so configured, the mDNSResponder system service automatically uses - NAT-PMP to set up an inbound port mapping, and then records the - public IP address and port in the global DNS. Existing client - software using the existing Bonjour programming APIs [Bonjour] - gets this functionality automatically. The logic is that if client - software publishes its information into the global DNS via Wide Area - Bonjour service advertising, then it's reasonable to infer an - expectation that this information should be usable by the peers - retrieving it. Generally speaking, recording a private IP address - like 10.0.0.2 in the public DNS is completely pointless because that - address is not reachable from clients on the other side of the NAT - gateway. In the case of a home user with a single computer directly - connected to their Cable or DSL modem, with a single global IPv4 - address and no NAT gateway (a surprisingly common configuration), - publishing that IP address into the global DNS is useful because that - IP address is reachable. In contrast, a home user using a NAT gateway - to share a single global IPv4 address between several computers loses - this ability to receive inbound connections easily. This breaks many - peer-to-peer collaborative applications, like the multi-user text - editor SubEthaEdit [SEE]. Automatically creating the necessary - inbound port mappings helps remedy this unintended side-effect of - NAT. - - The server side of the NAT-PMP protocol is implemented in Apple's - "AirPort Extreme" and "AirPort Express" wireless base stations. - - -9. Copyright Notice - - Copyright (C) The Internet Society (2006). - - This document is subject to the rights, licenses and restrictions - contained in BCP 78, and except as set forth therein, the authors - retain all their rights. For the purposes of this document, - the term "BCP 78" refers exclusively to RFC 3978, "IETF Rights - in Contributions", published March 2005. - - This document and the information contained herein are provided on - an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE - REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE - INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF - THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED - WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - - - - -Expires 14th March 2007 Cheshire, et al. [Page 18] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -10. Normative References - - [RFC 1918] Y. Rekhter et.al., "Address Allocation for Private - Internets", RFC 1918, February 1996. - - [RFC 2119] RFC 2119 - Key words for use in RFCs to Indicate - Requirement Levels - - -11. Informative References - - [Bonjour] Apple "Bonjour" - - [ETEAISD] J. Saltzer, D. Reed and D. Clark: "End-to-end arguments in - system design", ACM Trans. Comp. Sys., 2(4):277-88, Nov. - 1984 - - [DNS-SD] Cheshire, S., and M. Krochmal, "DNS-Based Service - Discovery", Internet-Draft (work in progress), - draft-cheshire-dnsext-dns-sd-04.txt, August 2006. - - [mDNS] Cheshire, S., and M. Krochmal, "Multicast DNS", - Internet-Draft (work in progress), - draft-cheshire-dnsext-multicastdns-06.txt, August 2006. - - [RFC 2131] R. Droms, "Dynamic Host Configuration Protocol", RFC 2131, - March 1997. - - [RFC 2401] Atkinson, R. and S. Kent, "Security Architecture for the - Internet Protocol", RFC 2401, November 1998. - - [RFC 2663] Srisuresh, P. and M. Holdrege, "IP Network Address - Translator (NAT) Terminology and Considerations", RFC - 2663, August 1999. - - [RFC 3007] Wellington, B., "Simple Secure Domain Name System - (DNS) Dynamic Update", RFC 3007, November 2000. - - [SEE] - - [RFC 3022] RFC 3022 - Network Address Translator - - [RFC 3424] RFC 3424 - IAB Considerations for UNilateral Self-Address - Fixing (UNSAF) Across Network Address Translation - - - - - - - - - -Expires 14th March 2007 Cheshire, et al. [Page 19] - -Internet Draft NAT Port Mapping Protocol 14th September 2006 - - -12. Authors' Addresses - - Stuart Cheshire - Apple Computer, Inc. - 1 Infinite Loop - Cupertino - California 95014 - USA - - Phone: +1 408 974 3207 - EMail: rfc [at] stuartcheshire [dot] org - - - Marc Krochmal - Apple Computer, Inc. - 1 Infinite Loop - Cupertino - California 95014 - USA - - Phone: +1 408 974 4368 - EMail: marc [at] apple [dot] com - - - Kiren Sekar - Sharpcast, Inc. - 250 Cambridge Ave, Suite 101 - Palo Alto - California 94306 - USA - - Phone: +1 650 323 1960 - EMail: ksekar [at] sharpcast [dot] com - - - - - - - - - - - - - - - - - - - - -Expires 14th March 2007 Cheshire, et al. [Page 20] diff --git a/src/upnp/test_upnp.c b/src/upnp/test_upnp.c deleted file mode 100644 index f20028dc9..000000000 --- a/src/upnp/test_upnp.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2006 Christian Grothoff (and other contributing authors) - - GNUnet 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 3, or (at your - option) any later version. - - GNUnet 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 GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ -/** - * @file upnp/test_upnp.c - * @brief Testcase for UPnP - * @author Christian Grothoff - */ - -#include "gnunet_util.h" -#include "gnunet_upnp_service.h" -#include "gnunet_core.h" -#include "platform.h" - - - -int -main (int argc, const char *argv[]) -{ - static GNUNET_CoreAPIForPlugins capi; - struct GNUNET_GE_Context *ectx; - struct GNUNET_GC_Configuration *cfg; - struct in_addr addr; - int i; - GNUNET_UPnP_ServiceAPI *upnp; - struct GNUNET_PluginHandle *plug; - GNUNET_ServicePluginInitializationMethod init; - GNUNET_ServicePluginShutdownMethod done; - char ntop_buf[INET_ADDRSTRLEN]; - - ectx = GNUNET_GE_create_context_stderr (GNUNET_NO, - GNUNET_GE_WARNING | GNUNET_GE_ERROR - | GNUNET_GE_FATAL | GNUNET_GE_USER | - GNUNET_GE_ADMIN | - GNUNET_GE_DEVELOPER | - GNUNET_GE_IMMEDIATE | - GNUNET_GE_BULK); - GNUNET_GE_setDefaultContext (ectx); - cfg = GNUNET_GC_create (); - GNUNET_GE_ASSERT (ectx, cfg != NULL); - GNUNET_os_init (ectx); - capi.ectx = ectx; - capi.cfg = cfg; - plug = GNUNET_plugin_load (ectx, "libgnunet", "module_upnp"); - if (plug == NULL) - { - GNUNET_GC_free (cfg); - GNUNET_GE_free_context (ectx); - return 1; - } - init = GNUNET_plugin_resolve_function (plug, "provide_", GNUNET_YES); - if (init == NULL) - { - GNUNET_plugin_unload (plug); - GNUNET_GC_free (cfg); - GNUNET_GE_free_context (ectx); - return 1; - } - upnp = init (&capi); - if (upnp == NULL) - { - GNUNET_plugin_unload (plug); - GNUNET_GC_free (cfg); - GNUNET_GE_free_context (ectx); - return 1; - } - for (i = 0; i < 10; i++) - { - if (GNUNET_shutdown_test () != GNUNET_NO) - break; - if (GNUNET_OK == upnp->get_ip (2086, "TCP", &addr)) - { - printf ("UPnP returned external IP %s\n", - inet_ntop (AF_INET, &addr, ntop_buf, INET_ADDRSTRLEN)); - } - else - { - /* we cannot be sure that there is a UPnP-capable - NAT-box out there, so test should not fail - just because of this! */ - printf ("No UPnP response (yet).\n"); - } - GNUNET_thread_sleep (2 * GNUNET_CRON_SECONDS); - } - done = GNUNET_plugin_resolve_function (plug, "release_", GNUNET_YES); - if (done != NULL) - done (); - GNUNET_plugin_unload (plug); - GNUNET_GC_free (cfg); - GNUNET_GE_free_context (ectx); - return 0; -} - -/* end of upnptest.c */ diff --git a/src/upnp/upnp.c b/src/upnp/upnp.c deleted file mode 100644 index 5e15b12b4..000000000 --- a/src/upnp/upnp.c +++ /dev/null @@ -1,721 +0,0 @@ -/** - * @file upnp/upnp.c UPnP Implementation - * @ingroup core - * - * gaim - * - * Gaim is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 "platform.h" -#include "upnp_xmlnode.h" -#include "upnp_util.h" -#include "upnp.h" - -#include - -#define TRUE GNUNET_YES -#define FALSE GNUNET_NO -#define g_return_if_fail(a) if(!(a)) return; -#define g_return_val_if_fail(a, val) if(!(a)) return (val); - -#define HTTP_OK "200 OK" -#define NUM_UDP_ATTEMPTS 2 -#define HTTPMU_HOST_ADDRESS "239.255.255.250" -#define HTTPMU_HOST_PORT 1900 -#define SEARCH_REQUEST_DEVICE "urn:schemas-upnp-org:service:%s" -#define SEARCH_REQUEST_STRING \ - "M-SEARCH * HTTP/1.1\r\n" \ - "MX: 2\r\n" \ - "HOST: 239.255.255.250:1900\r\n" \ - "MAN: \"ssdp:discover\"\r\n" \ - "ST: urn:schemas-upnp-org:service:%s\r\n" \ - "\r\n" -#define WAN_IP_CONN_SERVICE "WANIPConnection:1" -#define WAN_PPP_CONN_SERVICE "WANPPPConnection:1" -#define HTTP_POST_SOAP_HEADER \ - "SOAPACTION: \"urn:schemas-upnp-org:service:%s#%s\"" -#define HTTP_POST_SIZE_HEADER "CONTENT-LENGTH: %u" -#define SOAP_ACTION \ - "\r\n" \ - "\r\n" \ - "\r\n" \ - "\r\n" \ - "%s" \ - "\r\n" \ - "\r\n" \ - "" -#define PORT_MAPPING_LEASE_TIME "0" -#define PORT_MAPPING_DESCRIPTION "GNUNET_UPNP_PORT_FORWARD" -#define ADD_PORT_MAPPING_PARAMS \ - "\r\n" \ - "%i\r\n" \ - "%s\r\n" \ - "%i\r\n" \ - "%s\r\n" \ - "1\r\n" \ - "" \ - PORT_MAPPING_DESCRIPTION \ - "\r\n" \ - "" \ - PORT_MAPPING_LEASE_TIME \ - "\r\n" -#define DELETE_PORT_MAPPING_PARAMS \ - "\r\n" \ - "%i\r\n" \ - "%s\r\n" - -typedef enum -{ - GAIM_UPNP_STATUS_UNDISCOVERED = -1, - GAIM_UPNP_STATUS_UNABLE_TO_DISCOVER, - GAIM_UPNP_STATUS_DISCOVERING, - GAIM_UPNP_STATUS_DISCOVERED -} GaimUPnPStatus; - -typedef struct -{ - GaimUPnPStatus status; - char *control_url; - const char *service_type; - char publicip[16]; -} GaimUPnPControlInfo; - -typedef struct -{ - const char *service_type; - char *full_url; - char *buf; - unsigned int buf_len; - struct GNUNET_NETWORK_Handle *sock; -} UPnPDiscoveryData; - -static GaimUPnPControlInfo control_info = { - GAIM_UPNP_STATUS_UNDISCOVERED, - NULL, - NULL, - "", -}; - -/** - * This is the signature used for functions that act as a callback - * to CURL. - */ -typedef size_t (*GaimUtilFetchUrlCallback) (void *url_data, - size_t size, - size_t nmemb, void *user_data); - - - -static char * -g_strstr_len (const char *haystack, int haystack_len, const char *needle) -{ - int i; - - g_return_val_if_fail (haystack != NULL, NULL); - g_return_val_if_fail (needle != NULL, NULL); - - if (haystack_len < 0) - return strstr (haystack, needle); - else - { - const char *p = haystack; - int needle_len = strlen (needle); - const char *end = haystack + haystack_len - needle_len; - - if (needle_len == 0) - return (char *) haystack; - - while (*p && p <= end) - { - for (i = 0; i < needle_len; i++) - if (p[i] != needle[i]) - goto next; - - return (char *) p; - - next: - p++; - } - } - - return NULL; -} - -static int -gaim_upnp_compare_device (const xmlnode * device, const char *deviceType) -{ - xmlnode *deviceTypeNode = xmlnode_get_child (device, "deviceType"); - char *tmp; - int ret; - - if (deviceTypeNode == NULL) - return FALSE; - tmp = xmlnode_get_data (deviceTypeNode); - ret = !strcasecmp (tmp, deviceType); - GNUNET_free (tmp); - return ret; -} - -static int -gaim_upnp_compare_service (const xmlnode * service, const char *serviceType) -{ - xmlnode *serviceTypeNode; - char *tmp; - int ret; - - if (service == NULL) - return FALSE; - serviceTypeNode = xmlnode_get_child (service, "serviceType"); - if (serviceTypeNode == NULL) - return FALSE; - tmp = xmlnode_get_data (serviceTypeNode); - ret = !strcasecmp (tmp, serviceType); - GNUNET_free (tmp); - return ret; -} - -static char * -gaim_upnp_parse_description_response (const char *httpResponse, - size_t len, - const char *httpURL, - const char *serviceType) -{ - char *xmlRoot, *baseURL, *controlURL, *service; - xmlnode *xmlRootNode, *serviceTypeNode, *controlURLNode, *baseURLNode; - char *tmp; - - /* find the root of the xml document */ - xmlRoot = g_strstr_len (httpResponse, len, " 0) - CURL_EASY_SETOPT (curl, CURLOPT_PROXY, proxy); - CURL_EASY_SETOPT (curl, CURLOPT_BUFFERSIZE, 1024); /* a bit more than one HELLO */ - CURL_EASY_SETOPT (curl, CURLOPT_CONNECTTIMEOUT, 150L); - /* NOTE: use of CONNECTTIMEOUT without also - setting NOSIGNAL results in really weird - crashes on my system! */ - CURL_EASY_SETOPT (curl, CURLOPT_NOSIGNAL, 1); - return GNUNET_OK; -} - -static int -gaim_upnp_generate_action_message_and_send (const char *proxy, - const char *actionName, - const char *actionParams, - GaimUtilFetchUrlCallback cb, - void *cb_data) -{ - CURL *curl; - int ret; - char *soapHeader; - char *sizeHeader; - char *soapMessage; - struct curl_slist *headers = NULL; - - GNUNET_assert (cb != NULL); - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return GNUNET_SYSERR; - /* set the soap message */ - soapMessage = g_strdup_printf (SOAP_ACTION, - actionName, - control_info.service_type, - actionParams, actionName); - soapHeader = g_strdup_printf (HTTP_POST_SOAP_HEADER, - control_info.service_type, actionName); - sizeHeader = g_strdup_printf (HTTP_POST_SIZE_HEADER, strlen (soapMessage)); - curl = curl_easy_init (); - setup_curl (proxy, curl); - CURL_EASY_SETOPT (curl, CURLOPT_URL, control_info.control_url); - CURL_EASY_SETOPT (curl, CURLOPT_WRITEFUNCTION, cb); - CURL_EASY_SETOPT (curl, CURLOPT_WRITEDATA, cb_data); - CURL_EASY_SETOPT (curl, CURLOPT_POST, 1); - headers = curl_slist_append (headers, - "CONTENT-TYPE: text/xml ; charset=\"utf-8\""); - headers = curl_slist_append (headers, soapHeader); - headers = curl_slist_append (headers, sizeHeader); - CURL_EASY_SETOPT (curl, CURLOPT_HTTPHEADER, headers); - CURL_EASY_SETOPT (curl, CURLOPT_POSTFIELDS, soapMessage); - CURL_EASY_SETOPT (curl, CURLOPT_POSTFIELDSIZE, strlen (soapMessage)); - CURL_EASY_SETOPT (curl, CURLOPT_MAXREDIRS, 1L); - CURL_EASY_SETOPT (curl, CURLOPT_CONNECTTIMEOUT, 1L); - CURL_EASY_SETOPT (curl, CURLOPT_TIMEOUT, 2L); - /* NOTE: use of CONNECTTIMEOUT without also - setting NOSIGNAL results in really weird - crashes on my system! */ - CURL_EASY_SETOPT (curl, CURLOPT_NOSIGNAL, 1); - if (ret == CURLE_OK) - ret = curl_easy_perform (curl); -#if 0 - if (ret != CURLE_OK) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - _ - ("%s failed for url `%s' and post-data `%s' at %s:%d: `%s'\n"), - "curl_easy_perform", control_info.control_url, soapMessage, - __FILE__, __LINE__, curl_easy_strerror (ret)); -#endif - curl_slist_free_all (headers); - curl_easy_cleanup (curl); - curl_global_cleanup (); - GNUNET_free (sizeHeader); - GNUNET_free (soapMessage); - GNUNET_free (soapHeader); - if (ret != CURLE_OK) - return GNUNET_SYSERR; - return GNUNET_OK; -} - - -static size_t -looked_up_public_ip_cb (void *url_data, - size_t size, size_t nmemb, void *user_data) -{ - UPnPDiscoveryData *dd = user_data; - size_t len = size * nmemb; - const char *temp; - const char *temp2; - - if (len + dd->buf_len > 1024 * 1024 * 4) - return 0; /* refuse to process - too big! */ - GNUNET_array_grow (dd->buf, dd->buf_len, dd->buf_len + len); - memcpy (&dd->buf[dd->buf_len - len], url_data, len); - if (dd->buf_len == 0) - return len; - /* extract the ip, or see if there is an error */ - if ((temp = g_strstr_len (dd->buf, - dd->buf_len, "buf_len - (temp - dd->buf), ">"))) - return len; - if (!(temp2 = g_strstr_len (temp, dd->buf_len - (temp - dd->buf), "<"))) - return len; - memset (control_info.publicip, 0, sizeof (control_info.publicip)); - if (temp2 - temp >= sizeof (control_info.publicip)) - temp2 = temp + sizeof (control_info.publicip) - 1; - memcpy (control_info.publicip, temp + 1, temp2 - (temp + 1)); - GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, - _("upnp: NAT Returned IP: %s\n"), control_info.publicip); - return len; -} - - -static size_t -ignore_response (void *url_data, size_t size, size_t nmemb, void *user_data) -{ - return size * nmemb; -} - -/** - * Process downloaded bits of service description. - */ -static size_t -upnp_parse_description_cb (void *httpResponse, - size_t size, size_t nmemb, void *user_data) -{ - UPnPDiscoveryData *dd = user_data; - size_t len = size * nmemb; - char *control_url = NULL; - - if (len + dd->buf_len > 1024 * 1024 * 4) - return len; /* refuse to process - too big! */ - GNUNET_array_grow (dd->buf, dd->buf_len, dd->buf_len + len); - memcpy (&dd->buf[dd->buf_len - len], httpResponse, len); - if (dd->buf_len > 0) - control_url = gaim_upnp_parse_description_response (dd->buf, - dd->buf_len, - dd->full_url, - dd->service_type); - control_info.status = control_url ? GAIM_UPNP_STATUS_DISCOVERED - : GAIM_UPNP_STATUS_UNABLE_TO_DISCOVER; - GNUNET_free_non_null (control_info.control_url); - control_info.control_url = control_url; - control_info.service_type = dd->service_type; - return len; -} - -static int -gaim_upnp_parse_description (char *proxy, UPnPDiscoveryData * dd) -{ - CURL *curl; - int ret; - - if (0 != curl_global_init (CURL_GLOBAL_WIN32)) - return GNUNET_SYSERR; - curl = curl_easy_init (); - setup_curl (proxy, curl); - ret = CURLE_OK; - CURL_EASY_SETOPT (curl, CURLOPT_URL, dd->full_url); - CURL_EASY_SETOPT (curl, CURLOPT_WRITEFUNCTION, &upnp_parse_description_cb); - CURL_EASY_SETOPT (curl, CURLOPT_WRITEDATA, dd); - CURL_EASY_SETOPT (curl, CURLOPT_MAXREDIRS, 1L); - CURL_EASY_SETOPT (curl, CURLOPT_CONNECTTIMEOUT, 1L); - CURL_EASY_SETOPT (curl, CURLOPT_TIMEOUT, 2L); - - /* NOTE: use of CONNECTTIMEOUT without also - setting NOSIGNAL results in really weird - crashes on my system! */ - CURL_EASY_SETOPT (curl, CURLOPT_NOSIGNAL, 1); - ret = curl_easy_perform (curl); - if (ret != CURLE_OK) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - _("%s failed at %s:%d: `%s'\n"), - "curl_easy_perform", __FILE__, __LINE__, - curl_easy_strerror (ret)); - curl_easy_cleanup (curl); - curl_global_cleanup (); - if (control_info.control_url == NULL) - return GNUNET_SYSERR; - return GNUNET_OK; -} - -int -gaim_upnp_discover (struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_NETWORK_Handle *sock) -{ - char *proxy; - socklen_t avail; - struct sockaddr_in server; - int retry_count; - char *sendMessage; - size_t totalSize; - int sentSuccess; - char buf[65536]; - int buf_len; - const char *startDescURL; - const char *endDescURL; - int ret; - UPnPDiscoveryData dd; - struct sockaddr *sa; - - memset (&dd, 0, sizeof (UPnPDiscoveryData)); - if (control_info.status == GAIM_UPNP_STATUS_DISCOVERING) - return GNUNET_NO; - dd.sock = sock; - memset (&server, 0, sizeof (struct sockaddr_in)); - server.sin_family = AF_INET; - avail = sizeof (struct sockaddr_in); - sa = (struct sockaddr *) &server; - if (GNUNET_OK != - GNUNET_get_ip_from_hostname (HTTPMU_HOST_ADDRESS, AF_INET, &sa, &avail)) - { - return GNUNET_SYSERR; - } - server.sin_port = htons (HTTPMU_HOST_PORT); - control_info.status = GAIM_UPNP_STATUS_DISCOVERING; - - /* because we are sending over UDP, if there is a failure - we should retry the send NUM_UDP_ATTEMPTS times. Also, - try different requests for WANIPConnection and WANPPPConnection */ - for (retry_count = 0; retry_count < NUM_UDP_ATTEMPTS; retry_count++) - { - sentSuccess = FALSE; - if ((retry_count % 2) == 0) - dd.service_type = WAN_IP_CONN_SERVICE; - else - dd.service_type = WAN_PPP_CONN_SERVICE; - sendMessage = g_strdup_printf (SEARCH_REQUEST_STRING, dd.service_type); - totalSize = strlen (sendMessage); - do - { - if (SENDTO (dd.sock, - sendMessage, - totalSize, - 0, - (struct sockaddr *) &server, - sizeof (struct sockaddr_in)) == totalSize) - { - sentSuccess = TRUE; - break; - } - } - while (((errno == EINTR) || (errno == EAGAIN)) && - (GNUNET_shutdown_test () == GNUNET_NO)); - GNUNET_free (sendMessage); - if (sentSuccess) - break; - } - if (sentSuccess == FALSE) - return GNUNET_SYSERR; - - /* try to read response */ - do - { - buf_len = GNUNET_IO_recv (dd.sock, buf, sizeof (buf) - 1, 0); - if (buf_len > 0) - { - buf[buf_len] = '\0'; - break; - } - else if (errno != EINTR) - { - continue; - } - } - while ((errno == EINTR) && (GNUNET_shutdown_test () == GNUNET_NO)); - - /* parse the response, and see if it was a success */ - if (g_strstr_len (buf, buf_len, HTTP_OK) == NULL) - return GNUNET_SYSERR; - if ((startDescURL = g_strstr_len (buf, buf_len, "http://")) == NULL) - return GNUNET_SYSERR; - - endDescURL = g_strstr_len (startDescURL, - buf_len - (startDescURL - buf), "\r"); - if (endDescURL == NULL) - endDescURL = g_strstr_len (startDescURL, - buf_len - (startDescURL - buf), "\n"); - if (endDescURL == NULL) - return GNUNET_SYSERR; - if (endDescURL == startDescURL) - return GNUNET_SYSERR; - dd.full_url = GNUNET_strdup (startDescURL); - dd.full_url[endDescURL - startDescURL] = '\0'; - proxy = NULL; - GNUNET_CONFIGURATION_get_value_string (cfg, - "GNUNETD", "HTTP-PROXY", &proxy); - ret = gaim_upnp_parse_description (proxy, &dd); - GNUNET_free (dd.full_url); - GNUNET_array_grow (dd.buf, dd.buf_len, 0); - if (ret == GNUNET_OK) - { - ret = gaim_upnp_generate_action_message_and_send (proxy, - "GetExternalIPAddress", - "", - looked_up_public_ip_cb, - &dd); - GNUNET_array_grow (dd.buf, dd.buf_len, 0); - } - GNUNET_free (proxy); - return ret; -} - -const char * -gaim_upnp_get_public_ip () -{ - if ((control_info.status == GAIM_UPNP_STATUS_DISCOVERED) - && (strlen (control_info.publicip) > 0)) - return control_info.publicip; - return NULL; -} - -int -gaim_upnp_change_port_mapping (struct GNUNET_CONFIGURATION_Handle *cfg, - int do_add, - unsigned short portmap, const char *protocol) -{ - const char *action_name; - char *action_params; - char *internal_ip; - char *proxy; - int ret; - - if (control_info.status != GAIM_UPNP_STATUS_DISCOVERED) - return GNUNET_NO; - if (do_add) - { - internal_ip = GNUNET_upnp_get_internal_ip (cfg); - if (internal_ip == NULL) - { - gaim_debug_error ("upnp", - "gaim_upnp_set_port_mapping(): couldn't get local ip\n"); - return GNUNET_NO; - } - action_name = "AddPortMapping"; - action_params = g_strdup_printf (ADD_PORT_MAPPING_PARAMS, - portmap, - protocol, portmap, internal_ip); - GNUNET_free (internal_ip); - } - else - { - action_name = "DeletePortMapping"; - action_params = g_strdup_printf (DELETE_PORT_MAPPING_PARAMS, - portmap, protocol); - } - proxy = NULL; - GNUNET_CONFIGURATION_get_value_string (cfg, - "GNUNETD", "HTTP-PROXY", &proxy); - ret = - gaim_upnp_generate_action_message_and_send (proxy, action_name, - action_params, - &ignore_response, NULL); - - GNUNET_free (action_params); - GNUNET_free (proxy); - return ret; -} - -/* end of upnp.c */ diff --git a/src/upnp/upnp.h b/src/upnp/upnp.h deleted file mode 100644 index 537f9f3e7..000000000 --- a/src/upnp/upnp.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file upnp/upnp.h Universal Plug N Play API - * @ingroup core - * - * gaim - * - * Gaim is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 - */ - -#ifndef _GAIM_UPNP_H_ -#define _GAIM_UPNP_H_ - -#include -#include -#include "gnunet_util_lib.h" - -#ifdef __cplusplus -extern "C" -{ -#if 0 /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - -/** - * Sends a discovery request to search for a UPnP enabled IGD that - * contains the WANIPConnection service that will allow us to receive the - * public IP address of the IGD, and control it for forwarding ports. - * The result will be cached for further use. - */ -int gaim_upnp_discover (struct GNUNET_CONFIGURATION_Handle *cfg, int sock); - -/** - * Gets the IP address from a UPnP enabled IGD that sits on the local - * network, so when getting the network IP, instead of returning the - * local network IP, the public IP is retrieved. This is a cached value from - * the time of the UPnP discovery. - * - * @return The IP address of the network, or NULL if something went wrong - */ -const char *gaim_upnp_get_public_ip (void); - -/** - * Maps Ports in a UPnP enabled IGD that sits on the local network to - * this gaim client. Essentially, this function takes care of the port - * forwarding so things like file transfers can work behind NAT firewalls - * - * @param cfg configuration to use - * @param do_add TRUE/GNUNET_YES to add, FALSE/GNUNET_NO to remove - * @param portmap The port to map to this client - * @param protocol The protocol to map, either "TCP" or "UDP" - */ -int gaim_upnp_change_port_mapping (struct GNUNET_CONFIGURATION_Handle *cfg, - int do_add, - uint16_t portmap, const char *protocol); - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - -#endif /* _GAIM_UPNP_H_ */ diff --git a/src/upnp/upnp_init.c b/src/upnp/upnp_init.c deleted file mode 100644 index 2c612e159..000000000 --- a/src/upnp/upnp_init.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - This file is part of GNUnet - (C) 2006 Christian Grothoff (and other contributing authors) - - GNUnet 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 3, or (at your - option) any later version. - - GNUnet 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 GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file upnp/upnp_init.c - * @brief API for UPnP access - * @author Christian Grothoff - */ - -#include "platform.h" -#include "gnunet_util.h" -#include "upnp.h" -#include "gnunet_upnp_service.h" -#include "gnunet_core.h" - -static struct GNUNET_GE_Context *ectx; - -static struct GNUNET_GC_Configuration *cfg; - -static struct GNUNET_CronManager *cron; - -static struct GNUNET_Mutex *lock; - -typedef struct -{ - unsigned short port; - const char *proto; -} PMap; - -static PMap *maps; - -static unsigned int maps_size; - -static struct GNUNET_ThreadHandle *discovery; - -static struct GNUNET_NETWORK_Handle *discovery_socket; - -/** - * Obtain the public/external IP address. - * - * @return GNUNET_SYSERR on error, GNUNET_OK on success - */ -static int -gnunet_upnp_get_public_ip (struct in_addr *address) -{ - const char *ip; - socklen_t socklen; - struct sockaddr *sa; - struct sockaddr_in s4; - int ret; - - ip = gaim_upnp_get_public_ip (); - if (ip == NULL) - return GNUNET_SYSERR; - socklen = sizeof (struct sockaddr_in); - sa = (struct sockaddr *) &s4; - ret = GNUNET_get_ip_from_hostname (NULL, ip, AF_INET, &sa, &socklen); - if (ret == GNUNET_OK) - *address = s4.sin_addr; - return ret; -} - -static void -kill_discovery () -{ - void *unused; - - if (discovery != NULL) - { - GNUNET_IO_shutdown (discovery_socket, SHUT_RDWR); - GNUNET_IO_close (&discovery_socket); - GNUNET_thread_join (discovery, &unused); - discovery = NULL; - } -} - -static void * -discover_thread () -{ - gaim_upnp_discover (ectx, cfg, discovery_socket); - return NULL; -} - -/** - * Periodically try to (re)discover UPnP access points. - */ -static void -discover (void *unused) -{ - kill_discovery (); - discovery_socket = GNUNET_IO_socket (PF_INET, SOCK_DGRAM, 0); - if (NULL == discovery_socket) - return; - discovery = GNUNET_thread_create (&discover_thread, NULL, 1024 * 128); -} - -/** - * Periodically repeat our requests for port mappings. - */ -static void -portmap (void *unused) -{ - unsigned int i; - - GNUNET_mutex_lock (lock); - for (i = 0; i < maps_size; i++) - gaim_upnp_change_port_mapping (ectx, - cfg, GNUNET_NO, maps[i].port, - maps[i].proto); - GNUNET_mutex_unlock (lock); -} - - -/** - * Get the external IP address for the local machine. - * - * @return GNUNET_SYSERR on error, GNUNET_OK on success - */ -static int -gnunet_upnp_get_ip (unsigned short port, - const char *protocol, struct in_addr *address) -{ - unsigned int i; - - GNUNET_mutex_lock (lock); - for (i = 0; i < maps_size; i++) - if ((0 == strcmp (maps[i].proto, protocol)) && (maps[i].port == port)) - break; - if (i == maps_size) - { - /* new entry! */ - GNUNET_array_grow (maps, maps_size, maps_size + 1); - maps[i].proto = protocol; - maps[i].port = port; - gaim_upnp_change_port_mapping (ectx, cfg, GNUNET_YES, port, protocol); - } - GNUNET_mutex_unlock (lock); - return gnunet_upnp_get_public_ip (address); -} - - -/** - * Get the external IP address for the local machine. - */ -GNUNET_UPnP_ServiceAPI * -provide_module_upnp (GNUNET_CoreAPIForPlugins * capi) -{ - static GNUNET_UPnP_ServiceAPI api; - - ectx = capi->ectx; - cfg = capi->cfg; - cron = GNUNET_cron_create (ectx); - lock = GNUNET_mutex_create (GNUNET_NO); - GNUNET_cron_start (cron); - GNUNET_cron_add_job (cron, &discover, 0, 5 * GNUNET_CRON_MINUTES, NULL); - GNUNET_cron_add_job (cron, &portmap, 150 * GNUNET_CRON_SECONDS, - 5 * GNUNET_CRON_MINUTES, NULL); - api.get_ip = gnunet_upnp_get_ip; - return &api; -} - -/** - * Shutdown UPNP. - */ -int -release_module_upnp () -{ - unsigned int i; - - if (cron == NULL) - return GNUNET_SYSERR; /* not loaded! */ - for (i = 0; i < maps_size; i++) - gaim_upnp_change_port_mapping (ectx, - cfg, GNUNET_NO, maps[i].port, - maps[i].proto); - GNUNET_cron_stop (cron); - GNUNET_cron_del_job (cron, &discover, 5 * GNUNET_CRON_MINUTES, NULL); - GNUNET_cron_del_job (cron, &portmap, 5 * GNUNET_CRON_MINUTES, NULL); - GNUNET_cron_destroy (cron); - kill_discovery (); - cron = NULL; - GNUNET_mutex_destroy (lock); - lock = NULL; - GNUNET_array_grow (maps, maps_size, 0); - ectx = NULL; - cfg = NULL; - return GNUNET_OK; -} - - -/* end of init.c */ diff --git a/src/upnp/upnp_ip.c b/src/upnp/upnp_ip.c deleted file mode 100644 index 928f02b49..000000000 --- a/src/upnp/upnp_ip.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2006, 2007 Christian Grothoff (and other contributing authors) - - GNUnet 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 3, or (at your - option) any later version. - - GNUnet 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 GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file upnp/upnp_ip.c - * @brief code to determine the IP of the local machine - * - * @author Christian Grothoff - */ - -#include -#include "platform.h" -#include "gnunet_util.h" -#include "ip.h" - -/** - * Get the IP address for the local machine. - * @return NULL on error - */ -char * -GNUNET_upnp_get_internal_ip (struct GNUNET_GC_Configuration *cfg, - struct GNUNET_GE_Context *ectx) -{ - struct in_addr address; - - return GNUNET_get_local_ip (cfg, ectx, &address); -} - - -/* end of ip.c */ diff --git a/src/upnp/upnp_ip.h b/src/upnp/upnp_ip.h deleted file mode 100644 index 1b80d328a..000000000 --- a/src/upnp/upnp_ip.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2001, 2002, 2003, 2004, 2005 Christian Grothoff (and other contributing authors) - - GNUnet 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 3, or (at your - option) any later version. - - GNUnet 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 GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file upnp/upnp_ip.h - * @brief - * - * @author Christian Grothoff - */ - -#ifndef IP_H -#define IP_H - - -/** - * Get the IP address for the local machine. - * @return NULL on error - */ -char *GNUNET_upnp_get_internal_ip (struct GNUNET_GC_Configuration *cfg, - struct GNUNET_GE_Context *ectx); - - -#endif diff --git a/src/upnp/upnp_util.c b/src/upnp/upnp_util.c deleted file mode 100644 index a080b6470..000000000 --- a/src/upnp/upnp_util.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * @file upnp_util.cUtility Functions - * @ingroup core - * - * Gaim is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 "platform.h" -#include "util.h" -#include "gnunet_util.h" - -/* Returns a NULL-terminated string after unescaping an entity - * (eg. &, < & etc.) starting at s. Returns NULL on failure.*/ -static char * -detect_entity (const char *text, int *length) -{ - const char *pln; - int len; - int pound; - char b[7]; - char *buf; - - if (!text || *text != '&') - return NULL; - -#define IS_ENTITY(s) (!strncasecmp(text, s, (len = sizeof(s) - 1))) - - if (IS_ENTITY ("&")) - pln = "&"; - else if (IS_ENTITY ("<")) - pln = "<"; - else if (IS_ENTITY (">")) - pln = ">"; - else if (IS_ENTITY (" ")) - pln = " "; - else if (IS_ENTITY ("©")) - pln = "\302\251"; /* or use g_unichar_to_utf8(0xa9); */ - else if (IS_ENTITY (""")) - pln = "\""; - else if (IS_ENTITY ("®")) - pln = "\302\256"; /* or use g_unichar_to_utf8(0xae); */ - else if (IS_ENTITY ("'")) - pln = "\'"; - else if (*(text + 1) == '#' && (sscanf (text, "&#%u;", £) == 1) && - pound != 0 && *(text + 3 + (int) log10 (pound)) == ';') - { - buf = GNUNET_convert_string_to_utf8 (NULL, - (const char *) £, - 2, "UNICODE"); - if (strlen (buf) > 6) - buf[6] = '\0'; - strcpy (b, buf); - pln = b; - GNUNET_free (buf); - len = 2; - while (isdigit ((int) text[len])) - len++; - if (text[len] == ';') - len++; - } - else - return NULL; - - if (length) - *length = len; - return GNUNET_strdup (pln); -} - -char * -g_strdup_printf (const char *fmt, ...) -{ - size_t size; - char *buf; - va_list va; - - va_start (va, fmt); - size = VSNPRINTF (NULL, 0, fmt, va) + 1; - va_end (va); - buf = GNUNET_malloc (size); - va_start (va, fmt); - VSNPRINTF (buf, size, fmt, va); - va_end (va); - return buf; -} - -char * -gaim_unescape_html (const char *html) -{ - if (html != NULL) - { - const char *c = html; - char *ret = GNUNET_strdup (""); - char *app; - while (*c) - { - int len; - char *ent; - - if ((ent = detect_entity (c, &len)) != NULL) - { - app = g_strdup_printf ("%s%s", ret, ent); - GNUNET_free (ret); - ret = app; - c += len; - GNUNET_free (ent); - } - else if (!strncmp (c, "
", 4)) - { - app = g_strdup_printf ("%s%s", ret, "\n"); - GNUNET_free (ret); - ret = app; - c += 4; - } - else - { - app = g_strdup_printf ("%s%c", ret, *c); - GNUNET_free (ret); - ret = app; - c++; - } - } - return ret; - } - return NULL; -} - - -int -gaim_str_has_prefix (const char *s, const char *p) -{ - if ((s == NULL) || (p == NULL)) - return 0; - return !strncmp (s, p, strlen (p)); -} - -/* end of util.c */ diff --git a/src/upnp/upnp_util.h b/src/upnp/upnp_util.h deleted file mode 100644 index 1c7555b09..000000000 --- a/src/upnp/upnp_util.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file upnp/upnp_util.h Utility Functions - * @ingroup core - * - * gaim - * - * Gaim is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 - * - * @todo Rename the functions so that they live somewhere in the gaim - * namespace. - */ -#ifndef _GAIM_UTIL_H_ -#define _GAIM_UTIL_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * Unescapes HTML entities to their literal characters. - * For example "&" is replaced by '&' and so on. - * Actually only "&", """, "<" and ">" are currently - * supported. - * - * @param html The string in which to unescape any HTML entities - * - * @return the text with HTML entities literalized - */ - char *gaim_unescape_html (const char *html); - -/** - * Compares two strings to see if the first contains the second as - * a proper prefix. - * - * @param s The string to check. - * @param p The prefix in question. - * - * @return TRUE if p is a prefix of s, otherwise FALSE. - */ - int gaim_str_has_prefix (const char *s, const char *p); - - char *g_strdup_printf (const char *fmt, ...); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/upnp/upnp_xmlnode.c b/src/upnp/upnp_xmlnode.c deleted file mode 100644 index 46e66e11c..000000000 --- a/src/upnp/upnp_xmlnode.c +++ /dev/null @@ -1,487 +0,0 @@ -/** - * @file upnp/upnp_xmlnode.c XML DOM functions - * - * gaim - * - * Gaim is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 - */ - -/* A lot of this code at least resembles the code in libxode, but since - * libxode uses memory pools that we simply have no need for, I decided to - * write my own stuff. Also, re-writing this lets me be as lightweight - * as I want to be. Thank you libxode for giving me a good starting point */ - -#include "platform.h" - -#include "util.h" -#include "gnunet_util.h" -#include "xmlnode.h" - -#include -#include - - -#ifdef _WIN32 -# define NEWLINE_S "\r\n" -#else -# define NEWLINE_S "\n" -#endif - -#define TRUE GNUNET_YES -#define FALSE GNUNET_NO - -#define g_return_if_fail(a) if(!(a)) return; -#define g_return_val_if_fail(a, val) if(!(a)) return (val); - -/** - * The valid types for an xmlnode - */ -typedef enum _XMLNodeType -{ - XMLNODE_TYPE_TAG, /**< Just a tag */ - XMLNODE_TYPE_ATTRIB, /**< Has attributes */ - XMLNODE_TYPE_DATA /**< Has data */ -} XMLNodeType; - -typedef struct -{ - xmlnode *current; - xmlnode **nodes; - unsigned int pos; - unsigned int size; -} XMLNodePool; - -struct _xmlnode -{ - char *name; /**< The name of the node. */ - char *xmlns; /**< The namespace of the node */ - XMLNodeType type; /**< The type of the node. */ - char *data; /**< The data for the node. */ - size_t data_sz; /**< The size of the data. */ - struct _xmlnode *parent; /**< The parent node or @c NULL.*/ - struct _xmlnode *child; /**< The child node or @c NULL.*/ - struct _xmlnode *lastchild; /**< The last child node or @c NULL.*/ - struct _xmlnode *next; /**< The next node or @c NULL. */ - XMLNodePool *pool; - int free_pool; /* set to GNUNET_YES for the root node, which must free the pool */ -}; - - -static void * -g_memdup (const void *data, size_t s) -{ - void *ret; - - ret = GNUNET_malloc (s); - memcpy (ret, data, s); - return ret; -} - -static char * -g_string_append_len (char *prefix, const void *data, size_t s) -{ - char *ret; - - ret = g_strdup_printf ("%s%.*s", prefix, s, data); - GNUNET_free (prefix); - return ret; -} - -static xmlnode * -new_node (const char *name, XMLNodeType type, void *user_data) -{ - xmlnode *node = GNUNET_malloc (sizeof (xmlnode)); - - node->name = name == NULL ? NULL : GNUNET_strdup (name); - node->type = type; - node->pool = user_data; - if (node->pool->size == node->pool->pos) - GNUNET_array_grow (node->pool->nodes, node->pool->size, - node->pool->size * 2 + 64); - node->pool->nodes[node->pool->pos++] = node; - node->free_pool = 0; - return node; -} - -static xmlnode * -xmlnode_new (const char *name, void *user_data) -{ - g_return_val_if_fail (name != NULL, NULL); - return new_node (name, XMLNODE_TYPE_TAG, user_data); -} - -static void -xmlnode_insert_child (xmlnode * parent, xmlnode * child) -{ - g_return_if_fail (parent != NULL); - g_return_if_fail (child != NULL); - - child->parent = parent; - if (parent->lastchild) - parent->lastchild->next = child; - else - parent->child = child; - parent->lastchild = child; -} - -static xmlnode * -xmlnode_new_child (xmlnode * parent, const char *name, void *user_data) -{ - xmlnode *node; - - g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - node = new_node (name, XMLNODE_TYPE_TAG, user_data); - xmlnode_insert_child (parent, node); - return node; -} - -static void -xmlnode_insert_data (xmlnode * node, - const char *data, int size, void *user_data) -{ - xmlnode *child; - size_t real_size; - - g_return_if_fail (node != NULL); - g_return_if_fail (data != NULL); - g_return_if_fail (size != 0); - real_size = size == -1 ? strlen (data) : size; - child = new_node (NULL, XMLNODE_TYPE_DATA, user_data); - child->data = g_memdup (data, real_size); - child->data_sz = real_size; - xmlnode_insert_child (node, child); -} - -static void -xmlnode_remove_attrib (xmlnode * node, const char *attr) -{ - xmlnode *attr_node, *sibling = NULL; - - g_return_if_fail (node != NULL); - g_return_if_fail (attr != NULL); - - for (attr_node = node->child; attr_node; attr_node = attr_node->next) - { - if (attr_node->type == XMLNODE_TYPE_ATTRIB && - !strcmp (attr_node->name, attr)) - { - if (node->child == attr_node) - { - node->child = attr_node->next; - } - else - { - sibling->next = attr_node->next; - } - if (node->lastchild == attr_node) - { - node->lastchild = sibling; - } - xmlnode_free (attr_node); - return; - } - sibling = attr_node; - } -} - -static void -xmlnode_set_attrib (xmlnode * node, - const char *attr, const char *value, void *user_data) -{ - xmlnode *attrib_node; - - g_return_if_fail (node != NULL); - g_return_if_fail (attr != NULL); - g_return_if_fail (value != NULL); - xmlnode_remove_attrib (node, attr); - attrib_node = new_node (attr, XMLNODE_TYPE_ATTRIB, user_data); - attrib_node->data = GNUNET_strdup (value); - xmlnode_insert_child (node, attrib_node); -} - -static void -xmlnode_set_namespace (xmlnode * node, const char *xmlns) -{ - g_return_if_fail (node != NULL); - GNUNET_free_non_null (node->xmlns); - node->xmlns = GNUNET_strdup (xmlns); -} - -static const char * -xmlnode_get_namespace (xmlnode * node) -{ - g_return_val_if_fail (node != NULL, NULL); - return node->xmlns; -} - -static void -freePool (XMLNodePool * pool) -{ - unsigned int i; - xmlnode *x; - - for (i = 0; i < pool->pos; i++) - { - x = pool->nodes[i]; - GNUNET_free_non_null (x->name); - GNUNET_free_non_null (x->data); - GNUNET_free_non_null (x->xmlns); - GNUNET_free (x); - } - GNUNET_array_grow (pool->nodes, pool->size, 0); - GNUNET_free (pool); -} - -void -xmlnode_free (xmlnode * node) -{ - g_return_if_fail (node != NULL); - if (node->free_pool != GNUNET_YES) - return; - freePool (node->pool); -} - -static xmlnode * -xmlnode_get_child_with_namespace (const xmlnode * parent, - const char *name, const char *ns) -{ - xmlnode *x; - xmlnode *ret = NULL; - char *parent_name; - char *child_name; - - if (parent == NULL) - return NULL; - if (name == NULL) - return NULL; - - parent_name = GNUNET_strdup (name); - child_name = strstr (parent_name, "/"); - if (child_name != NULL) - { - child_name[0] = '\0'; - child_name++; - } - - for (x = parent->child; x; x = x->next) - { - const char *xmlns = NULL; - if (ns) - xmlns = xmlnode_get_namespace (x); - - if (x->type == XMLNODE_TYPE_TAG && name - && !strcmp (parent_name, x->name) && (!ns - || (xmlns - && !strcmp (ns, xmlns)))) - { - ret = x; - break; - } - } - - if (child_name && ret) - ret = xmlnode_get_child (ret, child_name); - - GNUNET_free (parent_name); - return ret; -} - -xmlnode * -xmlnode_get_child (const xmlnode * parent, const char *name) -{ - return xmlnode_get_child_with_namespace (parent, name, NULL); -} - -char * -xmlnode_get_data (xmlnode * node) -{ - char *str = NULL; - xmlnode *c; - - if (node == NULL) - return NULL; - for (c = node->child; c; c = c->next) - { - if (c->type == XMLNODE_TYPE_DATA) - { - if (!str) - str = GNUNET_strdup (""); - str = g_string_append_len (str, c->data, c->data_sz); - } - } - if (str == NULL) - return NULL; - - return str; -} - -static void -xmlnode_parser_element_start_libxml (void *user_data, - const xmlChar * element_name, - const xmlChar * prefix, - const xmlChar * xmlns, - int nb_namespaces, - const xmlChar ** namespaces, - int nb_attributes, - int nb_defaulted, - const xmlChar ** attributes) -{ - XMLNodePool *xpd = user_data; - xmlnode *node; - int i; - - if (!element_name) - return; - if (xpd->current) - node = - xmlnode_new_child (xpd->current, (const char *) element_name, - user_data); - else - node = xmlnode_new ((const char *) element_name, user_data); - - xmlnode_set_namespace (node, (const char *) xmlns); - - for (i = 0; i < nb_attributes * 5; i += 5) - { - char *txt; - int attrib_len = attributes[i + 4] - attributes[i + 3]; - char *attrib = GNUNET_malloc (attrib_len + 1); - memcpy (attrib, attributes[i + 3], attrib_len); - attrib[attrib_len] = '\0'; - txt = attrib; - attrib = gaim_unescape_html (txt); - GNUNET_free (txt); - xmlnode_set_attrib (node, (const char *) attributes[i], attrib, - user_data); - GNUNET_free (attrib); - } - xpd->current = node; -} - -static void -xmlnode_parser_element_end_libxml (void *user_data, - const xmlChar * element_name, - const xmlChar * prefix, - const xmlChar * xmlns) -{ - XMLNodePool *xpd = user_data; - - if (!element_name || !xpd->current) - return; - if (xpd->current->parent) - { - if (!xmlStrcmp ((xmlChar *) xpd->current->name, element_name)) - xpd->current = xpd->current->parent; - } -} - -static void -xmlnode_parser_element_text_libxml (void *user_data, - const xmlChar * text, int text_len) -{ - XMLNodePool *xpd = user_data; - - if (!xpd->current || !text || !text_len) - return; - xmlnode_insert_data (xpd->current, - (const char *) text, text_len, user_data); -} - -static xmlSAXHandler xmlnode_parser_libxml = { - .internalSubset = NULL, - .isStandalone = NULL, - .hasInternalSubset = NULL, - .hasExternalSubset = NULL, - .resolveEntity = NULL, - .getEntity = NULL, - .entityDecl = NULL, - .notationDecl = NULL, - .attributeDecl = NULL, - .elementDecl = NULL, - .unparsedEntityDecl = NULL, - .setDocumentLocator = NULL, - .startDocument = NULL, - .endDocument = NULL, - .startElement = NULL, - .endElement = NULL, - .reference = NULL, - .characters = xmlnode_parser_element_text_libxml, - .ignorableWhitespace = NULL, - .processingInstruction = NULL, - .comment = NULL, - .warning = NULL, - .error = NULL, - .fatalError = NULL, - .getParameterEntity = NULL, - .cdataBlock = NULL, - .externalSubset = NULL, - .initialized = XML_SAX2_MAGIC, - ._private = NULL, - .startElementNs = xmlnode_parser_element_start_libxml, - .endElementNs = xmlnode_parser_element_end_libxml, - .serror = NULL -}; - -xmlnode * -xmlnode_from_str (const char *str, int size) -{ - XMLNodePool *xpd; - xmlnode *ret; - size_t real_size; - - g_return_val_if_fail (str != NULL, NULL); - - real_size = size < 0 ? strlen (str) : size; - xpd = GNUNET_malloc (sizeof (XMLNodePool)); - memset (xpd, 0, sizeof (XMLNodePool)); - if (xmlSAXUserParseMemory (&xmlnode_parser_libxml, xpd, str, real_size) < 0) - { - freePool (xpd); - return NULL; - } - ret = xpd->current; - ret->free_pool = GNUNET_YES; - return ret; -} - -xmlnode * -xmlnode_get_next_twin (xmlnode * node) -{ - xmlnode *sibling; - const char *ns = xmlnode_get_namespace (node); - - g_return_val_if_fail (node != NULL, NULL); - g_return_val_if_fail (node->type == XMLNODE_TYPE_TAG, NULL); - - for (sibling = node->next; sibling; sibling = sibling->next) - { - const char *xmlns = NULL; - if (ns) - xmlns = xmlnode_get_namespace (sibling); - - if (sibling->type == XMLNODE_TYPE_TAG - && !strcmp (node->name, sibling->name) && (!ns - || (xmlns - && !strcmp (ns, - xmlns)))) - return sibling; - } - return NULL; -} diff --git a/src/upnp/upnp_xmlnode.h b/src/upnp/upnp_xmlnode.h deleted file mode 100644 index e3b9136a5..000000000 --- a/src/upnp/upnp_xmlnode.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @file upnp/upnp_xmlnode.h XML DOM functions - * @ingroup core - * - * gaim - * - * Gaim is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * 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 - */ -#ifndef _GGAIM_XMLNODE_H_ -#define _GGAIM_XMLNODE_H_ - - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * An xmlnode. - */ - typedef struct _xmlnode xmlnode; - -/** - * Gets a child node named name. - * - * @param parent The parent node. - * @param name The child's name. - * - * @return The child or NULL. - */ - xmlnode *xmlnode_get_child (const xmlnode * parent, const char *name); - -/** - * Gets the next node with the same name as node. - * - * @param node The node of a twin to find. - * - * @return The twin of node or NULL. - */ - xmlnode *xmlnode_get_next_twin (xmlnode * node); - -/** - * Gets data from a node. - * - * @param node The node to get data from. - * - * @return The data from the node. You must g_free - * this string when finished using it. - */ - char *xmlnode_get_data (xmlnode * node); - -/** - * Creates a node from a string of XML. Calling this on the - * root node of an XML document will parse the entire document - * into a tree of nodes, and return the xmlnode of the root. - * - * @param str The string of xml. - * @param size The size of the string, or -1 if @a str is - * NUL-terminated. - * - * @return The new node. - */ - xmlnode *xmlnode_from_str (const char *str, int size); - -/** - * Frees a node and all of it's children. - * - * @param node The node to free. - */ - void xmlnode_free (xmlnode * node); - -#ifdef __cplusplus -} -#endif - -#endif /* _GAIM_XMLNODE_H_ */ -- 2.25.1