summaryrefslogtreecommitdiffstats
path: root/tinyNET/src/dns
diff options
context:
space:
mode:
Diffstat (limited to 'tinyNET/src/dns')
-rw-r--r--tinyNET/src/dns/tnet_dns.c973
-rw-r--r--tinyNET/src/dns/tnet_dns.h125
-rw-r--r--tinyNET/src/dns/tnet_dns_a.c106
-rw-r--r--tinyNET/src/dns/tnet_dns_a.h61
-rw-r--r--tinyNET/src/dns/tnet_dns_aaaa.c108
-rw-r--r--tinyNET/src/dns/tnet_dns_aaaa.h58
-rw-r--r--tinyNET/src/dns/tnet_dns_cname.c97
-rw-r--r--tinyNET/src/dns/tnet_dns_cname.h63
-rw-r--r--tinyNET/src/dns/tnet_dns_message.c364
-rw-r--r--tinyNET/src/dns/tnet_dns_message.h209
-rw-r--r--tinyNET/src/dns/tnet_dns_mx.c99
-rw-r--r--tinyNET/src/dns/tnet_dns_mx.h66
-rw-r--r--tinyNET/src/dns/tnet_dns_naptr.c146
-rw-r--r--tinyNET/src/dns/tnet_dns_naptr.h81
-rw-r--r--tinyNET/src/dns/tnet_dns_ns.c96
-rw-r--r--tinyNET/src/dns/tnet_dns_ns.h63
-rw-r--r--tinyNET/src/dns/tnet_dns_opt.c91
-rw-r--r--tinyNET/src/dns/tnet_dns_opt.h54
-rw-r--r--tinyNET/src/dns/tnet_dns_ptr.c97
-rw-r--r--tinyNET/src/dns/tnet_dns_ptr.h61
-rw-r--r--tinyNET/src/dns/tnet_dns_regexp.c508
-rw-r--r--tinyNET/src/dns/tnet_dns_regexp.h41
-rw-r--r--tinyNET/src/dns/tnet_dns_resolvconf.c301
-rw-r--r--tinyNET/src/dns/tnet_dns_resolvconf.h43
-rw-r--r--tinyNET/src/dns/tnet_dns_rr.c452
-rw-r--r--tinyNET/src/dns/tnet_dns_rr.h171
-rw-r--r--tinyNET/src/dns/tnet_dns_soa.c112
-rw-r--r--tinyNET/src/dns/tnet_dns_soa.h82
-rw-r--r--tinyNET/src/dns/tnet_dns_srv.c137
-rw-r--r--tinyNET/src/dns/tnet_dns_srv.h59
-rw-r--r--tinyNET/src/dns/tnet_dns_txt.c96
-rw-r--r--tinyNET/src/dns/tnet_dns_txt.h61
32 files changed, 5081 insertions, 0 deletions
diff --git a/tinyNET/src/dns/tnet_dns.c b/tinyNET/src/dns/tnet_dns.c
new file mode 100644
index 0000000..0683cbb
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns.c
@@ -0,0 +1,973 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns.c
+ * @brief DNS utility functions (RFCS [1034 1035] [3401 3402 3403 3404] [3761]).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns.h"
+
+#include "tnet_dns_regexp.h"
+#include "tnet_dns_message.h"
+#include "tnet_dns_opt.h"
+#include "tnet_dns_srv.h"
+#include "tnet_dns_naptr.h"
+
+#include "tnet_types.h"
+
+#include "tsk_memory.h"
+#include "tsk_time.h"
+#include "tsk_debug.h"
+#include "tsk_string.h"
+
+#include <string.h> /* tsk_strlen, memser, .... */
+#include <ctype.h> /* isdigist */
+
+/* DNS cache functions */
+int tnet_dns_cache_maintenance(tnet_dns_ctx_t *ctx);
+int tnet_dns_cache_entry_add(tnet_dns_ctx_t *ctx, const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype, tnet_dns_response_t* response);
+const tnet_dns_cache_entry_t* tnet_dns_cache_entry_get(tnet_dns_ctx_t *ctx, const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype);
+
+/**@defgroup tnet_dns_group DNS utility functions (RFCS [1034 1035] [3401 3402 3403 3404]).
+*
+* <h1>11 DNS</h1>
+* <p>
+* The DNS Stack (RFC 1034 and RFC 1035) contains all network functions to send queries (both IPv4 and IPv6) and parse responses. <br>
+* The core framework implements RFC 3401, 3402, 3403 and 3404, also known as Dynamic Delegation Discovery System (DDDS).
+* </p>
+* <p>
+* The DNS servers are automatically loaded by the stack when you create a context (@ref tnet_dns_ctx_create()). <br>
+* On Windows systems (XP, VISTA, 7 and CE) the servers are retrieved using WIN32 APIs. On Unix-like systems (both desktop and embedded) such as Debian, Ubuntu, Nokia’s N900… the list of DNS servers comes from “/etc/resolv.conf” file. <br>
+* On Google Android operating system, this file is missing and the DNS settings are stored in the shared memory. You can access this shared memory by using @a property_get() and @a property_set() function which are part of Bionic. <br>
+* In all cases, you can retrieve the DNS servers yourself (e.g. using java/C# Frameworks) and add them to the context using @ref tnet_dns_add_server().
+* </p>
+* <p>
+* DNS resolution is always performed in a synchronous manner and is thread-safe. For all DNS requests the default timeout value is 5 seconds (@ref TNET_DNS_TIMEOUT_DEFAULT).
+* The stack also implements the ENUM protocol (RFC 3761).
+* </p>
+*
+* <h2>11.1 Resource Records</h2>
+* The table below lists all DNS Resource Records (RR) for which we provide a parser.
+*
+* <table>
+* <tr><td>Code</td> <td>RFC</td> <td>Description</td> <td>Well-defined type</td></tr>
+* <tr><td>A</td> <td>RFC 1035</td> <td>IPv4 address</td> <td>tnet_dns_a_t</td></tr>
+* <tr><td>AAAA</td> <td>RFC 3596</td> <td>IPv6 address</td> <td>tnet_dns_aaaa_t</td></tr>
+* <tr><td>CNAME</td> <td>RFC 1035</td> <td>Canonical name</td> <td>tnet_dns_cname_t</td></tr>
+* <tr><td>MX</td> <td>RFC 2035</td> <td>Mail exchange</td> <td>tnet_dns_mx_t</td></tr>
+* <tr><td>NAPTR</td> <td>RFC 3403</td> <td>Naming Authority Pointer</td> <td>tnet_dns_naptr_t</td></tr>
+* <tr><td>NS</td> <td>RFC 1035</td> <td>Name Server</td> <td>tnet_dns_ns_t</td></tr>
+* <tr><td>OPT</td> <td>RFC 2671</td> <td>Option</td> <td>tnet_dns_opt_t</td></tr>
+* <tr><td>PTR</td> <td>RFC 1035</td> <td>Pointer record</td> <td>tnet_dns_ptr_t</td></tr>
+* <tr><td>SOA</td> <td>RFC1035</td> <td>Start Of Authority record</td> <td>tnet_dns_soa_t</td></tr>
+* <tr><td>SRV</td> <td>RFC 2782</td> <td>Service locator</td> <td>tnet_dns_srv_t</td></tr>
+* </table>
+*
+* Here is an example of how to use the DNS stack to perform DNS NAPTR resolution and print the result to the console.
+*
+* @code
+tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
+tnet_dns_response_t *response = tsk_null;
+const tsk_list_item_t* item;
+const tnet_dns_rr_t* rr;
+
+if((response = tnet_dns_resolve(ctx, "sip2sip.info", qclass_in, qtype_naptr)))
+{
+ if(TNET_DNS_RESPONSE_IS_SUCCESS(response)){
+ TSK_DEBUG_INFO("We got a success response from the DNS server.");
+ // loop through the answers
+ tsk_list_foreach(item, response->Answers){
+ rr = item->data;
+ if(rr->qtype == qtype_naptr){
+ const tnet_dns_naptr_t *naptr = (const tnet_dns_naptr_t*)rr;
+
+ TSK_DEBUG_INFO("order=%u pref=%u flags=%s services=%s regexp=%s replacement=%s",
+ naptr->order,
+ naptr->preference,
+ naptr->flags,
+ naptr->services,
+ naptr->regexp,
+ naptr->replacement);
+ }
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("We got an error response from the DNS server. Error code: %u", response->Header.RCODE);
+ }
+}
+
+TSK_OBJECT_SAFE_FREE(response);
+TSK_OBJECT_SAFE_FREE(ctx);
+
+* @endcode
+* The @a ctx could be used several times and is a well-defined object.<br>
+* The console will output:
+* <i>INFO: We got a success response from the DNS server.</i><br>
+* <i>INFO: order=10 pref=0 flags=S services=SIP+d2u regexp=(null) replacement=_sip._udp.sip2sip.info</i><br>
+*
+* <h2>11.2 ENUM</h2>
+* ENUM (E.164 Number Mapping) protocol has been defined in RFC 3761.
+* ENUM protocol is used to transform telephone numbers of the PSTN network (e.g. +33600000) into internet resource addresses (e.g. sip:diopmamadou@example.com) by using DNS lookup (NAPTR). The internet resource address could be an email, ICQ, IAX2, H.323 …
+* In our case (3GPP IMS) it is typically used to convert TEL URIs (e.g. tel:+33600000) into SIP URIs (sip:+33600000;user=phone). The telephone number to convert should be a valid E.164 number.
+*
+* <h3>11.2.1 Usage</h3>
+* The code below shows how to gets the SIP address (with the higher order) associated to an E.164 telephone number.
+*
+* @code
+tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
+tnet_dns_response_t* response = tsk_null;
+char* uri = tsk_null;
+
+if((uri = tnet_dns_enum_2(ctx, "E2U+SIP", "+1-800-555-5555","e164.org"))){
+ TSK_DEBUG_INFO("URI=%s", uri);
+ TSK_FREE(uri);
+}
+else{
+ TSK_DEBUG_ERROR("ENUM(%s) failed", "+1-800-555-5555");
+}
+
+TSK_OBJECT_SAFE_FREE(response);
+TSK_OBJECT_SAFE_FREE(ctx);
+* @endcode
+*
+* Console Output:<br>
+* <i>INFO: URI=sip:16416418000-555-5555@sip.tollfreegateway.com</i><br>
+*
+* E2U+SIP is the name of SIP ENUM service assigned by the IANA. Any assigned service () could be used even if the associated addresse type isn’t a well-knonw internet address.
+* To get all internet addresses (email, IAX2, ICQ, H.323 …) associated to the telephone, use @ref tnet_dns_enum() instead of @ref tnet_dns_enum_2().
+*/
+
+/**@ingroup tnet_dns_group
+* Creates new DNS context.
+*/
+tnet_dns_ctx_t* tnet_dns_ctx_create()
+{
+ return tsk_object_new(tnet_dns_ctx_def_t);
+}
+
+/**@ingroup tnet_dns_group
+* Creates new DNS cache entry.
+*/
+tnet_dns_cache_entry_t* tnet_dns_cache_entry_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype, tnet_dns_response_t* answer)
+{
+ return tsk_object_new(tnet_dns_cache_entry_def_t, qname, qclass, qtype, answer);
+}
+
+
+/**@ingroup tnet_dns_group
+* Cleanup the internal DNS cache.
+* @param ctx The DNS context containing the cache to cleanup.
+* The context contains the user's preference and should be created using @ref tnet_dns_ctx_create().
+* @retval Zero if succeeed and non-zero error code otherwise.
+*/
+int tnet_dns_cache_clear(tnet_dns_ctx_t* ctx)
+{
+ if(ctx){
+ tsk_safeobj_lock(ctx);
+ tsk_list_clear_items(ctx->cache);
+ tsk_safeobj_unlock(ctx);
+
+ return 0;
+ }
+ return -1;
+}
+
+/**@ingroup tnet_dns_group
+* Sends DNS request over the network. The request will be sent each 500 milliseconds until @ref TNET_DNS_TIMEOUT_DEFAULT milliseconds is reached.
+* @param ctx The DNS context to use. The context contains the user's preference and should be created using @ref tnet_dns_ctx_create().
+* @param qname The domain name (e.g. google.com).
+* @param qclass The CLASS of the query.
+* @param qtype The type of the query.
+* @retval The DNS response. The @a answers in the @a response are already filtered.
+* MUST be destroyed using @a TSK_OBJECT_SAFE_FREE() macro.
+* @sa @ref tnet_dns_query_srv, @ref tnet_dns_query_naptr_srv, @ref tnet_dns_enum.
+*
+* @code
+* tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
+* tnet_dns_response_t *response = tnet_dns_resolve(ctx, "sip2sip.info", qclass_in, qtype_srv);
+* TSK_OBJECT_SAFE_FREE(response);
+* TSK_OBJECT_SAFE_FREE(ctx);
+* @endcode
+*/
+tnet_dns_response_t *tnet_dns_resolve(tnet_dns_ctx_t* ctx, const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype)
+{
+#if HAVE_DNS_H
+ struct sockaddr_storage result;
+ struct sockaddr *from;
+ uint32_t fromlen;
+ char buf[TNET_DNS_DGRAM_SIZE_DEFAULT];
+ int32_t ret;
+
+ tnet_dns_response_t *response = tsk_null;
+
+ tnet_socket_t *localsocket4 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv4);
+ tnet_socket_t *localsocket6 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv6);
+
+ tsk_safeobj_lock(ctx);
+
+ // First, try with IPv4
+ if(TNET_SOCKET_IS_VALID(localsocket4)){
+ if((ret = tnet_get_sockaddr(localsocket4->fd, &result))){
+ TNET_PRINT_LAST_ERROR("tnet_get_sockaddr() failed.");
+ goto ipv6;
+ }
+ from = (struct sockaddr *) &result;
+ fromlen = from->sa_len;
+
+ if ((ret = dns_search(ctx->resolv_handle, qname, qclass, qtype, buf, TNET_DNS_DGRAM_SIZE_DEFAULT, from, &fromlen)) > 0) {
+ response = tnet_dns_message_deserialize((uint8_t *) buf, ret);
+ goto done;
+ }
+ else{
+ TNET_PRINT_LAST_ERROR("dns_search_v4()");
+ }
+ }
+ipv6:
+ // Then, try with IPv6
+ if(TNET_SOCKET_IS_VALID(localsocket6)){
+ if((ret = tnet_get_sockaddr(localsocket6->fd, &result))){
+ TNET_PRINT_LAST_ERROR("tnet_get_sockaddr() failed.");
+ goto done;
+ }
+ from = (struct sockaddr *) &result;
+ fromlen = from->sa_len;
+
+ if((ret = dns_search(ctx->resolv_handle, qname, qclass, qtype, buf, TNET_DNS_DGRAM_SIZE_DEFAULT, from, &fromlen)) > 0){
+ response = tnet_dns_message_deserialize((uint8_t *) buf, ret);
+ goto done;
+ }
+ else{
+ TNET_PRINT_LAST_ERROR("dns_search_v6()");
+ }
+ }
+
+done:
+ tsk_safeobj_unlock(ctx);
+
+ TSK_OBJECT_SAFE_FREE(localsocket4);
+ TSK_OBJECT_SAFE_FREE(localsocket6);
+
+ return response;
+#else
+ tsk_buffer_t *output = tsk_null;
+ tnet_dns_query_t* query = tnet_dns_query_create(qname, qclass, qtype);
+ tnet_dns_response_t *response = tsk_null;
+ tsk_bool_t from_cache = tsk_false;
+
+ /* Check validity */
+ if(!ctx || !query){
+ goto bail;
+ }
+
+ /* Is there any DNS Server? */
+ if(TSK_LIST_IS_EMPTY(ctx->servers)){
+ TSK_DEBUG_ERROR("Failed to load DNS Servers. You can add new DNS servers by using \"tnet_dns_add_server\".");
+ goto bail;
+ }
+
+ /* Cache maintenance */
+ if(!TSK_LIST_IS_EMPTY(ctx->cache)){
+ /* Only do maintenance if the cache is not empty */
+ tnet_dns_cache_maintenance(ctx);
+ }
+
+ /* Retrieve data from cache. */
+ if(ctx->caching){
+ const tnet_dns_cache_entry_t *entry = tnet_dns_cache_entry_get(ctx, qname, qclass, qtype);
+ if(entry){
+ response = tsk_object_ref(((tnet_dns_cache_entry_t*)entry)->response);
+ from_cache = tsk_true;
+ goto bail;
+ }
+ }
+
+ /* Set user preference */
+ query->Header.RD = ctx->recursion;
+
+ /* EDNS0 */
+ if(ctx->edns0){
+ tnet_dns_opt_t *rr_opt = tnet_dns_opt_create(TNET_DNS_DGRAM_SIZE_DEFAULT);
+ if(!query->Additionals){
+ query->Additionals = tsk_list_create();
+ }
+ tsk_list_push_back_data(query->Additionals, (void**)&rr_opt);
+ query->Header.ARCOUNT++;
+ }
+
+ /* Serialize and send to the server. */
+ if(!(output = tnet_dns_message_serialize(query))){
+ TSK_DEBUG_ERROR("Failed to serialize the DNS message.");
+ goto bail;
+ }
+
+ /* ============================ */
+ // Send and Recaive data
+ /* ============================ */
+ {
+ int ret = -1;
+ struct timeval tv;
+ fd_set set;
+ tnet_fd_t maxFD;
+ uint64_t timeout = 0;
+ tsk_list_item_t *item;
+ const tnet_address_t *address;
+ struct sockaddr_storage server;
+ tnet_socket_t *localsocket4 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv4);
+ tnet_socket_t *localsocket6 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv6);
+ tsk_bool_t useIPv6 = TNET_SOCKET_IS_VALID(localsocket6);
+
+ tsk_safeobj_lock(ctx);
+
+ /* Check socket validity */
+ if(!TNET_SOCKET_IS_VALID(localsocket4)){
+ goto done;
+ }
+
+ /* Always wait 500ms before retransmission */
+ tv.tv_sec = 0;
+ tv.tv_usec = (500 * 1000);
+
+ do
+ {
+ //
+ // Send data (loop through all intefaces)
+ //
+ tsk_list_foreach(item, ctx->servers)
+ {
+ address = item->data;
+ if(!address->ip ||
+ (address->family != AF_INET && address->family != AF_INET6) ||
+ (address->family == AF_INET6 && !TNET_SOCKET_IS_VALID(localsocket6))){
+ continue;
+ }
+
+ if(tnet_sockaddr_init(address->ip, ctx->server_port, (address->family == AF_INET ? tnet_socket_type_udp_ipv4 : tnet_socket_type_udp_ipv6), &server)){
+ TSK_DEBUG_ERROR("Failed to initialize the DNS server address: \"%s\"", address->ip);
+ continue;
+ }
+
+ TSK_DEBUG_INFO("Sending DNS query to \"%s\"", address->ip);
+
+ if(address->family == AF_INET6){
+ if((ret = tnet_sockfd_sendto(localsocket6->fd, (const struct sockaddr*)&server, output->data, output->size))){
+ // succeed?
+ break;
+ }
+ }
+ else{
+ if((ret = tnet_sockfd_sendto(localsocket4->fd, (const struct sockaddr*)&server, output->data, output->size))){
+ // succeed?
+ break;
+ }
+ }
+ }
+
+ //
+ // Received data
+ //
+ /* First time? ==> set timeout value */
+ if(!timeout){
+ timeout = tsk_time_epoch() + ctx->timeout;
+ }
+
+ /* Set FDs */
+ FD_ZERO(&set);
+ FD_SET(localsocket4->fd, &set);
+ if(useIPv6){
+ FD_SET(localsocket6->fd, &set);
+ maxFD = TSK_MAX(localsocket4->fd, localsocket6->fd);
+ }
+ else{
+ maxFD = localsocket4->fd;
+ }
+
+ /* wait for response */
+ if((ret = select(maxFD+1, &set, NULL, NULL, &tv))<0){ /* Error */
+ TNET_PRINT_LAST_ERROR("Select failed.");
+ goto done;
+ }
+ else if(ret == 0){ /* timeout ==> do nothing */
+
+ }
+ else{ /* there is data to read */
+ tsk_size_t len = 0;
+ void* data = 0;
+ tnet_fd_t active_fd;
+
+ /* Find active file descriptor */
+ if(FD_ISSET(localsocket4->fd, &set)){
+ active_fd = localsocket4->fd;
+ }
+ else if(FD_ISSET(localsocket6->fd, &set)){
+ active_fd = localsocket4->fd;
+ }
+ else{
+ TSK_DEBUG_ERROR("FD_ISSET ==> Invalid file descriptor.");
+ continue;
+ }
+
+ /* Check how how many bytes are pending */
+ if((ret = tnet_ioctlt(active_fd, FIONREAD, &len))<0){
+ TSK_DEBUG_ERROR("tnet_ioctlt failed with error code:%d", tnet_geterrno());
+ goto done;
+ }
+
+ /* Receive pending data */
+ data = tsk_calloc(len, sizeof(uint8_t));
+ if((ret = tnet_sockfd_recv(active_fd, data, len, 0))<0){
+ TSK_FREE(data);
+
+ TSK_DEBUG_ERROR("tnet_sockfd_recv failed with error code:%d", tnet_geterrno());
+ goto done;
+ }
+
+ /* Parse the incoming response. */
+ response = tnet_dns_message_deserialize(data, (tsk_size_t)ret);
+ TSK_FREE(data);
+
+ if(response)
+ { /* response successfuly parsed */
+ if(query->Header.ID != response->Header.ID || !TNET_DNS_MESSAGE_IS_RESPONSE(response)){
+ /* Not same transaction id ==> continue*/
+ TSK_OBJECT_SAFE_FREE(response);
+ }
+ else goto done;
+ }
+ }
+ }
+ while(timeout > tsk_time_epoch());
+
+done:
+ tsk_safeobj_unlock(ctx);
+
+ TSK_OBJECT_SAFE_FREE(localsocket4);
+ TSK_OBJECT_SAFE_FREE(localsocket6);
+ goto bail;
+ }
+
+
+bail:
+ TSK_OBJECT_SAFE_FREE(query);
+ TSK_OBJECT_SAFE_FREE(output);
+
+ /* Add the result to the cache. */
+ if(response){
+ if(!from_cache && ctx->caching){
+ tnet_dns_cache_entry_add(ctx, qname, qclass, qtype, response);
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to contact the DNS server.");
+ }
+
+ return response;
+#endif
+}
+
+/**@ingroup tnet_dns_group
+* Gets list of URIs associated to this telephone number by using ENUM protocol (RFC 3761).
+* @param ctx The DNS context.
+* The context contains the user's preference and should be created using @ref tnet_dns_ctx_create().
+* @param e164num A valid E.164 number (e.g. +1-800-555-5555).
+* @param domain The domain name (e.g e164.arpa, e164.org, ...). If Null, default value is "e164.arpa" (IANA).
+* @retval The DNS response with NAPTR RRs. The @a answers in the @a response are already filtered.
+* MUST be destroyed using @a TSK_OBJECT_SAFE_FREE macro.
+* @sa @ref tnet_dns_resolve, @ref tnet_dns_enum_2.
+*/
+tnet_dns_response_t* tnet_dns_enum(tnet_dns_ctx_t* ctx, const char* e164num, const char* domain)
+{
+ char e164domain[255];
+ tnet_dns_response_t* ret = tsk_null;
+ tsk_size_t e164size;
+ int i, j; // must be signed
+
+ e164size = tsk_strlen(e164num);
+
+ if(!ctx || !e164num || !e164size){
+ goto bail;
+ }
+
+ if(e164size /* max=15 digits + ".e164.arpa" + '+' */>=(sizeof(e164domain)-1)){
+ TSK_DEBUG_ERROR("%s is an invalid E.164 number.", e164num);
+ goto bail;
+ }
+
+ memset(e164domain, '\0', sizeof(e164domain));
+
+ /* RFC 3761 - 2.4. Valid Databases
+ 1. Remove all characters with the exception of the digits. For
+ example, the First Well Known Rule produced the Key
+ "+442079460148". This step would simply remove the leading "+",
+ producing "442079460148".
+
+ 2. Put dots (".") between each digit. Example:
+ 4.4.2.0.7.9.4.6.0.1.4.8
+
+ 3. Reverse the order of the digits. Example:
+ 8.4.1.0.6.4.9.7.0.2.4.4
+
+ 4. Append the string ".e164.arpa" to the end. Example:
+ 8.4.1.0.6.4.9.7.0.2.4.4.e164.arpa
+
+ This domain-name is used to request NAPTR records which may contain
+ the end result or, if the flags field is blank, produces new keys in
+ the form of domain-names from the DNS.
+ */
+ for(i = e164size-1, j=0; i>=0; i--){
+ if(!isdigit(e164num[i])){
+ continue;
+ }
+ e164domain[j++] = e164num[i];
+ e164domain[j++] = '.';
+ }
+
+ // append domain name
+ if(domain){
+ memcpy( &e164domain[j], domain, ((tsk_strlen(domain) + j) >= sizeof(e164domain)-1) ? (sizeof(e164domain)-j-1) : tsk_strlen(domain) );
+ }
+ else{
+ memcpy(&e164domain[j], "e164.arpa", 9);
+ }
+
+ /* == Performs DNS (NAPTR) lookup == */
+ ret = tnet_dns_resolve(ctx, e164domain, qclass_in, qtype_naptr);
+
+bail:
+
+ return ret;
+}
+
+/**@ingroup tnet_dns_group
+* Gets the internate address associated to this telephone number by using ENUM protocol (RFC 3761).
+* Only terminale rules containing uris(flags="u") will be considered and the regex string will be executed on the original string for
+* substitution. <br>
+* <b> Parsing complex regexp will probably fail (99.99% chance). Please use @ref tnet_dns_enum if you want to use your own regexp parser. </b>
+* @param ctx The DNS context.
+* The context contains the user's preference and should be created using @ref tnet_dns_ctx_create().
+* @param service The ENUM service (e.g. E2U+SIP).
+* @param e164num A valid E.164 number (e.g. +1-800-555-5555).
+* @param domain The domain name (e.g e164.arpa, e164.org, ...). If Null, default value is "e164.arpa" (IANA).
+* @retval The Internet address (SIP, email, ICQ, fax, ...) associated to this service.
+* MUST be freed using @a TSK_FREE macro.
+* @sa @ref tnet_dns_resolve, @ref tnet_dns_enum.
+*/
+char* tnet_dns_enum_2(tnet_dns_ctx_t* ctx, const char* service, const char* e164num, const char* domain)
+{
+ tnet_dns_response_t* response;
+ const tsk_list_item_t* item;
+ char* ret = tsk_null;
+ const tnet_dns_rr_t* rr;
+
+ if((response = tnet_dns_enum(ctx, e164num, domain))){
+ if(TNET_DNS_RESPONSE_IS_SUCCESS(response)){
+ tsk_list_foreach(item, response->Answers){
+ rr = item->data;
+ if(rr->qtype == qtype_naptr){
+ const tnet_dns_naptr_t *naptr = (const tnet_dns_naptr_t*)rr;
+ /* RFC 3403 - 6.2 E164 Example
+ Both the ENUM [18] and URI Resolution [4] Applications use the 'u'
+ flag. This flag states that the Rule is terminal and that the output
+ is a URI which contains the information needed to contact that
+ telephone service.
+ */
+ if( tsk_striequals(naptr->flags, "u") && tsk_striequals(naptr->services, service)){
+ /* RFC 3403 - 4.1 Packet Format
+ The fields (replacement and regexp) are also mutually exclusive. If a record is
+ returned that has values for both fields then it is considered to
+ be in error and SHOULD be either ignored or an error returned.
+ */
+ if(naptr->regexp && naptr->replacement){
+ continue;
+ }
+
+ if((ret = tnet_dns_regex_parse(e164num, naptr->regexp))){
+ break;
+ }
+ }
+ }
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("We got an error response from the DNS server. Error code: %u", response->Header.RCODE);
+ }
+
+ TSK_OBJECT_SAFE_FREE(response);
+ }
+
+ return ret;
+}
+
+/**@ingroup tnet_dns_group
+* Performs DNS SRV resolution.
+* @param ctx The DNS context.
+* The context contains the user's preference and should be created using @ref tnet_dns_ctx_create.
+* @param service The name of the service (e.g. SIP+D2U).
+* @param hostname The result containing an IP address or FQDN.
+* @param port The port associated to the result.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tnet_dns_resolve.
+*
+* @code
+* tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
+* char* hostname = 0;
+* tnet_port_t port = 0;
+*
+* if(!tnet_dns_query_srv(ctx, "_sip._udp.sip2sip.info", &hostname, &port)){
+* TSK_DEBUG_INFO("DNS SRV succeed ==> hostname=%s and port=%u", hostname, port);
+* }
+*
+* TSK_FREE(hostname);
+* TSK_OBJECT_SAFE_FREE(ctx);
+* @endcode
+*/
+int tnet_dns_query_srv(tnet_dns_ctx_t *ctx, const char* service, char** hostname, tnet_port_t* port)
+{
+ tnet_dns_response_t *response;
+
+ if(!ctx){
+ return -1;
+ }
+
+ // tnet_dns_resolve is thread-safe
+ if((response = tnet_dns_resolve(ctx, service, qclass_in, qtype_srv)))
+ {
+ const tsk_list_item_t *item;
+ const tnet_dns_rr_t* rr;
+ tsk_list_foreach(item, response->Answers) /* Already Filtered ==> Peek the first One */
+ {
+ rr = item->data;
+ if(rr->qtype == qtype_srv){
+ const tnet_dns_srv_t *srv = (const tnet_dns_srv_t*)rr;
+
+ tsk_strupdate(hostname, srv->target);
+ *port = srv->port;
+ break;
+ }
+ }
+ }
+
+ TSK_OBJECT_SAFE_FREE(response);
+
+ return (hostname && !tsk_strnullORempty(*hostname)) ? 0 : -2;
+}
+
+/**@ingroup tnet_dns_group
+* Performs DNS NAPTR followed by DNS SRV resolution.
+* @param ctx The DNS context.
+* The context contains the user's preference and should be created using @ref tnet_dns_ctx_create().
+* @param domain The Name of the domain (e.g. google.com).
+* @param service The name of the service (e.g. SIP+D2U).
+* @param hostname The result containing an IP address or FQDN. Should be Null.
+* @param port The port associated to the result.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tnet_dns_resolve.
+*
+* @code
+* tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
+* char* hostname = tsk_null;
+* tnet_port_t port = 0;
+*
+* if(!tnet_dns_query_naptr_srv(ctx, "sip2sip.info", "SIP+D2U", &hostname, &port)){
+* TSK_DEBUG_INFO("DNS NAPTR+SRV succeed ==> hostname=%s and port=%u", hostname, port);
+* }
+*
+* TSK_FREE(hostname);
+* TSK_OBJECT_SAFE_FREE(ctx);
+* @endcode
+*/
+int tnet_dns_query_naptr_srv(tnet_dns_ctx_t *ctx, const char* domain, const char* service, char** hostname, tnet_port_t* port)
+{
+ tnet_dns_response_t *response;
+
+ if(!ctx || !hostname){
+ TSK_DEBUG_ERROR("Invalid parameters.");
+ return -1;
+ }
+
+ /* reset (do not free the user supplied value). trying to free dummy value will cause access violation error ==> zero. */
+ *hostname = tsk_null;
+
+ // tnet_dns_resolve is thread-safe
+ if((response = tnet_dns_resolve(ctx, domain, qclass_in, qtype_naptr))){
+ const tsk_list_item_t *item;
+ const tnet_dns_rr_t* rr;
+
+ char* replacement = tsk_null; /* e.g. _sip._udp.example.com */
+ char* flags = tsk_null;/* e.g. S, A, AAAA, A6, U, P ... */
+
+ tsk_list_foreach(item, response->Answers) /* Already Filtered ==> Peek the first One */
+ {
+ rr = item->data;
+ if(rr->qtype == qtype_naptr){
+ tnet_dns_naptr_t *naptr = (tnet_dns_naptr_t*)rr;
+
+ if(tsk_striequals(service, naptr->services)){
+ tsk_strupdate(&replacement, naptr->replacement);
+ tsk_strupdate(&flags, naptr->flags);
+
+ break;
+ }
+ }
+ }
+
+ if(flags && replacement){
+ if(tsk_striequals(flags, "S")){
+ tnet_dns_query_srv(ctx, replacement, hostname, port);
+ }
+ else if(tsk_striequals(flags, "A") || tsk_striequals(flags, "AAAA") ||tsk_striequals(flags, "A6")){
+ TSK_DEBUG_WARN("Defaulting port value.");
+ tsk_strupdate(hostname, replacement);
+ *port = 5060;
+ }
+ else{
+ TSK_DEBUG_ERROR("DNS NAPTR query returned invalid falgs.");
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("DNS NAPTR query returned zero result.");
+ }
+
+ TSK_FREE(flags);
+ TSK_FREE(replacement);
+ }
+
+ TSK_OBJECT_SAFE_FREE(response);
+
+ return (hostname && *hostname && !tsk_strempty(*hostname)) ? 0 : -2;
+}
+
+// remove timedout entries
+int tnet_dns_cache_maintenance(tnet_dns_ctx_t *ctx)
+{
+
+ if(ctx)
+ {
+ tsk_list_item_t *item;
+ tsk_safeobj_lock(ctx);
+again:
+
+ tsk_list_foreach(item, ctx->cache)
+ {
+ // FIXME: ttl should be from RR::ttl
+ tnet_dns_cache_entry_t *entry = (tnet_dns_cache_entry_t*)item->data;
+ if((entry ->epoch + ctx->cache_ttl) < tsk_time_epoch()){
+ tsk_list_remove_item_by_data(ctx->cache, entry);
+ goto again; /* Do not delete data while looping */
+ }
+ }
+
+ tsk_safeobj_unlock(ctx);
+
+ return 0;
+ }
+ return -1;
+}
+
+// add an entry to the cache
+int tnet_dns_cache_entry_add(tnet_dns_ctx_t *ctx, const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype, tnet_dns_response_t* response)
+{
+ int ret = -1;
+
+ if(ctx)
+ {
+ tnet_dns_cache_entry_t *entry;
+
+ tsk_safeobj_lock(ctx);
+
+ entry = 0;
+
+ /* Retrieve from cache */
+ entry = (tnet_dns_cache_entry_t*)tnet_dns_cache_entry_get(ctx, qname, qclass, qtype);
+
+ if(entry){
+ /* UPDATE */
+ TSK_OBJECT_SAFE_FREE(entry->response);
+ entry->response = tsk_object_ref(response);
+ entry->epoch = tsk_time_epoch();
+ ret = 0;
+ goto done;
+ }
+ else{
+ /* CREATE */
+ entry = tnet_dns_cache_entry_create(qname, qclass, qtype, response);
+ if(entry){
+ tsk_list_push_back_data(ctx->cache, (void**)&entry);
+ ret = 0;
+ goto done;
+ }
+ else{
+ ret = -2;
+ goto done;
+ }
+ }
+done:
+ tsk_safeobj_unlock(ctx);
+ }
+ return ret;
+}
+
+// get an entry from the cache
+const tnet_dns_cache_entry_t* tnet_dns_cache_entry_get(tnet_dns_ctx_t *ctx, const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype)
+{
+ tnet_dns_cache_entry_t *ret = tsk_null;
+ if(ctx)
+ {
+ tsk_list_item_t *item;
+
+ tsk_safeobj_lock(ctx);
+
+ tsk_list_foreach(item, ctx->cache){
+ tnet_dns_cache_entry_t *entry = (tnet_dns_cache_entry_t*)item->data;
+ if(entry->qtype == qtype && entry->qclass == qclass && tsk_strequals(entry->qname, qname)){
+ ret = entry;
+ break;
+ }
+ }
+
+ tsk_safeobj_unlock(ctx);
+ }
+
+ return ret;
+}
+
+
+/**@ingroup tnet_dns_group
+* Adds new DNS server to the list of the list of servers to query.
+* @param ctx DNS context containing the user parameters. The new DNS server will be added to this context.
+* @param host The IP address (or FQDN) of the dns server to add to the server.
+* @retval zero if succeed and non-zero error code otherwise.
+*/
+int tnet_dns_add_server(tnet_dns_ctx_t *ctx, const char* host)
+{
+ tnet_address_t *address;
+
+ if(!ctx || !host){
+ return -1;
+ }
+
+ if(!ctx->servers){
+ ctx->servers = tsk_list_create();
+ }
+
+ if((address = tnet_address_create(host))){
+ address->family = tnet_get_family(host, TNET_DNS_SERVER_PORT_DEFAULT);
+ address->dnsserver = 1;
+ tsk_list_push_ascending_data(ctx->servers, (void**)&address);
+
+ return 0;
+ }
+
+ return -2;
+}
+
+//=================================================================================================
+// [[DNS CACHE ENTRY]] object definition
+//
+static tsk_object_t* tnet_dns_cache_entry_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_cache_entry_t *entry = self;
+ if(entry){
+ entry->qname = tsk_strdup(va_arg(*app, const char*));
+ entry->qclass = va_arg(*app, tnet_dns_qtype_t);
+ entry->qtype = va_arg(*app, tnet_dns_qtype_t);
+ entry->response = tsk_object_ref(va_arg(*app, tnet_dns_response_t*));
+
+ entry->epoch = tsk_time_epoch();
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_cache_entry_dtor(tsk_object_t * self)
+{
+ tnet_dns_cache_entry_t *entry = self;
+ if(entry){
+ TSK_OBJECT_SAFE_FREE(entry->response);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_cache_entry_def_s =
+{
+ sizeof(tnet_dns_cache_entry_t),
+ tnet_dns_cache_entry_ctor,
+ tnet_dns_cache_entry_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_cache_entry_def_t = &tnet_dns_cache_entry_def_s;
+
+
+//=================================================================================================
+// [[DNS CONTEXT]] object definition
+//
+static tsk_object_t* tnet_dns_ctx_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_ctx_t *ctx = self;
+ if(ctx){
+ ctx->timeout = TNET_DNS_TIMEOUT_DEFAULT;
+ ctx->recursion = tsk_true;
+ ctx->edns0 = tsk_true;
+ ctx->caching = tsk_false;
+
+ ctx->cache_ttl = TNET_DNS_CACHE_TTL;
+
+ ctx->server_port = TNET_DNS_SERVER_PORT_DEFAULT;
+
+ /* Gets all dns servers. */
+ ctx->servers = tnet_get_addresses_all_dnsservers();
+ /* Creates empty cache. */
+ ctx->cache = tsk_list_create();
+
+#if HAVE_DNS_H
+ ctx->resolv_handle = dns_open(NULL);
+#endif
+
+ tsk_safeobj_init(ctx);
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_ctx_dtor(tsk_object_t * self)
+{
+ tnet_dns_ctx_t *ctx = self;
+ if(ctx){
+ tsk_safeobj_deinit(ctx);
+
+ TSK_OBJECT_SAFE_FREE(ctx->servers);
+ TSK_OBJECT_SAFE_FREE(ctx->cache);
+
+#if HAVE_DNS_H
+ dns_free(ctx->resolv_handle);
+#endif
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_ctx_def_s =
+{
+ sizeof(tnet_dns_ctx_t),
+ tnet_dns_ctx_ctor,
+ tnet_dns_ctx_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_ctx_def_t = &tnet_dns_ctx_def_s;
diff --git a/tinyNET/src/dns/tnet_dns.h b/tinyNET/src/dns/tnet_dns.h
new file mode 100644
index 0000000..0ff6290
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns.h
@@ -0,0 +1,125 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns.h
+ * @brief DNS utilities functions (RFCS [1034 1035] [2671] [3401 3402 3403 3404] [3761]).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#ifndef TNET_DNS_H
+#define TNET_DNS_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_message.h"
+
+#include "tnet_utils.h"
+
+#include "tsk_safeobj.h"
+
+#if HAVE_DNS_H
+#include <dns.h>
+#endif
+
+TNET_BEGIN_DECLS
+
+/**@ingroup tnet_dns_group
+*/
+#define TNET_DNS_CACHE_TTL (15000 * 1000)
+
+/**@ingroup tnet_dns_group
+* Default timeout (in milliseconds) value for DNS queries.
+*/
+#define TNET_DNS_TIMEOUT_DEFAULT 5000 //(5 seconds)
+
+/**@ingroup tnet_dns_group
+* Maximum supported Dgram size to advertise using EDNS0.
+*/
+#define TNET_DNS_DGRAM_SIZE_DEFAULT 4096
+
+/**@ingroup tnet_dns_group
+*/
+#define TNET_DNS_SERVER_PORT_DEFAULT 53
+
+/**DNS cache entry.
+*/
+typedef struct tnet_dns_cache_entry_s
+{
+ TSK_DECLARE_OBJECT;
+
+ char* qname;
+ tnet_dns_qclass_t qclass;
+ tnet_dns_qtype_t qtype;
+
+ uint64_t epoch;
+
+ tnet_dns_response_t *response;
+}
+tnet_dns_cache_entry_t;
+typedef tsk_list_t tnet_dns_cache_entries_L_t;
+typedef tnet_dns_cache_entries_L_t tnet_dns_cache_t;
+
+/**DNS context.
+*/
+typedef struct tnet_dns_ctx_s
+{
+ TSK_DECLARE_OBJECT;
+
+ uint64_t timeout; /**< In milliseconds. Default: @ref TNET_DNS_TIMEOUT_DEFAULT. */
+ tsk_bool_t recursion; /**< Indicates whether to direct the name server to pursue the query recursively. Default: enabled.*/
+ tsk_bool_t edns0; /**< Indicates whether to enable EDNS0 (Extension Mechanisms for DNS) or not. This option will allow you to send DNS packet larger than 512 bytes. Default: enabled. */
+ tsk_bool_t caching; /**< Indicates whether to enable the DNS cache or not. Default: no. */
+
+ int32_t cache_ttl;
+
+ tnet_port_t server_port; /**< Default port (@a TNET_DNS_SERVER_PORT_DEFAULT)) */
+
+ tnet_dns_cache_t *cache;
+ tnet_addresses_L_t *servers;
+
+#if HAVE_DNS_H
+ dns_handle_t resolv_handle;
+#endif
+
+ TSK_DECLARE_SAFEOBJ;
+}
+tnet_dns_ctx_t;
+
+TINYNET_API int tnet_dns_cache_clear(tnet_dns_ctx_t* ctx);
+TINYNET_API tnet_dns_response_t* tnet_dns_resolve(tnet_dns_ctx_t* ctx, const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype);
+TINYNET_API tnet_dns_response_t* tnet_dns_enum(tnet_dns_ctx_t* ctx, const char* e164num, const char* domain);
+TINYNET_API char* tnet_dns_enum_2(tnet_dns_ctx_t* ctx, const char* service, const char* e164num, const char* domain);
+TINYNET_API int tnet_dns_query_srv(tnet_dns_ctx_t *ctx, const char* service, char** hostname, tnet_port_t* port);
+TINYNET_API int tnet_dns_query_naptr_srv(tnet_dns_ctx_t *ctx, const char* domain, const char* service, char** hostname, tnet_port_t* port);
+
+TINYNET_API int tnet_dns_add_server(tnet_dns_ctx_t *ctx, const char* host);
+
+TINYNET_API tnet_dns_ctx_t* tnet_dns_ctx_create();
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_ctx_def_t;
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_cache_entry_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_H */
diff --git a/tinyNET/src/dns/tnet_dns_a.c b/tinyNET/src/dns/tnet_dns_a.c
new file mode 100644
index 0000000..f53e070
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_a.c
@@ -0,0 +1,106 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_a.c
+ * @brief DNS Address record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_a.h"
+
+#include "../tnet_types.h"
+#include "../tnet_endianness.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+/** Creates new DNS A Resource Record.
+*/
+tnet_dns_a_t* tnet_dns_a_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_a_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+
+//=================================================================================================
+// [[DNS A]] object definition
+//
+static tsk_object_t* tnet_dns_a_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_a_t *a = self;
+ if(a){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ const uint8_t* rddata = (((uint8_t*)data) + offset);
+ //const uint8_t* dataEnd = (rddata + rdlength);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(a), qtype_a, qclass);
+ TNET_DNS_RR(a)->name = tsk_strdup(name);
+ TNET_DNS_RR(a)->rdlength = rdlength;
+ TNET_DNS_RR(a)->ttl = ttl;
+
+ if(rddata && rdlength && (rdlength == 4/* 32bits */)){
+ // ==> DESERIALIZATION
+ /* ADDRESS */
+ uint32_t address = tnet_htonl_2(rddata);
+ tsk_sprintf(&(a->address), "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF);
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid IPv4 address.");
+ }
+
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_a_dtor(tsk_object_t * self)
+{
+ tnet_dns_a_t *a = self;
+ if(a){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(a));
+
+ TSK_FREE(a->address);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_a_def_s =
+{
+ sizeof(tnet_dns_a_t),
+ tnet_dns_a_ctor,
+ tnet_dns_a_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_a_def_t = &tnet_dns_a_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_a.h b/tinyNET/src/dns/tnet_dns_a.h
new file mode 100644
index 0000000..19fb910
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_a.h
@@ -0,0 +1,61 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_a.h
+ * @brief DNS Address record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_A_H
+#define TNET_DNS_RR_A_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+TNET_BEGIN_DECLS
+
+
+/**DNS A Resource Record.
+*/
+typedef struct tnet_dns_a_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ /* RFC 1035 - 3.4.1. A RDATA format
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ADDRESS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ char* address;
+}
+tnet_dns_a_t;
+
+TINYNET_API tnet_dns_a_t* tnet_dns_a_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_a_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_A_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_aaaa.c b/tinyNET/src/dns/tnet_dns_aaaa.c
new file mode 100644
index 0000000..ab1fa64
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_aaaa.c
@@ -0,0 +1,108 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_aaaA.c
+ * @brief DNS IPv6 address record - RR - (RFC 3596).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_aaaa.h"
+
+#include "../tnet_types.h"
+#include "../tnet_endianness.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+/** Creates new DNS AAAA Resource Record.
+*/
+
+tnet_dns_aaaa_t* tnet_dns_aaaa_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_aaaa_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+
+//=================================================================================================
+// [[DNS AAAA]] object definition
+//
+static tsk_object_t* tnet_dns_aaaa_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_aaaa_t *aaaa = self;
+ if(aaaa){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ const uint8_t* rddata = (((uint8_t*)data) + offset);
+ //const uint8_t* dataEnd = (rddata + rdlength);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(aaaa), qtype_aaaa, qclass);
+ TNET_DNS_RR(aaaa)->name = tsk_strdup(name);
+ TNET_DNS_RR(aaaa)->rdlength = rdlength;
+ TNET_DNS_RR(aaaa)->ttl = ttl;
+
+ if(rddata && rdlength && (rdlength == 16/* 128bits */)){
+ // ==> DESERIALIZATION
+ /* ADDRESS */
+ tsk_sprintf(&(aaaa->address), "%x:%x:%x:%x:%x:%x:%x:%x",
+ tnet_ntohs_2(&rddata[0]), tnet_ntohs_2(&rddata[2]), tnet_ntohs_2(&rddata[4]), tnet_ntohs_2(&rddata[6]),
+ tnet_ntohs_2(&rddata[8]), tnet_ntohs_2(&rddata[10]), tnet_ntohs_2(&rddata[12]), tnet_ntohs_2(&rddata[14]));
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid IPv6 address.");
+ }
+
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_aaaa_dtor(tsk_object_t * self)
+{
+ tnet_dns_aaaa_t *aaaa = self;
+ if(aaaa){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(aaaa));
+
+ TSK_FREE(aaaa->address);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_aaaa_def_s =
+{
+ sizeof(tnet_dns_aaaa_t),
+ tnet_dns_aaaa_ctor,
+ tnet_dns_aaaa_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_aaaa_def_t = &tnet_dns_aaaa_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_aaaa.h b/tinyNET/src/dns/tnet_dns_aaaa.h
new file mode 100644
index 0000000..73d5f3f
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_aaaa.h
@@ -0,0 +1,58 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_aaaa.h
+ * @brief DNS IPv6 address record - RR - (RFC 3596).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_AAAA_H
+#define TNET_DNS_RR_AAAA_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+
+TNET_BEGIN_DECLS
+
+/**DNS AAAA Resource Record.
+*/
+typedef struct tnet_dns_aaaa_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ /* RFC 3596 -
+ */
+ char* address;
+}
+tnet_dns_aaaa_t;
+
+tnet_dns_aaaa_t* tnet_dns_aaaa_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_aaaa_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_AAAA_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_cname.c b/tinyNET/src/dns/tnet_dns_cname.c
new file mode 100644
index 0000000..507a713
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_cname.c
@@ -0,0 +1,97 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_cname.c
+ * @brief DNS Mail eXchange record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_cname.h"
+
+#include "../tnet_types.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+
+/** Creates new DNS CNAME Resource Record.
+*/
+
+tnet_dns_cname_t* tnet_dns_cname_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_cname_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+
+//=================================================================================================
+// [[DNS CNAME]] object definition
+//
+static tsk_object_t* tnet_dns_cname_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_cname_t *cname = self;
+ if(cname){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(cname), qtype_cname, qclass);
+ TNET_DNS_RR(cname)->name = tsk_strdup(name);
+ TNET_DNS_RR(cname)->rdlength = rdlength;
+ TNET_DNS_RR(cname)->ttl = ttl;
+
+ if(rdlength){
+ // ==> DESERIALIZATION
+ /* CNAME */
+ tnet_dns_rr_qname_deserialize(data, &(cname->cname), &offset);
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_cname_dtor(tsk_object_t * self)
+{
+ tnet_dns_cname_t *cname = self;
+ if(cname){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(cname));
+
+ TSK_FREE(cname->cname);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_cname_def_s =
+{
+ sizeof(tnet_dns_cname_t),
+ tnet_dns_cname_ctor,
+ tnet_dns_cname_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_cname_def_t = &tnet_dns_cname_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_cname.h b/tinyNET/src/dns/tnet_dns_cname.h
new file mode 100644
index 0000000..b41b159
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_cname.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_cname.h
+ * @brief DNS Mail eXchange record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_CNAME_H
+#define TNET_DNS_RR_CNAME_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+
+TNET_BEGIN_DECLS
+
+
+/** DNS CNAME Resource Record
+*/
+typedef struct tnet_dns_cname_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ /* 3.3.1. CNAME RDATA format
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / CNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ char* cname;
+}
+tnet_dns_cname_t;
+
+tnet_dns_cname_t* tnet_dns_cname_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_cname_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_CNAME_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_message.c b/tinyNET/src/dns/tnet_dns_message.c
new file mode 100644
index 0000000..cc2c2e2
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_message.c
@@ -0,0 +1,364 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_message.h
+ * @brief DNS Message holding RRs (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_message.h"
+
+#include "../tnet_utils.h"
+#include "../tnet_endianness.h"
+
+#include "tsk_memory.h"
+#include "tsk_string.h"
+#include "tsk_debug.h"
+
+#include <string.h>
+
+/**@ingroup tnet_dns_group
+* Creates new DNS message.
+* @sa tnet_dns_message_create_null.
+*/
+tnet_dns_message_t* tnet_dns_message_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype, tsk_bool_t isquery)
+{
+ return tsk_object_new(tnet_dns_message_def_t, qname, qclass, qtype, isquery);
+}
+
+/**@ingroup tnet_dns_group
+* Creates new DNS message.
+* @sa tnet_dns_message_create.
+*/
+tnet_dns_message_t* tnet_dns_message_create_null()
+{
+ return tnet_dns_message_create(tsk_null, qclass_any, qtype_any, tsk_false);
+}
+
+/**@ingroup tnet_dns_group
+* Creates new DNS response message.
+* @sa tnet_dns_query_create.
+*/
+tnet_dns_response_t* tnet_dns_response_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype)
+{
+ return tnet_dns_message_create(qname, qclass, qtype, tsk_false);
+}
+
+/**@ingroup tnet_dns_group
+* Creates new DNS query message.
+* @sa tnet_dns_response_create.
+*/
+tnet_dns_query_t* tnet_dns_query_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype)
+{
+ return tnet_dns_message_create(qname, qclass, qtype, tsk_true);
+}
+
+/**@ingroup tnet_dns_group
+* Serializes a DNS message in binary data.
+* @param message The DNS message to seriablize.
+* @retval The binary buffer containong the message if succeed. Otherwise, @a tsk_null is returned.
+* @sa tnet_dns_message_deserialize.
+*/
+tsk_buffer_t* tnet_dns_message_serialize(const tnet_dns_message_t *message)
+{
+ tsk_buffer_t* output = tsk_null;
+ uint16_t _2bytes;
+ tsk_list_item_t *item;
+
+ /* Check message validity */
+ if(!message){
+ goto bail;
+ }
+
+ /* Creates empty buffer */
+ output = tsk_buffer_create_null();
+
+ /* ==============================
+ * HEADER
+ */
+ //tsk_buffer_append(output, &(message->Header), sizeof(message->Header));
+
+ /* ID */
+ _2bytes = tnet_ntohs(message->Header.ID);
+ tsk_buffer_append(output, &(_2bytes), 2);
+ /* |QR| Opcode |AA|TC|RD|RA| Z | RCODE | */
+ {
+ uint16_t temp, _2bytes = 0;
+
+ temp = message->Header.QR, temp <<= 15;
+ _2bytes |= temp;
+
+ temp = message->Header.OPCODE, temp <<= 11;
+ _2bytes |= temp;
+
+ temp = message->Header.AA, temp <<= 10;
+ _2bytes |= temp;
+
+ temp = message->Header.TC, temp <<= 9;
+ _2bytes |= temp;
+
+ temp = message->Header.RD, temp <<= 8;
+ _2bytes |= temp;
+
+ temp = message->Header.RA, temp <<= 7;
+ _2bytes |= temp;
+
+ temp = message->Header.Z, temp <<= 4;
+ _2bytes |= temp;
+
+ temp = message->Header.RCODE, temp <<= 4;
+ _2bytes |= temp;
+
+ _2bytes = tnet_ntohs(_2bytes);
+ tsk_buffer_append(output, &(_2bytes), 2);
+ }
+ /* QDCOUNT */
+ _2bytes = tnet_ntohs(message->Header.QDCOUNT);
+ tsk_buffer_append(output, &(_2bytes), 2);
+ /* ANCOUNT */
+ _2bytes = tnet_ntohs(message->Header.ANCOUNT);
+ tsk_buffer_append(output, &(_2bytes), 2);
+ /* NSCOUNT */
+ _2bytes = tnet_ntohs(message->Header.NSCOUNT);
+ tsk_buffer_append(output, &(_2bytes), 2);
+ /* ARCOUNT */
+ _2bytes = tnet_ntohs(message->Header.ARCOUNT);
+ tsk_buffer_append(output, &(_2bytes), 2);
+
+
+ /* ==============================
+ * QUESTION
+ */
+ if(TNET_DNS_MESSAGE_IS_QUERY(message))
+ {
+ /* QNAME */
+ tnet_dns_rr_qname_serialize(message->Question.QNAME, output);
+ /* QTYPE */
+ _2bytes = tnet_ntohs(message->Question.QTYPE);
+ tsk_buffer_append(output, &(_2bytes), 2);
+ /* QCLASS */
+ _2bytes = tnet_ntohs(message->Question.QCLASS);
+ tsk_buffer_append(output, &(_2bytes), 2);
+ }
+
+ /* ==============================
+ * ANSWERS
+ */
+ tsk_list_foreach(item, message->Answers)
+ {
+ tnet_dns_rr_serialize((tnet_dns_rr_t *)item->data, output);
+ }
+
+ /* ==============================
+ * AUTHORITIES
+ */
+ tsk_list_foreach(item, message->Authorities)
+ {
+ tnet_dns_rr_serialize((tnet_dns_rr_t *)item->data, output);
+ }
+
+ /* ==============================
+ * ADDITIONALS
+ */
+ tsk_list_foreach(item, message->Additionals)
+ {
+ tnet_dns_rr_serialize((tnet_dns_rr_t *)item->data, output);
+ }
+
+
+bail:
+ return output;
+}
+
+/**@ingroup tnet_dns_group
+* Deserialize a STUN message from binary data.
+* @param data A pointer to the binary data.
+* @param size The size of the bnary data buffer.
+* @retval @ref tnet_dns_message_t object if succeed or NULL otherwise.
+* @sa @ref tnet_dns_message_serialize.
+*/
+tnet_dns_message_t* tnet_dns_message_deserialize(const uint8_t *data, tsk_size_t size)
+{
+ tnet_dns_message_t *message = 0;
+ uint8_t *dataPtr, *dataEnd, *dataStart;
+ uint16_t i;
+ tsk_size_t offset = 0;
+
+ if(!data || !size){
+ goto bail;
+ }
+
+ dataPtr = (uint8_t*)data;
+ dataStart = dataPtr;
+ dataEnd = (dataStart + size);
+
+ message = tnet_dns_message_create_null();
+
+ /* === HEADER ===*/
+ /* ID */
+ message->Header.ID = tnet_ntohs_2(dataPtr);
+ dataPtr += 2;
+ /* |QR| Opcode |AA|TC|RD|RA| Z | RCODE | */
+ {
+ uint16_t flags = tnet_ntohs_2(dataPtr);
+
+ message->Header.QR = (flags >> 15);
+ message->Header.OPCODE = ((flags >> 11) & 0x000F);
+ message->Header.AA = ((flags >> 10) & 0x0001);
+ message->Header.TC = ((flags >> 9) & 0x0001);
+ message->Header.RD = ((flags >> 8) & 0x0001);
+ message->Header.RA = ((flags >> 7) & 0x0001);
+ message->Header.Z = ((flags >> 4) & 0x0007);
+ message->Header.RCODE = (flags & 0x000F);
+
+ dataPtr += 2;
+ }
+ /* QDCOUNT */
+ message->Header.QDCOUNT = tnet_ntohs_2(dataPtr);
+ dataPtr += 2;
+ /* ANCOUNT */
+ message->Header.ANCOUNT = tnet_ntohs_2(dataPtr);
+ dataPtr += 2;
+ /* NSCOUNT */
+ message->Header.NSCOUNT = tnet_ntohs_2(dataPtr);
+ dataPtr += 2;
+ /* ARCOUNT */
+ message->Header.ARCOUNT = tnet_ntohs_2(dataPtr);
+ dataPtr += 2;
+
+ /* === Queries ===*/
+ offset = (dataPtr - dataStart);
+ for(i=0; i<message->Header.QDCOUNT; i++)
+ {
+ /* Do not need to parse queries in the response ==> silently ignore */
+ char* name = 0;
+ tnet_dns_rr_qname_deserialize(dataStart, &name, &offset); /* QNAME */
+ dataPtr+=offset;
+ dataPtr+=4, offset+=4; /* QTYPE + QCLASS */
+ TSK_FREE(name);
+ }
+ dataPtr = (dataStart + offset); /* TODO: remove ==> obly for debug tests */
+
+ /* === Answers ===*/
+ offset = (dataPtr - dataStart);
+ for(i=0; i<message->Header.ANCOUNT; i++)
+ {
+ tnet_dns_rr_t* rr = tnet_dns_rr_deserialize(dataStart, (dataEnd-dataPtr), &offset);
+ if(rr){
+ if(!message->Answers){
+ message->Answers = tsk_list_create();
+ }
+ /* Push in descending order (useful for NAPTR and SRV records). */
+ tsk_list_push_descending_data(message->Answers, (void**)&rr);
+ }
+ }
+ dataPtr = (dataStart + offset);
+
+ /* === Authorities ===*/
+ offset = (dataPtr - dataStart);
+ for(i=0; i<message->Header.NSCOUNT; i++)
+ {
+ tnet_dns_rr_t* rr = tnet_dns_rr_deserialize(dataStart, (dataEnd-dataPtr), &offset);
+ if(rr){
+ if(!message->Authorities){
+ message->Authorities = tsk_list_create();
+ }
+ tsk_list_push_back_data(message->Authorities, (void**)&rr);
+ }
+ }
+ dataPtr = (dataStart + offset);
+
+ /* === Additionals ===*/
+ offset = (dataPtr - dataStart);
+ for(i=0; i<message->Header.ARCOUNT; i++)
+ {
+ tnet_dns_rr_t* rr = tnet_dns_rr_deserialize(dataStart, (dataEnd-dataPtr), &offset);
+ if(rr){
+ if(!message->Additionals){
+ message->Additionals = tsk_list_create();
+ }
+ tsk_list_push_back_data(message->Additionals, (void**)&rr);
+ }
+ }
+ dataPtr = (dataStart + offset);
+
+
+bail:
+ return message;
+}
+
+//=================================================================================================
+// [[DNS MESSAGE]] object definition
+//
+static tsk_object_t* tnet_dns_message_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_message_t *message = self;
+ if(message){
+ static uint16_t __dnsmessage_unique_id = 0;
+
+ const char* qname = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ tnet_dns_qtype_t qtype = va_arg(*app, tnet_dns_qtype_t);
+ tsk_bool_t isquery = va_arg(*app, tsk_bool_t);
+
+ /* Create random ID. */
+ message->Header.ID = ++__dnsmessage_unique_id;
+
+ /* QR field ==> query (0) - response (1) */
+ message->Header.QR = isquery ? 0 : 1;
+
+ if(isquery){
+ /* QDCOUNT field ==> at least one question */
+ message->Header.QDCOUNT = 1;
+ }
+
+ if(qname){
+ message->Question.QNAME = tsk_strdup(qname);
+ message->Question.QTYPE = qtype;
+ message->Question.QCLASS = qclass;
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_message_dtor(tsk_object_t * self)
+{
+ tnet_dns_message_t *message = self;
+ if(message){
+ TSK_FREE(message->Question.QNAME);
+
+ TSK_OBJECT_SAFE_FREE(message->Answers);
+ TSK_OBJECT_SAFE_FREE(message->Authorities);
+ TSK_OBJECT_SAFE_FREE(message->Additionals);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_message_def_s =
+{
+ sizeof(tnet_dns_message_t),
+ tnet_dns_message_ctor,
+ tnet_dns_message_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_message_def_t = &tnet_dns_message_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_message.h b/tinyNET/src/dns/tnet_dns_message.h
new file mode 100644
index 0000000..a474095
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_message.h
@@ -0,0 +1,209 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_message.h
+ * @brief DNS Message holding RRs (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#ifndef TNET_DNS_MESSAGE_H
+#define TNET_DNS_MESSAGE_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+#include "tsk_buffer.h"
+
+/**@ingroup tnet_dns_group
+* @def TNET_DNS_MESSAGE_IS_RESPONSE
+* Checks whether the STUN message is a response or not(query).
+* @sa TNET_DNS_MESSAGE_IS_QUERY.
+*/
+/**@ingroup tnet_dns_group
+* @def TNET_DNS_MESSAGE_IS_QUERY
+* Checks whether the STUN message is a query or not(response).
+* @sa TNET_DNS_MESSAGE_IS_RESPONSE.
+*/
+
+TNET_BEGIN_DECLS
+
+
+#define TNET_DNS_MESSAGE_IS_RESPONSE(message) ((message) && (message)->Header.QR == 1)
+#define TNET_DNS_MESSAGE_IS_QUERY(message) ((message) && (message)->Header.QR == 0)
+
+/**@ingroup tnet_dns_group
+* @def TNET_DNS_RESPONSE_IS_SUCCESS
+* Checks whether the STUN message is a success response or not(error).
+* @sa TNET_DNS_RESPONSE_IS_ERROR.
+*/
+/**@ingroup tnet_dns_group
+* @def TNET_DNS_RESPONSE_IS_ERROR
+* Checks whether the STUN message is an error response or not(success).
+* @sa TNET_DNS_RESPONSE_IS_SUCCESS.
+*/
+#define TNET_DNS_RESPONSE_IS_SUCCESS(response) ((response) && (response)->Header.RCODE == rcode_noerror)
+#define TNET_DNS_RESPONSE_IS_ERROR(response) !TNET_DNS_RESPONSE_IS_SUCCESS(response)
+
+/**Response codes as per RFC 1035 subclause 4.1.1.
+*/
+typedef enum tnet_dns_rcode_e
+{
+ rcode_noerror = 0,
+ rcode_error_format = 1,
+ rcode_server_failure = 2,
+ rcode_error_name = 3,
+ rcode_notimplemented = 4,
+ rcode_refused = 5
+}
+tnet_dns_rcode_t;
+
+/**OPCODE defining the kind of query as per RFC 1035 subclause 4.1.1.
+*/
+typedef enum tnet_dns_opcode_e
+{
+ opcode_query = 0, /**< 0 a standard query (QUERY) */
+ opcode_iquery = 1, /**< 1 an inverse query (IQUERY) */
+ opcode_status = 2, /**< 2 a server status request (STATUS) */
+}
+tnet_dns_opcode_t;
+
+/** DNS message as per RFC 1035 subclause 4.
+*/
+typedef struct tnet_dns_message_s
+{
+ TSK_DECLARE_OBJECT;
+
+ /* RFC 1035 - 4.1. Format
+ +---------------------+
+ | Header |
+ +---------------------+
+ | Question | the question for the name server
+ +---------------------+
+ | Answer | RRs answering the question
+ +---------------------+
+ | Authority | RRs pointing toward an authority
+ +---------------------+
+ | Additional | RRs holding additional information
+ +---------------------+
+ */
+
+ /* RFC 1035 - 4.1.1. Header section format
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QDCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ANCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | NSCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ARCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ struct
+ {
+ uint16_t ID;
+ unsigned QR:1;
+ unsigned OPCODE:4; /* see @ref tnet_dns_opcode_t */
+ unsigned AA:1;
+ unsigned TC:1;
+ unsigned RD:1;
+ unsigned RA:1;
+ unsigned Z:3;
+ unsigned RCODE:4; /* see @ref tnet_dns_rcode_t */
+ uint16_t QDCOUNT;
+ uint16_t ANCOUNT;
+ uint16_t NSCOUNT;
+ uint16_t ARCOUNT;
+ }
+ Header;
+
+ /* RFc 1035 - 4.1.2. Question section format
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / QNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QTYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QCLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ struct
+ {
+ /** RFC 1035 - 4.1.2. Question section format
+ a domain name represented as a sequence of labels, where
+ each label consists of a length octet followed by that
+ number of octets. The domain name terminates with the
+ zero length octet for the null label of the root. Note
+ that this field may be an odd number of octets; no
+ padding is used.*/
+ void* QNAME;
+ /** RFC 1035 - 4.1.2. Question section format
+ a two octet code which specifies the type of the query.
+ The values for this field include all codes valid for a
+ TYPE field, together with some more general codes which
+ can match more than one type of RR.*/
+ tnet_dns_qtype_t QTYPE;
+ /* RFC 1035 - 4.1.2. Question section format
+ a two octet code that specifies the class of the query.
+ For example, the QCLASS field is IN for the Internet.
+ */
+ tnet_dns_qclass_t QCLASS;
+ }
+ Question;
+
+ tnet_dns_rrs_L_t *Answers; /**< Filtered answers by priority. */
+ tnet_dns_rrs_L_t *Authorities;
+ tnet_dns_rrs_L_t *Additionals;
+}
+tnet_dns_message_t;
+
+typedef tsk_list_t tnet_dns_messages_L_t; /**< List of @ref tnet_dns_message_t elements. */
+typedef tnet_dns_message_t tnet_dns_query_t; /**< DNS Query messsage. */
+typedef tnet_dns_message_t tnet_dns_response_t; /**< DNS response message. */
+
+tsk_buffer_t* tnet_dns_message_serialize(const tnet_dns_message_t *message);
+tnet_dns_message_t* tnet_dns_message_deserialize(const uint8_t *data, tsk_size_t size);
+
+
+tnet_dns_message_t* tnet_dns_message_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype, tsk_bool_t isquery);
+tnet_dns_message_t* tnet_dns_message_create_null();
+tnet_dns_response_t* tnet_dns_response_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype);
+tnet_dns_query_t* tnet_dns_query_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_message_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_MESSAGE_H */
+
+
diff --git a/tinyNET/src/dns/tnet_dns_mx.c b/tinyNET/src/dns/tnet_dns_mx.c
new file mode 100644
index 0000000..8537af7
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_mx.c
@@ -0,0 +1,99 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_mx.c
+ * @brief DNS Mail eXchange record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_mx.h"
+
+#include "../tnet_types.h"
+#include "../tnet_endianness.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+
+/** Creates new DNS MX Resource Record.
+*/
+tnet_dns_mx_t* tnet_dns_mx_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_mx_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+//=================================================================================================
+// [[DNS MX]] object definition
+//
+static tsk_object_t* tnet_dns_mx_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_mx_t *mx = self;
+ if(mx){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(mx), qtype_mx, qclass);
+ TNET_DNS_RR(mx)->name = tsk_strdup(name);
+ TNET_DNS_RR(mx)->rdlength = rdlength;
+ TNET_DNS_RR(mx)->ttl = ttl;
+
+ if(rdlength){
+ // ==> DESERIALIZATION
+ /* PREFERENCE */
+ mx->preference = tnet_ntohs_2(((uint8_t*)data) + offset);
+ offset += 2;
+ /* EXCHANGE */
+ tnet_dns_rr_qname_deserialize(data, &(mx->exchange), &offset);
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_mx_dtor(tsk_object_t * self)
+{
+ tnet_dns_mx_t *mx = self;
+ if(mx){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(mx));
+
+ TSK_FREE(mx->exchange);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_mx_def_s =
+{
+ sizeof(tnet_dns_mx_t),
+ tnet_dns_mx_ctor,
+ tnet_dns_mx_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_mx_def_t = &tnet_dns_mx_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_mx.h b/tinyNET/src/dns/tnet_dns_mx.h
new file mode 100644
index 0000000..1bc4f66
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_mx.h
@@ -0,0 +1,66 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_mx.h
+ * @brief DNS Mail eXchange record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_MX_H
+#define TNET_DNS_RR_MX_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+
+TNET_BEGIN_DECLS
+
+
+/** DNS MX Resource Record
+*/
+typedef struct tnet_dns_mx_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ /* RFC 1035 - 3.3.9. MX RDATA format
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PREFERENCE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / EXCHANGE /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ uint16_t preference;
+ char* exchange;
+}
+tnet_dns_mx_t;
+
+tnet_dns_mx_t* tnet_dns_mx_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_mx_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_MX_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_naptr.c b/tinyNET/src/dns/tnet_dns_naptr.c
new file mode 100644
index 0000000..4152734
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_naptr.c
@@ -0,0 +1,146 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_naptr.c
+ * @brief DNS Naming Authority Pointer - RR - (RFC 3403).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_naptr.h"
+
+
+#include "../tnet_types.h"
+#include "./tnet_endianness.h"
+
+#include "tsk_memory.h"
+#include "tsk_string.h"
+
+/** Creates new DNS NAPTR Resource Record.
+*/
+tnet_dns_naptr_t* tnet_dns_naptr_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_naptr_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+
+
+//=================================================================================================
+// [[DNS NAPTR]] object definition
+//
+static tsk_object_t* tnet_dns_naptr_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_naptr_t *naptr = self;
+ if(naptr){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(naptr), qtype_naptr, qclass);
+ TNET_DNS_RR(naptr)->name = tsk_strdup(name);
+ TNET_DNS_RR(naptr)->rdlength = rdlength;
+ TNET_DNS_RR(naptr)->ttl = ttl;
+
+ if(rdlength){
+ // ==> DESERIALIZATION
+ /* ORDER */
+ naptr->order = tnet_ntohs_2(((uint8_t*)data) + offset);
+ offset += 2;
+ /* PREFERENCE */
+ naptr->preference = tnet_ntohs_2(((uint8_t*)data) + offset);
+ offset += 2;
+ /* FLAGS */
+ tnet_dns_rr_charstring_deserialize(data, &(naptr->flags), &offset);
+ /* SERVICES */
+ tnet_dns_rr_charstring_deserialize(data, &(naptr->services), &offset);
+ /* REGEXP */
+ tnet_dns_rr_charstring_deserialize(data, &(naptr->regexp), &offset);
+ /* REPLACEMENT */
+ tnet_dns_rr_qname_deserialize(data, &(naptr->replacement), &offset);
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_naptr_dtor(tsk_object_t * self)
+{
+ tnet_dns_naptr_t *naptr = self;
+ if(naptr){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(naptr));
+
+ TSK_FREE(naptr->flags);
+ TSK_FREE(naptr->services);
+ TSK_FREE(naptr->regexp);
+ TSK_FREE(naptr->replacement);
+ }
+ return self;
+}
+
+static int tnet_dns_naptr_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
+{
+ const tnet_dns_rr_t* rr1 = obj1;
+ const tnet_dns_rr_t* rr2 = obj2;
+
+ if(rr1 && rr2 && (rr1->qtype==qtype_naptr) && (rr2->qtype==qtype_naptr)){
+ const tnet_dns_naptr_t* naptr1 = (tnet_dns_naptr_t*)rr1;
+ const tnet_dns_naptr_t* naptr2 = (tnet_dns_naptr_t*)rr2;
+
+ /* Compare orders. */
+ if(naptr1->order < naptr2->order){ /* Lowest order is tried first. */
+ return 1;
+ }
+ else if(naptr1->order > naptr2->order){
+ return -1;
+ }
+
+ /* Compare preference */
+ if(naptr1->order < naptr2->order){ /* Lowest preference is tried first. */
+ return 1;
+ }
+ else if(naptr1->order > naptr2->order){
+ return -1;
+ }
+
+ return 0;
+ }
+ else{
+ return -1;
+ }
+}
+
+static const tsk_object_def_t tnet_dns_naptr_def_s =
+{
+ sizeof(tnet_dns_naptr_t),
+ tnet_dns_naptr_ctor,
+ tnet_dns_naptr_dtor,
+ tnet_dns_naptr_cmp,
+};
+const tsk_object_def_t *tnet_dns_naptr_def_t = &tnet_dns_naptr_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_naptr.h b/tinyNET/src/dns/tnet_dns_naptr.h
new file mode 100644
index 0000000..b601d49
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_naptr.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_naptr.h
+ * @brief DNS Naming Authority Pointer - RR - (RFC 3403).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_NAPTR_H
+#define TNET_DNS_RR_NAPTR_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+TNET_BEGIN_DECLS
+
+/** DNS NAPTR Resource Record
+*/
+typedef struct tnet_dns_naptr_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ /* RFC 3403 - 4.1 Packet Format
+
+ The packet format for the NAPTR record is as follows
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ORDER |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PREFERENCE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / FLAGS /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / SERVICES /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / REGEXP /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / REPLACEMENT /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ <character-string> and <domain-name> as used here are defined in RFC 1035.
+ */
+ uint16_t order;
+ uint16_t preference;
+ char* flags;
+ char* services;
+ char* regexp;
+ char* replacement;
+}
+tnet_dns_naptr_t;
+
+TINYNET_API tnet_dns_naptr_t* tnet_dns_naptr_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_naptr_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_NAPTR_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_ns.c b/tinyNET/src/dns/tnet_dns_ns.c
new file mode 100644
index 0000000..9453cec
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_ns.c
@@ -0,0 +1,96 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_ns.c
+ * @brief DNS Name Server record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_ns.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+
+#include "tnet_dns_rr.h"
+
+/** Creates new DNS NS Resource Record.
+*/
+tnet_dns_ns_t* tnet_dns_ns_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_ns_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+//=================================================================================================
+// [[DNS NS]] object definition
+//
+static tsk_object_t* tnet_dns_ns_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_ns_t *ns = self;
+ if(ns){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(ns), qtype_ns, qclass);
+ TNET_DNS_RR(ns)->name = tsk_strdup(name);
+ TNET_DNS_RR(ns)->rdlength = rdlength;
+ TNET_DNS_RR(ns)->ttl = ttl;
+
+ if(rdlength){
+ // ==> DESERIALIZATION
+ /* NSDNAME */
+ tnet_dns_rr_qname_deserialize(data, &(ns->nsdname), &offset);
+ }
+
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_ns_dtor(tsk_object_t * self)
+{
+ tnet_dns_ns_t *ns = self;
+ if(ns){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(ns));
+
+ TSK_FREE(ns->nsdname);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_ns_def_s =
+{
+ sizeof(tnet_dns_ns_t),
+ tnet_dns_ns_ctor,
+ tnet_dns_ns_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_ns_def_t = &tnet_dns_ns_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_ns.h b/tinyNET/src/dns/tnet_dns_ns.h
new file mode 100644
index 0000000..66c4ff8
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_ns.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_ns.h
+ * @brief DNS Name Server record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_NS_H
+#define TNET_DNS_RR_NS_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+
+TNET_BEGIN_DECLS
+
+
+/** DNS NS Resource Record.
+*/
+typedef struct tnet_dns_ns_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ /* RFC 1035 - 3.3.11. NS RDATA format
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / NSDNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ char* nsdname;
+}
+tnet_dns_ns_t;
+
+TINYNET_API tnet_dns_ns_t* tnet_dns_ns_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_ns_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_NS_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_opt.c b/tinyNET/src/dns/tnet_dns_opt.c
new file mode 100644
index 0000000..f5e2c57
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_opt.c
@@ -0,0 +1,91 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_opt.c
+ * @brief DNS OPT pseudo-RR (RFC 2671).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_opt.h"
+
+
+
+/** Creates new DNS OPT Resource Record.
+*/
+tnet_dns_opt_t* tnet_dns_opt_create(tsk_size_t payload_size)
+{
+ return tsk_object_new(tnet_dns_opt_def_t, payload_size);
+}
+
+
+
+
+
+
+
+
+
+//=================================================================================================
+// [[DNS OPT]] object definition
+//
+static tsk_object_t* tnet_dns_opt_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_opt_t *rr_opt = self;
+ if(rr_opt){
+ uint16_t payload_size = (uint16_t)va_arg(*app, tsk_size_t);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(rr_opt), qtype_opt, qclass_any);
+
+ /*
+ NAME domain name empty (root domain)
+ TYPE u_int16_t OPT
+ CLASS u_int16_t sender's UDP payload size
+ TTL u_int32_t extended RCODE and flags
+ RDLEN u_int16_t describes RDATA
+ RDATA octet stream {attribute,value} pairs
+
+ */
+ TNET_DNS_RR(rr_opt)->qclass = payload_size;
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_opt_dtor(tsk_object_t * self)
+{
+ tnet_dns_opt_t *rr_opt = self;
+ if(rr_opt){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(rr_opt));
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_opt_def_s =
+{
+ sizeof(tnet_dns_opt_t),
+ tnet_dns_opt_ctor,
+ tnet_dns_opt_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_opt_def_t = &tnet_dns_opt_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_opt.h b/tinyNET/src/dns/tnet_dns_opt.h
new file mode 100644
index 0000000..8c0407b
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_opt.h
@@ -0,0 +1,54 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_opt.h
+ * @brief DNS OPT pseudo-RR (RFC 2671).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_OPT_H
+#define TNET_DNS_RR_OPT_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+
+TNET_BEGIN_DECLS
+
+/** DNS OPT Resource Record
+*/
+typedef struct tnet_dns_opt_s
+{
+ TNET_DECLARE_DNS_RR;
+}
+tnet_dns_opt_t;
+
+tnet_dns_opt_t* tnet_dns_opt_create(tsk_size_t payload_size);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_opt_def_t;
+
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_OPT_H */
diff --git a/tinyNET/src/dns/tnet_dns_ptr.c b/tinyNET/src/dns/tnet_dns_ptr.c
new file mode 100644
index 0000000..a629b91
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_ptr.c
@@ -0,0 +1,97 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_ptr.c
+ * @brief DNS Pointer record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_ptr.h"
+
+#include "../tnet_types.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+
+/** Creates new DNS PTR Resource Record.
+*/
+
+
+tnet_dns_ptr_t* tnet_dns_ptr_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void*data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_ptr_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+//=================================================================================================
+// [[DNS PTR]] object definition
+//
+static tsk_object_t* tnet_dns_ptr_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_ptr_t *ptr = self;
+ if(ptr){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(ptr), qtype_ptr, qclass);
+ TNET_DNS_RR(ptr)->name = tsk_strdup(name);
+ TNET_DNS_RR(ptr)->rdlength = rdlength;
+ TNET_DNS_RR(ptr)->ttl = ttl;
+
+ if(rdlength){
+ // ==> DESERIALIZATION
+ /* PTRDNAME */
+ tnet_dns_rr_qname_deserialize(data, &(ptr->ptrdname), &offset);
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_ptr_dtor(tsk_object_t * self)
+{
+ tnet_dns_ptr_t *ptr = self;
+ if(ptr){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(ptr));
+
+ TSK_FREE(ptr->ptrdname);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_ptr_def_s =
+{
+ sizeof(tnet_dns_ptr_t),
+ tnet_dns_ptr_ctor,
+ tnet_dns_ptr_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_ptr_def_t = &tnet_dns_ptr_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_ptr.h b/tinyNET/src/dns/tnet_dns_ptr.h
new file mode 100644
index 0000000..19e1882
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_ptr.h
@@ -0,0 +1,61 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_ptr.h
+ * @brief DNS Pointer record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_PTR_H
+#define TNET_DNS_RR_PTR_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+TNET_BEGIN_DECLS
+
+
+/** DNS PTR Resource Record
+*/
+typedef struct tnet_dns_ptr_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ /* RFC 1035 - 3.3.12. PTR RDATA format
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / PTRDNAME /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ char* ptrdname;
+}
+tnet_dns_ptr_t;
+
+tnet_dns_ptr_t* tnet_dns_ptr_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void*data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_ptr_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_PTR_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_regexp.c b/tinyNET/src/dns/tnet_dns_regexp.c
new file mode 100644
index 0000000..e0e60d1
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_regexp.c
@@ -0,0 +1,508 @@
+
+/* #line 1 "./ragel/tnet_dns_regexp.rl" */
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_regexp.h
+ * @brief DNS Regex parser for NAPTR RR.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_regexp.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_ragel_state.h"
+#include "tsk_debug.h"
+
+#include <string.h>
+
+/* === Ragel state machine === */
+
+/* #line 77 "./ragel/tnet_dns_regexp.rl" */
+
+
+/**
+* Apply @a regexp to @a e164num.
+* @param e164num Original E.164 number supplied by the user (only digits or '+' are accepted).
+* @param regexp A <character-string> containing a substitution expression that is
+* applied to the original string held by the client in order to
+* construct the next domain name to lookup. Example: "!^.*$!sip:bob@doubango.org!i".
+* @retval The final Internet address. It's up to the caller to free the string.
+*/
+char* tnet_dns_regex_parse(const char* e164num, const char* regexp)
+{
+ char* ret = tsk_null;
+ char* prefix = tsk_null;
+ const char* tag_start;
+ tsk_size_t e164len;
+
+ // Ragel
+ int cs = 0;
+ const char *p = tag_start = regexp;
+ const char *pe;
+ const char *eof;
+
+
+/* #line 68 "./src/dns/tnet_dns_regexp.c" */
+static const char _tdns_machine_regexp_actions[] = {
+ 0, 1, 0, 1, 1, 1, 2, 2,
+ 0, 1, 2, 0, 2, 2, 2, 0,
+ 2, 3, 0, 3, 3, 0, 2
+};
+
+static const char _tdns_machine_regexp_key_offsets[] = {
+ 0, 0, 1, 2, 5, 6, 7, 8,
+ 9, 10, 11, 13, 15, 17, 19, 21,
+ 23, 25, 26, 27
+};
+
+static const char _tdns_machine_regexp_trans_keys[] = {
+ 33, 94, 40, 46, 92, 40, 46, 42,
+ 41, 36, 33, 33, 92, 33, 92, 48,
+ 57, 33, 92, 33, 92, 40, 42, 36,
+ 40, 40, 105, 0
+};
+
+static const char _tdns_machine_regexp_single_lengths[] = {
+ 0, 1, 1, 3, 1, 1, 1, 1,
+ 1, 1, 2, 2, 0, 2, 2, 2,
+ 2, 1, 1, 0
+};
+
+static const char _tdns_machine_regexp_range_lengths[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+static const char _tdns_machine_regexp_index_offsets[] = {
+ 0, 0, 2, 4, 8, 10, 12, 14,
+ 16, 18, 20, 23, 26, 28, 31, 34,
+ 37, 40, 42, 44
+};
+
+static const char _tdns_machine_regexp_trans_targs[] = {
+ 2, 0, 3, 0, 5, 15, 17, 4,
+ 5, 4, 6, 0, 7, 0, 8, 0,
+ 9, 0, 10, 0, 18, 12, 11, 18,
+ 12, 11, 13, 0, 18, 0, 14, 18,
+ 0, 14, 5, 16, 4, 9, 5, 4,
+ 5, 4, 19, 0, 0, 0
+};
+
+static const char _tdns_machine_regexp_trans_actions[] = {
+ 0, 0, 0, 0, 7, 1, 0, 1,
+ 3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 10, 10, 10, 13,
+ 13, 13, 0, 0, 19, 0, 16, 5,
+ 0, 0, 3, 0, 0, 0, 3, 0,
+ 7, 1, 0, 0, 0, 0
+};
+
+static const int tdns_machine_regexp_start = 1;
+static const int tdns_machine_regexp_first_final = 18;
+static const int tdns_machine_regexp_error = 0;
+
+static const int tdns_machine_regexp_en_main = 1;
+
+
+/* #line 101 "./ragel/tnet_dns_regexp.rl" */
+
+ if(!e164num){
+ goto bail;
+ }
+
+ if(!regexp){
+ ret = tsk_strdup(e164num);
+ goto bail;
+ }
+
+ e164len = tsk_strlen(e164num);
+ pe = p + tsk_strlen(regexp);
+ eof = pe;
+
+
+/* #line 147 "./src/dns/tnet_dns_regexp.c" */
+ {
+ cs = tdns_machine_regexp_start;
+ }
+
+/* #line 116 "./ragel/tnet_dns_regexp.rl" */
+
+/* #line 154 "./src/dns/tnet_dns_regexp.c" */
+ {
+ int _klen;
+ unsigned int _trans;
+ const char *_acts;
+ unsigned int _nacts;
+ const char *_keys;
+
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _keys = _tdns_machine_regexp_trans_keys + _tdns_machine_regexp_key_offsets[cs];
+ _trans = _tdns_machine_regexp_index_offsets[cs];
+
+ _klen = _tdns_machine_regexp_single_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + _klen - 1;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + ((_upper-_lower) >> 1);
+ if ( (*p) < *_mid )
+ _upper = _mid - 1;
+ else if ( (*p) > *_mid )
+ _lower = _mid + 1;
+ else {
+ _trans += (_mid - _keys);
+ goto _match;
+ }
+ }
+ _keys += _klen;
+ _trans += _klen;
+ }
+
+ _klen = _tdns_machine_regexp_range_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + (_klen<<1) - 2;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+ if ( (*p) < _mid[0] )
+ _upper = _mid - 2;
+ else if ( (*p) > _mid[1] )
+ _lower = _mid + 2;
+ else {
+ _trans += ((_mid - _keys)>>1);
+ goto _match;
+ }
+ }
+ _trans += _klen;
+ }
+
+_match:
+ cs = _tdns_machine_regexp_trans_targs[_trans];
+
+ if ( _tdns_machine_regexp_trans_actions[_trans] == 0 )
+ goto _again;
+
+ _acts = _tdns_machine_regexp_actions + _tdns_machine_regexp_trans_actions[_trans];
+ _nacts = (unsigned int) *_acts++;
+ while ( _nacts-- > 0 )
+ {
+ switch ( *_acts++ )
+ {
+ case 0:
+/* #line 42 "./ragel/tnet_dns_regexp.rl" */
+ {
+ tag_start = p;
+ }
+ break;
+ case 1:
+/* #line 46 "./ragel/tnet_dns_regexp.rl" */
+ {
+ TSK_PARSER_SET_STRING(prefix);
+ }
+ break;
+ case 2:
+/* #line 50 "./ragel/tnet_dns_regexp.rl" */
+ {
+ int len = (int)(p - tag_start);
+ if(len){
+ tsk_strncat(&ret, tag_start, len);
+ }
+ }
+ break;
+ case 3:
+/* #line 57 "./ragel/tnet_dns_regexp.rl" */
+ {
+ if(prefix){
+ int prefixlen = tsk_strlen(prefix);
+ tsk_strncat(&ret, e164num + prefixlen, (e164len - prefixlen));
+ }
+ }
+ break;
+/* #line 257 "./src/dns/tnet_dns_regexp.c" */
+ }
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ _out: {}
+ }
+
+/* #line 117 "./ragel/tnet_dns_regexp.rl" */
+
+ if( cs <
+/* #line 273 "./src/dns/tnet_dns_regexp.c" */
+18
+/* #line 118 "./ragel/tnet_dns_regexp.rl" */
+ ){
+ TSK_DEBUG_ERROR("regexp substitition failed.");
+ TSK_FREE(ret);
+ }
+
+bail:
+ TSK_FREE(prefix);
+
+ return ret;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+///*
+//* Copyright (C) 2009-2010 Mamadou Diop.
+//*
+//* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+//*
+//* This file is part of Open Source Doubango Framework.
+//*
+//* DOUBANGO 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 of the License, or
+//* (at your option) any later version.
+//*
+//* DOUBANGO 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 DOUBANGO.
+//*
+//*/
+///**@file tnet_dns_regexp.h
+// * @brief DNS Regex parser for NAPTR RR.
+// *
+// * @author Mamadou Diop <diopmamadou(at)doubango.org>
+// *
+// * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+// */
+//#include "tnet_dns_regexp.h"
+//
+//#include "tsk_debug.h"
+//#include "tsk_memory.h"
+//#include "tsk_string.h"
+//#include "tsk_list.h"
+//
+//#include <string.h>
+//
+//const tsk_object_def_t *group_def_t;
+//typedef tsk_list_t groups_L_t;
+//
+//#define CREATE_GROUP(id) tsk_object_new(group_def_t, (int)id)
+//typedef struct group_s
+//{
+// TSK_DECLARE_OBJECT;
+//
+// int id;
+// tsk_size_t start;
+// tsk_size_t end;
+//}
+//group_t;
+//
+///* === Ragel state machine === */
+//%%{
+// machine tdns_machine_regexp;
+//
+// action tag{
+// tag_start = p;
+// }
+//
+// action inc_index{
+// index++;
+// TSK_DEBUG_INFO("inc_index %d", index);
+// }
+//
+// action create_group{
+// if(curr_group){
+// TSK_OBJECT_SAFE_FREE(curr_group);
+// }
+// curr_group = CREATE_GROUP(++group_id);
+// curr_group->start = index;
+// TSK_DEBUG_INFO("Create groupe");
+// }
+//
+// action add_group{
+// curr_group->end = index;
+// tsk_list_push_back_data(groups, (void**)&curr_group);
+// TSK_DEBUG_INFO("Create groupe");
+// }
+//
+// # http://www.itu.int/itudoc/itu-t/workshop/enum/012_pp7.ppt
+// # The format is like this: !<regexp>!<string>!
+// # * 1. Match <regexp> on the original E.164 number
+// # * 2. Apply rewrite rule <string>
+// # * \n in <string> is replaced with group number 'n' in <regexp>
+// #
+//
+// # Match beginning
+// m_begin = "^" any* $inc_index;
+//
+// # Match end
+// m_end = "$";
+//
+// # Math any character
+// m_any_c = ".";
+//
+// # Match any number of any character
+// m_any_string = ".*" | ".+";
+//
+// # Grouping
+// group_n = "\\" digit+;
+// group_begin = "(" >create_group;
+// group_end = ")" >add_group;
+// group = group_begin<: any* :>group_end;
+//
+// # Escaped char
+// escaped_char = "\\" alpha;
+//
+// regexp =
+// m_begin<:
+// m_any_c | m_any_string | group
+// :>m_end;
+//
+// string = any*;
+//
+// main := "!"<: regexp :> "!" <: string :> "!";
+//}%%
+//
+///**
+//* Apply @a regexp to @a e164num.
+//* @param e164num Original E.164 number supplied by the user (only digits or '+' are accepted).
+//* @param regexp A <character-string> containing a substitution expression that is
+//* applied to the original string held by the client in order to
+//* construct the next domain name to lookup. Example: "!^.*$!sip:bob@doubango.org!i".
+//* @retval The final Internet address. It's up to the caller to free the string.
+//*/
+//char* tnet_dns_regex_parse(const char* e164num, const char* regexp)
+//{
+// char* ret = tsk_null;
+// groups_L_t* groups = tsk_list_create();
+// group_t* curr_group = tsk_null;
+// tsk_size_t index = 0;
+// int group_id = 0;
+//
+// // Ragel
+// int cs = 0;
+// const char *p = regexp;
+// const char *pe;
+// const char *eof;
+//
+// %%write data;
+//
+// if(!e164num){
+// goto bail;
+// }
+//
+// if(!regexp){
+// ret = tsk_strdup(e164num);
+// goto bail;
+// }
+//
+// pe = p + tsk_strlen(regexp);
+// eof = pe;
+//
+// %%write init;
+// %%write exec;
+//
+// if( cs < %%{ write first_final; }%% ){
+// TSK_DEBUG_ERROR("regexp substitition failed.");
+// TSK_FREE(ret);
+// }
+//
+//bail:
+// TSK_OBJECT_SAFE_FREE(groups);
+// if(curr_group){
+// TSK_OBJECT_SAFE_FREE(curr_group);
+// }
+//
+// return ret;
+//}
+//
+////=================================================================================================
+//// String object definition
+////
+//static tsk_object_t* group_create(tsk_object_t * self, va_list * app)
+//{
+// group_t *g = self;
+// if(g){
+// g->id = va_arg(*app, int);
+// }
+// return self;
+//}
+//
+//static tsk_object_t* group_destroy(tsk_object_t * self)
+//{
+// group_t *g = self;
+// if(g){
+// }
+//
+// return self;
+//}
+//
+//static int group_cmp(const tsk_object_t *_g1, const tsk_object_t *_g2)
+//{
+// const group_t *g1 = _g1;
+// const group_t *g2 = _g2;
+//
+// if(g1 && g22){
+// return (g1->id - g2->id);
+// }
+// else if(!g1 && !g2) return 0;
+// else return -1;
+//}
+//
+//static const tsk_object_def_t group_def_s =
+//{
+// sizeof(group_t),
+// group_create,
+// group_destroy,
+// group_cmp,
+//};
+//const tsk_object_def_t *group_def_t = &group_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_regexp.h b/tinyNET/src/dns/tnet_dns_regexp.h
new file mode 100644
index 0000000..371cc27
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_regexp.h
@@ -0,0 +1,41 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_regexp.h
+ * @brief DNS Regexp parser for NAPTR RR.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_REGEX_H
+#define TNET_DNS_REGEX_H
+
+#include "tinynet_config.h"
+
+TNET_BEGIN_DECLS
+
+TINYNET_API char* tnet_dns_regex_parse(const char* e164num, const char* regexp);
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_REGEX_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_resolvconf.c b/tinyNET/src/dns/tnet_dns_resolvconf.c
new file mode 100644
index 0000000..887ecfc
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_resolvconf.c
@@ -0,0 +1,301 @@
+
+/* #line 1 "./ragel/tnet_dns_resolvconf.rl" */
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_resolvconf.c
+ * @brief Parser for "/etc/resolv.conf" file to retrive DNS servers.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_resolvconf.h"
+
+#include "tnet_utils.h"
+
+#include "dns/tnet_dns.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_ragel_state.h"
+#include "tsk_debug.h"
+
+#include <string.h>
+
+
+/* === Ragel state machine === */
+
+/* #line 80 "./ragel/tnet_dns_resolvconf.rl" */
+
+
+/** Gets list of DNS servers from a conf file.
+* @param path Path of the conf file from which to retrieve the DNS servers.
+* should be @a "/etc/resolv.conf". You can adjust the value by modifying @ref TNET_RESOLV_CONF_PATH.<br>
+* If you are using <b>Android</b> and the resolv.conf file is missing, then run the following line in a command window: <br>
+* <i>ln -s /private/var/run/resolv.conf /etc/resolv.conf</i><br> If this fails, then try to manually add the file.
+* @retval List of DNS servers.
+*/
+tnet_addresses_L_t * tnet_dns_resolvconf_parse(const char* path)
+{
+ tnet_addresses_L_t* servers = tsk_null;
+ tnet_ip_t ip;
+ const char* fullpath = path;
+ const char* tag_start;
+ FILE* fd;
+ char buf[4092];
+
+ // Ragel
+ int cs = 0;
+ const char *p;
+ const char *pe;
+ const char *eof;
+
+
+/* #line 74 "./src/dns/tnet_dns_resolvconf.c" */
+static const char _tdns_machine_resolvconf_actions[] = {
+ 0, 1, 0, 1, 1
+};
+
+static const char _tdns_machine_resolvconf_key_offsets[] = {
+ 0, 6, 7, 8, 11, 14, 14, 20,
+ 22, 25, 28, 31, 34, 37, 40, 43,
+ 46, 49, 50, 51, 54
+};
+
+static const char _tdns_machine_resolvconf_trans_keys[] = {
+ 10, 13, 32, 35, 78, 110, 32, 32,
+ 10, 13, 32, 10, 13, 32, 10, 13,
+ 32, 35, 78, 110, 10, 13, 32, 65,
+ 97, 32, 77, 109, 32, 69, 101, 32,
+ 83, 115, 32, 69, 101, 32, 82, 114,
+ 32, 86, 118, 32, 69, 101, 32, 82,
+ 114, 32, 32, 10, 13, 32, 32, 35,
+ 78, 110, 0
+};
+
+static const char _tdns_machine_resolvconf_single_lengths[] = {
+ 6, 1, 1, 3, 3, 0, 6, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 1, 1, 3, 4
+};
+
+static const char _tdns_machine_resolvconf_range_lengths[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0
+};
+
+static const char _tdns_machine_resolvconf_index_offsets[] = {
+ 0, 7, 9, 11, 15, 19, 20, 27,
+ 30, 34, 38, 42, 46, 50, 54, 58,
+ 62, 66, 68, 70, 74
+};
+
+static const char _tdns_machine_resolvconf_indicies[] = {
+ 1, 1, 2, 3, 4, 4, 0, 5,
+ 0, 5, 6, 7, 7, 8, 6, 7,
+ 7, 8, 9, 9, 1, 1, 5, 3,
+ 4, 4, 0, 7, 7, 3, 5, 10,
+ 10, 0, 5, 11, 11, 0, 5, 12,
+ 12, 0, 5, 13, 13, 0, 5, 14,
+ 14, 0, 5, 15, 15, 0, 5, 16,
+ 16, 0, 5, 17, 17, 0, 5, 18,
+ 18, 0, 19, 0, 19, 20, 22, 22,
+ 23, 21, 2, 3, 4, 4, 0, 0
+};
+
+static const char _tdns_machine_resolvconf_trans_targs[] = {
+ 1, 6, 20, 7, 8, 2, 3, 0,
+ 4, 5, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 19, 0, 4
+};
+
+static const char _tdns_machine_resolvconf_trans_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 3, 3
+};
+
+static const int tdns_machine_resolvconf_start = 0;
+static const int tdns_machine_resolvconf_first_final = 0;
+static const int tdns_machine_resolvconf_error = -1;
+
+static const int tdns_machine_resolvconf_en_main = 0;
+
+
+/* #line 105 "./ragel/tnet_dns_resolvconf.rl" */
+
+ if(tsk_strnullORempty(fullpath)){
+ fullpath = TNET_RESOLV_CONF_PATH;
+ }
+
+ /* Open the file and read all data */
+ if((fd = fopen(fullpath, "r"))){
+ int len = fread(buf, sizeof(uint8_t), sizeof(buf)-2, fd);
+ p = &buf[0];
+ pe = p + len + 1/*hack*/;
+ eof = pe;
+ fclose(fd);
+
+ buf[len] = '\n'; // hack to have perfect lines
+
+ servers = tsk_list_create();
+ }
+ else{
+#if ANDROID
+ TSK_DEBUG_INFO("Failed to open [%s]. But don't panic, we have detected that you are using Google Android System.\n"
+ "You should look at the Progammer's Guide for more information.\n If you are not using DNS functions, don't worry about this warning.",
+ fullpath);
+#else
+ TSK_DEBUG_ERROR("Failed to open %s.", fullpath);
+#endif
+ goto bail;
+ }
+
+
+/* #line 176 "./src/dns/tnet_dns_resolvconf.c" */
+ {
+ cs = tdns_machine_resolvconf_start;
+ }
+
+/* #line 134 "./ragel/tnet_dns_resolvconf.rl" */
+
+/* #line 183 "./src/dns/tnet_dns_resolvconf.c" */
+ {
+ int _klen;
+ unsigned int _trans;
+ const char *_acts;
+ unsigned int _nacts;
+ const char *_keys;
+
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ _keys = _tdns_machine_resolvconf_trans_keys + _tdns_machine_resolvconf_key_offsets[cs];
+ _trans = _tdns_machine_resolvconf_index_offsets[cs];
+
+ _klen = _tdns_machine_resolvconf_single_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + _klen - 1;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + ((_upper-_lower) >> 1);
+ if ( (*p) < *_mid )
+ _upper = _mid - 1;
+ else if ( (*p) > *_mid )
+ _lower = _mid + 1;
+ else {
+ _trans += (_mid - _keys);
+ goto _match;
+ }
+ }
+ _keys += _klen;
+ _trans += _klen;
+ }
+
+ _klen = _tdns_machine_resolvconf_range_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + (_klen<<1) - 2;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+ if ( (*p) < _mid[0] )
+ _upper = _mid - 2;
+ else if ( (*p) > _mid[1] )
+ _lower = _mid + 2;
+ else {
+ _trans += ((_mid - _keys)>>1);
+ goto _match;
+ }
+ }
+ _trans += _klen;
+ }
+
+_match:
+ _trans = _tdns_machine_resolvconf_indicies[_trans];
+ cs = _tdns_machine_resolvconf_trans_targs[_trans];
+
+ if ( _tdns_machine_resolvconf_trans_actions[_trans] == 0 )
+ goto _again;
+
+ _acts = _tdns_machine_resolvconf_actions + _tdns_machine_resolvconf_trans_actions[_trans];
+ _nacts = (unsigned int) *_acts++;
+ while ( _nacts-- > 0 )
+ {
+ switch ( *_acts++ )
+ {
+ case 0:
+/* #line 47 "./ragel/tnet_dns_resolvconf.rl" */
+ {
+ tag_start = p;
+ }
+ break;
+ case 1:
+/* #line 51 "./ragel/tnet_dns_resolvconf.rl" */
+ {
+ int len = (int)(p - tag_start);
+ if(len && len<=sizeof(ip)){
+ tnet_address_t *address;
+ memset(ip, '\0', sizeof(ip));
+ memcpy(ip, tag_start, len);
+
+ address = tnet_address_create(ip);
+ address->family = tnet_get_family(ip, TNET_DNS_SERVER_PORT_DEFAULT);
+ address->dnsserver = 1;
+ tsk_list_push_ascending_data(servers, (void**)&address);
+ }
+ }
+ break;
+/* #line 277 "./src/dns/tnet_dns_resolvconf.c" */
+ }
+ }
+
+_again:
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ }
+
+/* #line 135 "./ragel/tnet_dns_resolvconf.rl" */
+
+ if( cs <
+/* #line 290 "./src/dns/tnet_dns_resolvconf.c" */
+0
+/* #line 136 "./ragel/tnet_dns_resolvconf.rl" */
+ ){
+ TSK_DEBUG_ERROR("Failed to parse %s.", fullpath);
+ TSK_OBJECT_SAFE_FREE(servers);
+ }
+
+bail:
+ return servers;
+}
+
+
diff --git a/tinyNET/src/dns/tnet_dns_resolvconf.h b/tinyNET/src/dns/tnet_dns_resolvconf.h
new file mode 100644
index 0000000..b13e092
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_resolvconf.h
@@ -0,0 +1,43 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_resolvconf.h
+ * @brief Parser for "/etc/resolv.conf" file to retrive DNS servers.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RESOLVCONF_H
+#define TNET_DNS_RESOLVCONF_H
+
+#include "tinynet_config.h"
+
+#include "tnet_types.h"
+
+TNET_BEGIN_DECLS
+
+TINYNET_API tnet_addresses_L_t * tnet_dns_resolvconf_parse(const char* path);
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RESOLVCONF_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_rr.c b/tinyNET/src/dns/tnet_dns_rr.c
new file mode 100644
index 0000000..ddf3682
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_rr.c
@@ -0,0 +1,452 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_rr.c
+ * @brief DNS Resource Record (RFC 1034 and 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_rr.h"
+
+#include "tnet_dns_a.h"
+#include "tnet_dns_aaaa.h"
+#include "tnet_dns_cname.h"
+#include "tnet_dns_mx.h"
+#include "tnet_dns_naptr.h"
+#include "tnet_dns_ns.h"
+#include "tnet_dns_opt.h"
+#include "tnet_dns_ptr.h"
+#include "tnet_dns_soa.h"
+#include "tnet_dns_srv.h"
+#include "tnet_dns_txt.h"
+
+#include "../tnet_types.h"
+#include "../tnet_endianness.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+#include "tsk_string.h"
+
+#include <string.h> /* strtok, strlen ... */
+
+
+/** Creates a new DNS RR.
+*/
+
+tnet_dns_rr_t* tnet_dns_rr_create()
+{
+ return tsk_object_new(tnet_dns_rr_def_t);
+}
+
+/** Initializes any DNS RR (either NAPTR or SRV ...).
+* @param rr The DNS RR to initialize.
+* @param qtype The type of the RR.
+* @param qclass The class of the RR.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tnet_dns_rr_init(tnet_dns_rr_t *rr, tnet_dns_qtype_t qtype, tnet_dns_qclass_t qclass)
+{
+ if(rr){
+ if(!rr->initialized){
+ rr->qtype = qtype;
+ rr->qclass = qclass;
+
+ rr->initialized = tsk_true;
+ return 0;
+ }
+ return -2;
+ }
+ return -1;
+}
+
+/** Deinitializes any DNS RR (either NAPTR or SRV ...).
+* @param rr The DNS RR to deinitialize.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tnet_dns_rr_deinit(tnet_dns_rr_t *rr)
+{
+ if(rr){
+ if(rr->initialized){
+ TSK_FREE(rr->name);
+ TSK_FREE(rr->rpdata);
+
+ rr->initialized = tsk_false;
+ return 0;
+ }
+ return -2;
+ }
+ return -1;
+}
+
+/** Deserialize <character-string>.
+*/
+int tnet_dns_rr_charstring_deserialize(const void* data, char** charstring, tsk_size_t *offset)
+{
+ /* RFC 1035 - 3.3. Standard RRs
+ <character-string> is a single length octet followed by that number of characters.
+ <character-string> is treated as binary information, and can be up to 256 characters in
+ length (including the length octet).
+ */
+ uint8_t* dataPtr = (((uint8_t*)data)+ *offset);
+ uint8_t length = *dataPtr;
+
+ *charstring = tsk_strndup((const char*)(dataPtr + 1), length);
+ *offset += (1 + length);
+
+ return 0;
+}
+
+/** Deserializes a QName.
+*/
+int tnet_dns_rr_qname_deserialize(const void* data, char** name, tsk_size_t *offset)
+{
+ /* RFC 1035 - 4.1.4. Message compression
+
+ The pointer takes the form of a two octet sequence:
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | 1 1| OFFSET |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ uint8_t* dataPtr = (((uint8_t*)data) + *offset);
+ unsigned usingPtr = 0; /* Do not change. */
+
+ while(*dataPtr){
+ usingPtr = ((*dataPtr & 0xC0) == 0xC0);
+
+ if(usingPtr){
+ tsk_size_t ptr_offset = (*dataPtr & 0x3F);
+ ptr_offset = ptr_offset << 8 | *(dataPtr+1);
+
+ *offset += 2;
+ return tnet_dns_rr_qname_deserialize(data, name, &ptr_offset);
+ }
+ else{
+ uint8_t length;
+
+ if(*name){
+ tsk_strcat(name, ".");
+ }
+
+ length = *dataPtr;
+ *offset+=1, dataPtr++;
+
+ tsk_strncat(name, (const char*)dataPtr, length);
+ *offset += length, dataPtr += length;
+ }
+ }
+
+ *offset+=1;
+
+ return 0;
+}
+
+//int tnet_dns_rr_qname_deserialize(const void* data, tsk_size_t size, char** name, tsk_size_t *offset)
+//{
+// /* RFC 1035 - 4.1.4. Message compression
+//
+// The pointer takes the form of a two octet sequence:
+// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+// | 1 1| OFFSET |
+// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+// */
+// uint8_t* dataPtr = (((uint8_t*)data) + *offset);
+// uint8_t* dataEnd = (dataPtr + size);
+// unsigned usingPtr = 0; /* Do not change. */
+// unsigned islast = 0;
+//
+// while(!islast)
+// {
+// usingPtr = ((*dataPtr & 0xC0) == 0xC0);
+//
+// if(usingPtr)
+// {
+// uint8_t *Ptr;
+// uint16_t ptr_offset = (*dataPtr & 0x3F);
+// ptr_offset = ptr_offset << 8 | *(dataPtr+1);
+// Ptr = ((uint8_t*)data) + ptr_offset;
+//
+// tnet_qname_label_parse(Ptr, (dataEnd - Ptr), name, &islast);
+// *offset += 2, dataPtr += 2;
+// }
+// else
+// {
+// tsk_size_t length = tnet_qname_label_parse(dataPtr, size, name, &islast);
+// *offset += length, dataPtr += length;
+// }
+// }
+//
+// *offset += usingPtr ? 0 : 1;
+//
+// return 0;
+//}
+
+/** Serializes a QName.
+*/
+int tnet_dns_rr_qname_serialize(const char* qname, tsk_buffer_t* output)
+{
+ /*
+ QNAME a domain name represented as a sequence of labels, where
+ each label consists of a length octet followed by that
+ number of octets. The domain name terminates with the
+ zero length octet for the null label of the root. Note
+ that this field may be an odd number of octets; no
+ padding is used.
+
+ Example: "doubango.com" ==> 8doubango3comNULL
+ */
+ static uint8_t null = 0;
+
+ if(qname){
+ char* _qname = tsk_strdup(qname);
+ char* label = strtok(_qname, ".");
+
+ while(label){
+ uint8_t length = tsk_strlen(label);
+ tsk_buffer_append(output, &length, 1);
+ tsk_buffer_append(output, label, tsk_strlen(label));
+
+ label = strtok (tsk_null, ".");
+ }
+
+ TSK_FREE(_qname);
+ }
+
+ /* terminates domain name */
+ tsk_buffer_append(output, &null, 1);
+
+ return 0;
+}
+
+/** Deserializes a DNS RR.
+*/
+tnet_dns_rr_t* tnet_dns_rr_deserialize(const void* data, tsk_size_t size, tsk_size_t* offset)
+{
+ tnet_dns_rr_t *rr = tsk_null;
+ uint8_t* dataStart = (uint8_t*)data;
+ uint8_t* dataPtr = (dataStart + *offset);
+ //uint8_t* dataEnd = (dataPtr+size);
+ tnet_dns_qtype_t qtype;
+ tnet_dns_qclass_t qclass;
+ uint32_t ttl;
+ uint16_t rdlength;
+ char* qname = tsk_null;
+
+ /* Check validity */
+ if(!dataPtr || !size){
+ goto bail;
+ }
+
+ /* == Parse QNAME == */
+ tnet_dns_rr_qname_deserialize(dataStart, &qname, offset);
+ dataPtr = (dataStart + *offset);
+ /* == Parse QTYPE == */
+ qtype = (tnet_dns_qtype_t)tnet_ntohs_2(dataPtr);
+ dataPtr += 2, *offset += 2;
+ /* == Parse QCLASS == */
+ qclass = (tnet_dns_qclass_t)tnet_ntohs_2(dataPtr);
+ dataPtr += 2, *offset += 2;
+ /* == Parse TTL == */
+ ttl = tnet_htonl_2(dataPtr);
+ dataPtr += 4, *offset += 4;
+ /* == Parse RDLENGTH == */
+ rdlength = tnet_ntohs_2(dataPtr);
+ dataPtr += 2, *offset += 2;
+
+ switch(qtype){
+ case qtype_a:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_a_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ case qtype_aaaa:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_aaaa_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ case qtype_cname:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_cname_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ case qtype_mx:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_mx_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ case qtype_naptr:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_naptr_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ case qtype_ns:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_ns_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ case qtype_opt:
+ {
+ unsigned payload_size = qclass;
+ rr = (tnet_dns_rr_t *)tnet_dns_opt_create(payload_size);
+ break;
+ }
+
+ case qtype_ptr:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_ptr_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ case qtype_soa:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_soa_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ case qtype_srv:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_srv_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ case qtype_txt:
+ {
+ rr = (tnet_dns_rr_t *)tnet_dns_txt_create(qname, qclass, ttl, rdlength, dataStart, *offset);
+ break;
+ }
+
+ default:
+ {
+ TSK_DEBUG_ERROR("NOT IMPLEMENTED");
+ break;
+ }
+ }
+
+bail:
+ TSK_FREE(qname);
+
+ *offset += rdlength;
+ return rr;
+}
+
+/** Serializes a DNS RR.
+*/
+int tnet_dns_rr_serialize(const tnet_dns_rr_t* rr, tsk_buffer_t *output)
+{
+ if(!rr || !output){
+ return -1;
+ }
+
+ /*=== NAME ===*/
+ {
+ tnet_dns_rr_qname_serialize(rr->name, output);
+ }
+
+ /*=== TYPE ===*/
+ {
+ uint16_t qtype = tnet_htons(rr->qtype);
+ tsk_buffer_append(output, &(qtype), 2);
+ }
+
+ /*=== CLASS ===*/
+ {
+ uint16_t qclass = tnet_htons(rr->qclass);
+ tsk_buffer_append(output, &(qclass), 2);
+ }
+
+ /*=== TTL ===*/
+ {
+ uint32_t ttl = tnet_htonl(rr->ttl);
+ tsk_buffer_append(output, &(ttl), 4);
+ }
+
+ /*=== RDLENGTH ===*/
+ {
+ uint16_t length = tnet_htons(rr->rdlength);
+ tsk_buffer_append(output, &(length), 2);
+ }
+
+ /*=== RDATA : Request never contains data
+ ===*/
+ if(!rr->rpdata){
+ goto done;
+ }
+
+ switch(rr->qtype){
+ case qtype_a:
+ case qtype_aaaa:
+ case qtype_cname:
+ case qtype_mx:
+ case qtype_naptr:
+ case qtype_ns:
+ case qtype_opt:
+ case qtype_ptr:
+ case qtype_soa:
+ case qtype_srv:
+ case qtype_txt:
+ default:
+ {
+ TSK_DEBUG_WARN("DNS Request should not contains RDATA (not supported).");
+ break;
+ }
+ }
+
+done:
+ return 0;
+}
+
+
+//=================================================================================================
+// [[DNS RR]] object definition
+//
+static tsk_object_t* tnet_dns_rr_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_rr_t *rr = self;
+ if(rr){
+ tnet_dns_rr_init(rr, qtype_any, qclass_any);
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_rr_dtor(tsk_object_t * self)
+{
+ tnet_dns_rr_t *rr = self;
+ if(rr){
+ tnet_dns_rr_deinit(rr);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_rr_def_s =
+{
+ sizeof(tnet_dns_rr_t),
+ tnet_dns_rr_ctor,
+ tnet_dns_rr_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_rr_def_t = &tnet_dns_rr_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_rr.h b/tinyNET/src/dns/tnet_dns_rr.h
new file mode 100644
index 0000000..f3fcbc0
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_rr.h
@@ -0,0 +1,171 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_rr.h
+ * @brief DNS Resource Record (RFCS 1034 and 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#ifndef TNET_DNS_RR_H
+#define TNET_DNS_RR_H
+
+#include "tinynet_config.h"
+
+#include "tsk_list.h"
+#include "tsk_buffer.h"
+
+/** @def TNET_DNS_RR
+* Converts any DNS RR to a pointer to @ref tnet_dns_rr_t.
+* @retval A pointer to @ref tnet_dns_rr_t object.
+*/
+TNET_BEGIN_DECLS
+
+#define TNET_DNS_RR(self) ((tnet_dns_rr_t*)(self))
+
+/** RFC 1035 - 3.2.2. TYPE values
+* @sa http://en.wikipedia.org/wiki/List_of_DNS_record_types
+*/
+typedef enum tnet_dns_qtype_e
+{
+ qtype_a = 1, /**< A 1 a host address */
+ qtype_ns = 2, /**< NS 2 an authoritative name server */
+ qtype_md = 3, /**< MD 3 a mail destination (Obsolete - use MX) */
+ qtype_mf = 4, /**< MF 4 a mail forwarder (Obsolete - use MX) */
+ qtype_cname = 5, /**< CNAME 5 the canonical name for an alias */
+ qtype_soa = 6, /**< SOA 6 marks the start of a zone of authority */
+ qtype_mb = 7, /**< MB 7 a mailbox domain name (EXPERIMENTAL) */
+ qtype_mg = 8, /**< MG 8 a mail group member (EXPERIMENTAL) */
+ qtype_mr = 9, /**< MR 9 a mail rename domain name (EXPERIMENTAL) */
+ qtype_null = 10, /**< NULL 10 a null RR (EXPERIMENTAL) */
+ qtype_wks = 11, /**< WKS 11 a well known service description */
+ qtype_ptr = 12, /**< PTR 12 a domain name pointer */
+ qtype_hinfo = 13, /**< HINFO 13 host information */
+ qtype_minfo = 14, /**< MINFO 14 mailbox or mail list information */
+ qtype_mx = 15, /**< MX 15 mail exchange */
+ qtype_txt = 16, /**< TXT 16 text strings */
+
+ qtype_aaaa = 28, /**< AAAA 28 IPv6 host address */
+
+ qtype_srv = 33, /**< SRV 33 Service locator */
+
+ qtype_naptr = 35, /**< NAPTR 35 Naming Authority Pointer */
+
+ qtype_opt = 41, /**< OPT 41 Option */
+
+ qtype_ipseckey = 45,/**< IPSECKEY 45 IPSEC Key */
+
+ qtype_spf = 99, /**< SPF 99 SPF record */
+
+ qtype_any = 255 /**< * 255 A request for all records (3.2.3. QTYPE values)*/
+}
+tnet_dns_qtype_t;
+
+/** RFC 1035 - 3.2.4. CLASS values
+*/
+typedef enum tnet_dns_qclass_e
+{
+ qclass_in = 1, /**< IN 1 the Internet */
+ qclass_ics = 2, /**< CS 2 the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
+ qclass_ch = 3, /**< CH 3 the CHAOS class */
+ qclass_hs = 4, /**< HS 4 Hesiod [Dyer 87] */
+
+ qclass_any = 255 /**< * 255 any class (3.2.5. QCLASS values) */
+}
+tnet_dns_qclass_t;
+
+/** RFC 1034 (3.6. Resource Records) and 1035 (3.2.1. Format)
+*/
+typedef struct tnet_dns_rr_s
+{
+ TSK_DECLARE_OBJECT;
+
+ /* RFC 1035 - 3.2.1. Format
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+
+ tsk_bool_t initialized;
+
+ /** An owner name, i.e., the name of the node to which this resource record pertains. */
+ char* name;
+
+ /** Two octets containing one of the RR TYPE codes. */
+ tnet_dns_qtype_t qtype;
+
+ /** Two octets containing one of the RR CLASS codes. */
+ tnet_dns_qclass_t qclass;
+
+ /** A 32 bit signed integer that specifies the time interval (seconds) that the resource record may be cached before the source
+ of the information should again be consulted.
+ Zero values are interpreted to mean that the RR can only be used for the transaction in progress, and should not be cached.
+ For example, SOA records are always distributed with a zero TTL to prohibit caching. Zero values can also be used for extremely volatile data. */
+ int32_t ttl;
+
+ /** An unsigned 16 bit integer that specifies the length in octets of the RDATA field. */
+ uint16_t rdlength;
+
+ /** A variable length string of octets that describes the resource.
+ The format of this information varies according to the TYPE and CLASS of the resource record.*/
+ void *rpdata;
+}
+tnet_dns_rr_t;
+
+#define TNET_DECLARE_DNS_RR tnet_dns_rr_t dns_rr
+
+typedef tsk_list_t tnet_dns_rrs_L_t; /**< List of @ref tnet_dns_rr_t elements. */
+
+int tnet_dns_rr_init(tnet_dns_rr_t *rr, tnet_dns_qtype_t qtype, tnet_dns_qclass_t qclass);
+int tnet_dns_rr_deinit(tnet_dns_rr_t *rr);
+
+int tnet_dns_rr_charstring_deserialize(const void* data, char** name, tsk_size_t *offset);
+
+int tnet_dns_rr_qname_deserialize(const void* data, char** name, tsk_size_t *offset);
+int tnet_dns_rr_qname_serialize(const char* qname, tsk_buffer_t* output);
+
+tnet_dns_rr_t* tnet_dns_rr_deserialize(const void* data, tsk_size_t size, tsk_size_t* offset);
+int tnet_dns_rr_serialize(const tnet_dns_rr_t* rr, tsk_buffer_t *output);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_rr_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_H */
diff --git a/tinyNET/src/dns/tnet_dns_soa.c b/tinyNET/src/dns/tnet_dns_soa.c
new file mode 100644
index 0000000..0b8be15
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_soa.c
@@ -0,0 +1,112 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_soa.c
+ * @brief DNS Start Of Authority record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_soa.h"
+
+#include "../tnet_types.h"
+#include "../tnet_endianness.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+
+tnet_dns_soa_t* tnet_dns_soa_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_soa_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+//=================================================================================================
+// [[DNS SOA]] object definition
+//
+static tsk_object_t* tnet_dns_soa_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_soa_t *soa = self;
+ if(soa){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(soa), qtype_soa, qclass);
+ TNET_DNS_RR(soa)->name = tsk_strdup(name);
+ TNET_DNS_RR(soa)->rdlength = rdlength;
+ TNET_DNS_RR(soa)->ttl = ttl;
+
+ if(rdlength)
+ { // ==> DESERIALIZATION
+ /* MNAME */
+ tnet_dns_rr_qname_deserialize(data, &(soa->mname), &offset);
+ /* RNAME */
+ tnet_dns_rr_qname_deserialize(data, &(soa->rname), &offset);
+ /* SERIAL */
+ soa->serial = tnet_htonl_2(((uint8_t*)data) + offset),
+ offset += 2;
+ /* REFRESH */
+ soa->refresh = tnet_htonl_2(((uint8_t*)data) + offset),
+ offset += 2;
+ /* RETRY */
+ soa->retry = tnet_htonl_2(((uint8_t*)data) + offset),
+ offset += 2;
+ /* EXPIRE */
+ soa->expire = tnet_htonl_2(((uint8_t*)data) + offset),
+ offset += 2;
+ /* MINIMUM */
+ soa->minimum = tnet_htonl_2(((uint8_t*)data) + offset),
+ offset += 2;
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_soa_dtor(tsk_object_t * self)
+{
+ tnet_dns_soa_t *soa = self;
+ if(soa){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(soa));
+
+ TSK_FREE(soa->mname);
+ TSK_FREE(soa->rname);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_soa_def_s =
+{
+ sizeof(tnet_dns_soa_t),
+ tnet_dns_soa_ctor,
+ tnet_dns_soa_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_soa_def_t = &tnet_dns_soa_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_soa.h b/tinyNET/src/dns/tnet_dns_soa.h
new file mode 100644
index 0000000..eb88989
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_soa.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_soa.h
+ * @brief DNS Start Of Authority record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_SOA_H
+#define TNET_DNS_RR_SOA_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+TNET_BEGIN_DECLS
+
+typedef struct tnet_dns_soa_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ /* RFC 1035 - 3.3.13. SOA RDATA format
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / RNAME /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | SERIAL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | REFRESH |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RETRY |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | EXPIRE |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | MINIMUM |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ char* mname;
+ char* rname;
+ uint32_t serial;
+ uint32_t refresh;
+ uint32_t retry;
+ uint32_t expire;
+ uint32_t minimum;
+}
+tnet_dns_soa_t;
+
+tnet_dns_soa_t* tnet_dns_soa_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_soa_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_SOA_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_srv.c b/tinyNET/src/dns/tnet_dns_srv.c
new file mode 100644
index 0000000..2fc8f41
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_srv.c
@@ -0,0 +1,137 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_srv.c
+ * @brief DNS SeRVice locator record - RR - (RFC 2782).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_srv.h"
+
+#include "../tnet_types.h"
+#include "../tnet_endianness.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+
+/** Creates new DNS SRV Resource Record.
+*/
+tnet_dns_srv_t* tnet_dns_srv_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_srv_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+//=================================================================================================
+// [[DNS SRV]] object definition
+//
+static tsk_object_t* tnet_dns_srv_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_srv_t *srv = self;
+ if(srv){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(srv), qtype_srv, qclass);
+ TNET_DNS_RR(srv)->name = tsk_strdup(name);
+ TNET_DNS_RR(srv)->rdlength = rdlength;
+ TNET_DNS_RR(srv)->ttl = ttl;
+
+ if(rdlength){
+ // ==> DESERIALIZATION
+ /* Priority */
+ srv->priority = tnet_ntohs_2(((uint8_t*)data) + offset),
+ offset += 2;
+ /* Weight */
+ srv->weight = tnet_ntohs_2(((uint8_t*)data) + offset),
+ offset += 2;
+ /* Port */
+ srv->port = tnet_ntohs_2(((uint8_t*)data) + offset),
+ offset += 2;
+ /* Target */
+ tnet_dns_rr_qname_deserialize(data, &(srv->target), &offset);
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_srv_dtor(tsk_object_t * self)
+{
+ tnet_dns_srv_t *srv = self;
+ if(srv){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(srv));
+
+ TSK_FREE(srv->target);
+ }
+ return self;
+}
+
+static int tnet_dns_srv_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
+{
+ const tnet_dns_rr_t* rr1 = obj1;
+ const tnet_dns_rr_t* rr2 = obj2;
+
+ if(rr1 && rr2 && (rr1->qtype==qtype_srv) && (rr2->qtype==qtype_srv)){
+ const tnet_dns_srv_t* srv1 = (tnet_dns_srv_t*)rr1;
+ const tnet_dns_srv_t* srv2 = (tnet_dns_srv_t*)rr2;
+
+ /* Compare priorities. */
+ if(srv1->priority < srv2->priority){ /* Lowest priority is tried first. */
+ return 1;
+ }
+ else if(srv1->priority > srv2->priority){
+ return -1;
+ }
+
+ /* Compare weight */
+ if(srv1->weight > srv2->weight){
+ return 1;
+ }
+ else if(srv1->weight < srv2->weight){
+ return -1;
+ }
+
+ return 0;
+ }
+ else{
+ return -1;
+ }
+}
+
+static const tsk_object_def_t tnet_dns_srv_def_s =
+{
+ sizeof(tnet_dns_srv_t),
+ tnet_dns_srv_ctor,
+ tnet_dns_srv_dtor,
+ tnet_dns_srv_cmp,
+};
+const tsk_object_def_t *tnet_dns_srv_def_t = &tnet_dns_srv_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_srv.h b/tinyNET/src/dns/tnet_dns_srv.h
new file mode 100644
index 0000000..1e04c5d
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_srv.h
@@ -0,0 +1,59 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_srv.h
+ * @brief DNS SeRVice locator record - RR - (RFC 2782).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_SRV_H
+#define TNET_DNS_RR_SRV_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+
+TNET_BEGIN_DECLS
+
+/** DNS SRV Resource Record
+*/
+typedef struct tnet_dns_srv_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ uint16_t priority;
+ uint16_t weight;
+ uint16_t port;
+ char* target;
+}
+tnet_dns_srv_t;
+
+tnet_dns_srv_t* tnet_dns_srv_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_srv_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_SRV_H */
+
diff --git a/tinyNET/src/dns/tnet_dns_txt.c b/tinyNET/src/dns/tnet_dns_txt.c
new file mode 100644
index 0000000..baabed9
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_txt.c
@@ -0,0 +1,96 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_txt.c
+ * @brief DNS TeXT record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tnet_dns_txt.h"
+
+#include "../tnet_types.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+
+/** Creates new DNS TXT Resource Record.
+*/
+
+tnet_dns_txt_t* tnet_dns_txt_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset)
+{
+ return tsk_object_new(tnet_dns_txt_def_t, name, qclass, ttl, rdlength, data, offset);
+}
+
+//=================================================================================================
+// [[DNS TXT]] object definition
+//
+static tsk_object_t* tnet_dns_txt_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_dns_txt_t *txt = self;
+ if(txt){
+ const char* name = va_arg(*app, const char*);
+ tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t);
+ uint32_t ttl = va_arg(*app, uint32_t);
+#if defined(__GNUC__)
+ uint16_t rdlength = (uint16_t)va_arg(*app, unsigned);
+#else
+ uint16_t rdlength = va_arg(*app, uint16_t);
+#endif
+ const void* data = va_arg(*app, const void*);
+ tsk_size_t offset = va_arg(*app, tsk_size_t);
+
+ /* init base */
+ tnet_dns_rr_init(TNET_DNS_RR(txt), qtype_txt, qclass);
+ TNET_DNS_RR(txt)->name = tsk_strdup(name);
+ TNET_DNS_RR(txt)->rdlength = rdlength;
+ TNET_DNS_RR(txt)->ttl = ttl;
+
+ if(rdlength){
+ // ==> DESERIALIZATION
+ /* TXT-DATA */
+ tnet_dns_rr_charstring_deserialize(data, &(txt->txt_data), &offset);
+ }
+ }
+ return self;
+}
+
+static tsk_object_t* tnet_dns_txt_dtor(tsk_object_t * self)
+{
+ tnet_dns_txt_t *txt = self;
+ if(txt){
+ /* deinit base */
+ tnet_dns_rr_deinit(TNET_DNS_RR(txt));
+
+ TSK_FREE(txt->txt_data);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tnet_dns_txt_def_s =
+{
+ sizeof(tnet_dns_txt_t),
+ tnet_dns_txt_ctor,
+ tnet_dns_txt_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_dns_txt_def_t = &tnet_dns_txt_def_s;
diff --git a/tinyNET/src/dns/tnet_dns_txt.h b/tinyNET/src/dns/tnet_dns_txt.h
new file mode 100644
index 0000000..69b7a74
--- /dev/null
+++ b/tinyNET/src/dns/tnet_dns_txt.h
@@ -0,0 +1,61 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO 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 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO 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 DOUBANGO.
+*
+*/
+/**@file tnet_dns_txt.h
+ * @brief DNS TeXT record - RR - (RFC 1035).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TNET_DNS_RR_TXT_H
+#define TNET_DNS_RR_TXT_H
+
+#include "tinynet_config.h"
+
+#include "tnet_dns_rr.h"
+
+
+TNET_BEGIN_DECLS
+
+/** DNS TXT Resource Record
+*/
+typedef struct tnet_dns_txt_s
+{
+ TNET_DECLARE_DNS_RR;
+
+ /* RFC 1035 - 3.3.14. TXT RDATA format
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / TXT-DATA /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ */
+ char* txt_data;
+}
+tnet_dns_txt_t;
+
+tnet_dns_txt_t* tnet_dns_txt_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset);
+
+TINYNET_GEXTERN const tsk_object_def_t *tnet_dns_txt_def_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_DNS_RR_TXT_H */
+
OpenPOWER on IntegriCloud