Complete DNS supports for unix-like systems (and Android?) and add parser for /etc/resolv.conf

This commit is contained in:
bossiel 2010-04-01 17:15:06 +00:00
parent 86f34a04e7
commit 636b786d6a
12 changed files with 650 additions and 55 deletions

View File

@ -5,3 +5,4 @@ export OPTIONS="-C -L -T0"
#export OPTIONS="-C -L -G2"
ragel.exe $OPTIONS -o ./src/dns/tnet_dns_regexp.c ./ragel/tnet_dns_regexp.rl
ragel.exe $OPTIONS -o ./src/dns/tnet_dns_resolvconf.c ./ragel/tnet_dns_resolvconf.rl

View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
*
* 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)yahoo.fr>
*
* @date Created: Sat Nov 8 16:54:58 2009 mdiop
*/
#include "tnet_dns_resolvconf.h"
#include "tnet_utils.h"
#include "tsk_string.h"
#include "tsk_memory.h"
#include "tsk_ragel_state.h"
#include "tsk_debug.h"
#include <string.h>
/* === Ragel state machine === */
%%{
machine tdns_machine_resolvconf;
action tag{
tag_start = p;
}
action add_dns{
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);
address->dnsserver = 1;
tsk_list_push_ascending_data(servers, &address);
}
}
SP = " ";
LF = "\n";
CR = "\r";
CRLF = CR LF;
ENDL = (LF | CR | CRLF);
o_name = any+;
o_value = any+;
COMMENT = SP*<: "#" any*;
OPTION_ANY = SP*<: o_name :>SP+<: o_value :>SP*;
OPTION_DNS = SP*<: "nameserver"i :>SP+<: o_value>tag %add_dns :>SP*;
LINE = (OPTION_DNS)@100 | (OPTION_ANY)@0 | (COMMENT)@50;
main := ((LINE :>ENDL) | ENDL)* %3 any* %2;
}%%
/** 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 fail, 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;
%%write data;
if(!fullpath || tsk_strempty(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{
TSK_DEBUG_ERROR("Failed to open %s.", fullpath);
goto bail;
}
%%write init;
%%write exec;
if( cs < %%{ write first_final; }%% ){
TSK_DEBUG_ERROR("Failed to parse %s.", fullpath);
TSK_OBJECT_SAFE_FREE(servers);
}
bail:
return servers;
}

View File

@ -69,7 +69,7 @@ int tnet_dns_cache_clear(tnet_dns_ctx_t* ctx)
}
/**@ingroup tnet_dns_group
* Sends DNS request over the network. The request will be sent each 200 milliseconds until @ref TNET_DNS_TIMEOUT_DEFAULT milliseconds is reached.
* 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.
@ -87,9 +87,9 @@ int tnet_dns_cache_clear(tnet_dns_ctx_t* ctx)
*/
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)
{
tsk_buffer_t *output = 0;
tsk_buffer_t *output = tsk_null;
tnet_dns_query_t* query = TNET_DNS_QUERY_CREATE(qname, qclass, qtype);
tnet_dns_response_t *response = 0;
tnet_dns_response_t *response = tsk_null;
tsk_bool_t from_cache = tsk_false;
/* Check validity */
@ -97,6 +97,12 @@ tnet_dns_response_t *tnet_dns_resolve(tnet_dns_ctx_t* ctx, const char* qname, tn
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 */
@ -138,7 +144,7 @@ tnet_dns_response_t *tnet_dns_resolve(tnet_dns_ctx_t* ctx, const char* qname, tn
// Send and Recaive data
/* ============================ */
{
int ret;
int ret = -1;
struct timeval tv;
fd_set set;
tnet_fd_t maxFD;
@ -157,9 +163,9 @@ tnet_dns_response_t *tnet_dns_resolve(tnet_dns_ctx_t* ctx, const char* qname, tn
goto done;
}
/* Always wait 200ms before retransmission */
/* Always wait 500ms before retransmission */
tv.tv_sec = 0;
tv.tv_usec = (200 * 1000);
tv.tv_usec = (500 * 1000);
do
{
@ -194,7 +200,7 @@ tnet_dns_response_t *tnet_dns_resolve(tnet_dns_ctx_t* ctx, const char* qname, tn
break;
}
}
}
}
//
// Received data
@ -660,6 +666,35 @@ const tnet_dns_cache_entry_t* tnet_dns_cache_entry_get(tnet_dns_ctx_t *ctx, cons
}
/**
* 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);
address->dnsserver = 1;
tsk_list_push_ascending_data(ctx->servers, (void**)&address);
return 0;
}
return -2;
}
//=================================================================================================
// [[DNS CACHE ENTRY]] object definition
//

View File

@ -99,8 +99,8 @@ typedef struct tnet_dns_ctx_s
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. Default: enabled. */
tsk_bool_t caching; /**< Indicates whether to enable the DNS cache or not. */
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;
@ -120,6 +120,8 @@ TINYNET_API char* tnet_dns_enum_2(tnet_dns_ctx_t* ctx, const char* service, cons
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_GEXTERN const void *tnet_dns_ctx_def_t;
TINYNET_GEXTERN const void *tnet_dns_cache_entry_def_t;

View File

@ -0,0 +1,293 @@
/* #line 1 "./ragel/tnet_dns_resolvconf.rl" */
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
*
* 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)yahoo.fr>
*
* @date Created: Sat Nov 8 16:54:58 2009 mdiop
*/
#include "tnet_dns_resolvconf.h"
#include "tnet_utils.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 78 "./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 fail, 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 72 "./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 103 "./ragel/tnet_dns_resolvconf.rl" */
if(!fullpath || tsk_strempty(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{
TSK_DEBUG_ERROR("Failed to open %s.", fullpath);
goto bail;
}
/* #line 168 "./src/dns/tnet_dns_resolvconf.c" */
{
cs = tdns_machine_resolvconf_start;
}
/* #line 126 "./ragel/tnet_dns_resolvconf.rl" */
/* #line 175 "./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 45 "./ragel/tnet_dns_resolvconf.rl" */
{
tag_start = p;
}
break;
case 1:
/* #line 49 "./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);
address->dnsserver = 1;
tsk_list_push_ascending_data(servers, &address);
}
}
break;
/* #line 269 "./src/dns/tnet_dns_resolvconf.c" */
}
}
_again:
if ( ++p != pe )
goto _resume;
_test_eof: {}
}
/* #line 127 "./ragel/tnet_dns_resolvconf.rl" */
if( cs <
/* #line 282 "./src/dns/tnet_dns_resolvconf.c" */
0
/* #line 128 "./ragel/tnet_dns_resolvconf.rl" */
){
TSK_DEBUG_ERROR("Failed to parse %s.", fullpath);
TSK_OBJECT_SAFE_FREE(servers);
}
bail:
return servers;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
*
* 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)yahoo.fr>
*
* @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 */

View File

@ -115,6 +115,7 @@
#define TNET_SOFTWARE "IM-client/OMA1.0 doubango/v0.0.0"
#define TNET_IANA_PEN 35368 /**< PEN number assigned by the IANA.
The list of assigned numbers could be found here http://www.iana.org/assignments/enterprise-numbers. */
#define TNET_RESOLV_CONF_PATH "/etc/resolv.conf"
#include <stdint.h>

View File

@ -60,6 +60,7 @@
#endif
#include "tsk_errno.h"
#include "tsk_list.h"
TNET_BEGIN_DECLS
@ -69,6 +70,8 @@ typedef int32_t tnet_family_t;
typedef char tnet_host_t[NI_MAXHOST];
typedef char tnet_ip_t[INET6_ADDRSTRLEN];
typedef tsk_list_t tnet_interfaces_L_t; /**< List of @ref tnet_interface_t elements.*/
typedef tsk_list_t tnet_addresses_L_t; /**< List of @ref tnet_address_t elements.*/
#if TNET_UNDER_WINDOWS
# define TNET_INVALID_SOCKET INVALID_SOCKET

View File

@ -36,6 +36,7 @@
#include "tnet_socket.h"
#include "tnet_endianness.h"
#include "dns/tnet_dns_resolvconf.h"
#include <string.h>
@ -281,14 +282,14 @@ bail:
tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, unsigned unicast, unsigned anycast, unsigned multicast, unsigned dnsserver, long if_index)
{
tnet_addresses_L_t *addresses = TSK_LIST_CREATE();
tnet_ip_t ip;
#if TSK_UNDER_WINDOWS
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
/* Declare and initialize variables */
tnet_ip_t ip;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
@ -337,8 +338,7 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, unsigned unicast, u
goto next;
}
/* UNICAST addresses
*/
/* == UNICAST addresses == */
pUnicast = pCurrAddresses->FirstUnicastAddress;
while(unicast && pUnicast)
{
@ -348,14 +348,13 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, unsigned unicast, u
tnet_address_t *address = TNET_ADDRESS_CREATE(ip);
address->family = pUnicast->Address.lpSockaddr->sa_family;
address->unicast = 1;
tsk_list_push_back_data(addresses, &address);
tsk_list_push_ascending_data(addresses, &address);
}
pUnicast = pUnicast->Next;
}
/* ANYCAST addresses
*/
/* == ANYCAST addresses == */
pAnycast = pCurrAddresses->FirstAnycastAddress;
while(anycast && pAnycast)
{
@ -365,14 +364,13 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, unsigned unicast, u
tnet_address_t *address = TNET_ADDRESS_CREATE(ip);
address->family = pAnycast->Address.lpSockaddr->sa_family;
address->anycast = 1;
tsk_list_push_back_data(addresses, &address);
tsk_list_push_ascending_data(addresses, &address);
}
pAnycast = pAnycast->Next;
}
/* MULTYCAST addresses
*/
/* == MULTYCAST addresses == */
pMulticast = pCurrAddresses->FirstMulticastAddress;
while(multicast && pMulticast)
{
@ -382,14 +380,13 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, unsigned unicast, u
tnet_address_t *address = TNET_ADDRESS_CREATE(ip);
address->family = pMulticast->Address.lpSockaddr->sa_family;
address->multicast = 1;
tsk_list_push_back_data(addresses, &address);
tsk_list_push_ascending_data(addresses, &address);
}
pMulticast = pMulticast->Next;
}
/* DNS servers
*/
/* == DNS servers == */
pDnServer = pCurrAddresses->FirstDnsServerAddress;
while(dnsserver && pDnServer)
{
@ -399,12 +396,7 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, unsigned unicast, u
tnet_address_t *address = TNET_ADDRESS_CREATE(ip);
address->family = pDnServer->Address.lpSockaddr->sa_family;
address->dnsserver = 1;
// IPv4 first
if(address->family == AF_INET){
tsk_list_push_front_data(addresses, &address);
}else{
tsk_list_push_back_data(addresses, &address);
}
tsk_list_push_ascending_data(addresses, &address);
}
pDnServer = pDnServer->Next;
@ -414,26 +406,30 @@ next:
}
}
if(pAddresses)
{
if(pAddresses){
FREE(pAddresses);
}
#undef MALLOC
#undef FREE
bail:
#else /* !TSK_UNDER_WINDOWS (MAC OX, UNIX, ANDROID ...) */
#else /* !TSK_UNDER_WINDOWS */
tnet_addresses_L_t * dns_servers;
/* == DNS servers == */
if((dns_servers = tnet_dns_resolvconf_parse("/etc/resolv.conf"))){
tsk_list_pushback_list(addresses, dns_servers);
TSK_OBJECT_SAFE_FREE(dns_servers);
}
#endif
bail:
return addresses;
}
@ -568,6 +564,42 @@ tnet_socket_type_t tnet_get_socket_type(tnet_fd_t fd)
return type;
}
/**@ingroup tnet_utils_group
* Gets the IP family of the @a host (e.g. "google.com" or "192.168.16.104" or "::1").
* If the @a host is FQDN associated with both IPv4 and IPv6 then the result is unpredictable.
* @retval @a AF_* if succeed and @a AF_UNSPEC otherwise.
*/
tnet_family_t tnet_get_family(const char* host)
{
tnet_family_t ret = AF_UNSPEC;
if(host){
int status;
struct addrinfo *result = tsk_null;
struct addrinfo *ptr = tsk_null;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
if((status = tnet_getaddrinfo(host, "", &hints, &result))){
TNET_PRINT_LAST_ERROR("getaddrinfo failed:");
goto done;
}
/* Get the First result. */
if(result){
ret = result->ai_family;
goto done;
}
done:
freeaddrinfo(result);
}
return ret;
}
/**@ingroup tnet_utils_group
* Gets the IP address and the Port of a @b sockaddr object.
* @param addr [in] A pointer to @b sockaddr structure for which to retrieve the IP address and port.
@ -1252,7 +1284,7 @@ int tnet_sockfd_close(tnet_fd_t *fd)
//=================================================================================================
// INTERFACE object definition
//
static void* tnet_interface_create(void * self, va_list * app)
static tsk_object_t* tnet_interface_create(tsk_object_t * self, va_list * app)
{
tnet_interface_t *iface = self;
if(iface)
@ -1270,11 +1302,10 @@ static void* tnet_interface_create(void * self, va_list * app)
return self;
}
static void* tnet_interface_destroy(void * self)
static tsk_object_t* tnet_interface_destroy(tsk_object_t * self)
{
tnet_interface_t *iface = self;
if(iface)
{
if(iface){
TSK_FREE(iface->description);
TSK_FREE(iface->mac_address);
}
@ -1282,13 +1313,12 @@ static void* tnet_interface_destroy(void * self)
return self;
}
static int tnet_interface_cmp(const void *if1, const void *if2)
static int tnet_interface_cmp(const tsk_object_t *if1, const tsk_object_t *if2)
{
const tnet_interface_t *iface1 = if1;
const tnet_interface_t *iface2 = if2;
if(iface1 && iface2)
{
if(iface1 && iface2){
return tsk_stricmp(iface1->description, iface1->description);
}
else if(!iface1 && !iface2) return 0;
@ -1302,7 +1332,7 @@ static const tsk_object_def_t tnet_interface_def_s =
tnet_interface_destroy,
tnet_interface_cmp,
};
const void *tnet_interface_def_t = &tnet_interface_def_s;
const tsk_object_def_t *tnet_interface_def_t = &tnet_interface_def_s;
@ -1310,33 +1340,44 @@ const void *tnet_interface_def_t = &tnet_interface_def_s;
//=================================================================================================
// ADDRESS object definition
//
static void* tnet_address_create(void * self, va_list * app)
static tsk_object_t* tnet_address_create(tsk_object_t * self, va_list * app)
{
tnet_address_t *address = self;
if(address)
{
if(address){
address->ip = tsk_strdup(va_arg(*app, const char*));
}
return self;
}
static void* tnet_address_destroy(void * self)
static tsk_object_t* tnet_address_destroy(tsk_object_t * self)
{
tnet_address_t *address = self;
if(address)
{
if(address){
TSK_FREE(address->ip);
}
return self;
}
static int tnet_address_cmp(const tsk_object_t *_a1, const tsk_object_t *_a2)
{
const tnet_address_t *a1 = _a1;
const tnet_address_t *a2 = _a2;
if(a1 && a2){
// to have AF_UNSPEC, AF_UNIX, AF_INET, ... first
return (a1->family - a2->family);
}
else if(!a1 && !a2) return 0;
else return -1;
}
static const tsk_object_def_t tnet_address_def_s =
{
sizeof(tnet_address_t),
tnet_address_create,
tnet_address_destroy,
0,
tnet_address_cmp,
};
const void *tnet_address_def_t = &tnet_address_def_s;
const tsk_object_def_t *tnet_address_def_t = &tnet_address_def_s;

View File

@ -35,8 +35,6 @@
#include "tnet_socket.h"
#include "tnet_types.h"
#include "tsk_list.h"
/**@ingroup tnet_utils_group
* @def TNET_INTERFACE_CREATE
* Creates new @ref tnet_interface_t object.
@ -69,7 +67,7 @@ typedef struct tnet_interface_s
size_t mac_address_length;
}
tnet_interface_t;
typedef tsk_list_t tnet_interfaces_L_t; /**< List of @ref tnet_interface_t elements.*/
/**@ingroup tnet_utils_group
* Address.
@ -88,7 +86,6 @@ typedef struct tnet_address_s
char* ip;
}
tnet_address_t;
typedef tsk_list_t tnet_addresses_L_t; /**< List of @ref tnet_address_t elements.*/
TINYNET_API void tnet_getlasterror(tnet_error_t *error);
TINYNET_API int tnet_geterrno();
@ -114,6 +111,7 @@ TINYNET_API int tnet_getaddrinfo(const char *node, const char *service, const st
TINYNET_API void tnet_freeaddrinfo(struct addrinfo *ai);
TINYNET_API int tnet_get_sockaddr(tnet_fd_t fd, struct sockaddr_storage *result);
TINYNET_API tnet_socket_type_t tnet_get_socket_type(tnet_fd_t fd);
TINYNET_API tnet_family_t tnet_get_family(const char* host);
TINYNET_API int tnet_get_ip_n_port(tnet_fd_t fd, tnet_ip_t *ip, tnet_port_t *port);
TINYNET_API int tnet_get_sockip_n_port(struct sockaddr *addr, tnet_ip_t *ip, tnet_port_t *port);
TINYNET_API int tnet_get_peerip_n_port(tnet_fd_t localFD, tnet_ip_t *ip, tnet_port_t *port);
@ -173,8 +171,8 @@ TINYNET_API int tnet_sockfd_close(tnet_fd_t *fd);
#endif
TINYNET_GEXTERN const void *tnet_interface_def_t;
TINYNET_GEXTERN const void *tnet_address_def_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_interface_def_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_address_def_t;
TNET_END_DECLS

View File

@ -24,6 +24,9 @@
#include "dns/tnet_dns_naptr.h"
#include "dns/tnet_dns_regexp.h"
#include "dns/tnet_dns_resolvconf.h"
//#include "tnet_utils.h" /* tnet_address_t */
void test_dns_query()
{
@ -109,6 +112,8 @@ void test_enum()
const char* e164num = "+1-800-555-5555";
//const char* e164num = "+33660188661";
//tnet_dns_add_server(ctx, "192.168.16.9");
//if((uri = tnet_dns_enum_2(ctx, "E2U+SIP", e164num, "e164.org"))){
if((uri = tnet_dns_enum_2(ctx, "E2U+SIP", e164num, "e164.org"))){
TSK_DEBUG_INFO("URI=%s", uri);
@ -189,6 +194,29 @@ void test_regex()
}
}
void test_resolvconf()
{
tnet_addresses_L_t * servers;
const tnet_address_t* address;
const tsk_list_item_t* item;
const char* path = "C:\\tmp\\resolv32.conf";
//const char* path = "C:\\tmp\\resolv.conf";
//const char* path = "/etc/resolv.conf";
if((servers = tnet_dns_resolvconf_parse(path))){
tsk_list_foreach(item, servers){
address = item->data;
TSK_DEBUG_INFO("DNS Server host=%s Family=%d", address->ip, address->family);
}
TSK_OBJECT_SAFE_FREE(servers);
}
else{
TSK_DEBUG_ERROR("Failed to parse DNS servers from %s.", );
}
}
void test_dns()
{
//test_dns_naptr_srv();
@ -196,6 +224,7 @@ void test_dns()
//test_dns_query();
test_enum();
//test_regex();
//test_resolvconf();
}

View File

@ -471,6 +471,10 @@
RelativePath="..\..\tinyNET\src\dns\tnet_dns_regexp.c"
>
</File>
<File
RelativePath="..\..\tinyNET\src\dns\tnet_dns_resolvconf.c"
>
</File>
<File
RelativePath="..\..\tinyNET\src\dns\tnet_dns_rr.c"
>
@ -671,6 +675,10 @@
RelativePath="..\..\tinyNET\src\dns\tnet_dns_regexp.h"
>
</File>
<File
RelativePath="..\..\tinyNET\src\dns\tnet_dns_resolvconf.h"
>
</File>
<File
RelativePath="..\..\tinyNET\src\dns\tnet_dns_rr.h"
>
@ -744,6 +752,10 @@
RelativePath="..\..\tinyNET\ragel\tnet_dns_regexp.rl"
>
</File>
<File
RelativePath="..\..\tinyNET\ragel\tnet_dns_resolvconf.rl"
>
</File>
</Filter>
</Files>
<Globals>