Complete DNS supports for unix-like systems (and Android?) and add parser for /etc/resolv.conf
This commit is contained in:
parent
86f34a04e7
commit
636b786d6a
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue