diff options
Diffstat (limited to 'tinyNET/src/dns')
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 */
+
|