mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-06 06:07:37 +02:00
It's good to be back. Add jdns and make libtomahawk link to it, so that we can do proper SRV resolving. Also create thirdparty/ which portfwd and others should really be moved in to
This commit is contained in:
@@ -23,6 +23,7 @@ ELSE()
|
|||||||
ADD_SUBDIRECTORY( rtaudio )
|
ADD_SUBDIRECTORY( rtaudio )
|
||||||
ENDIF( UNIX AND NOT APPLE )
|
ENDIF( UNIX AND NOT APPLE )
|
||||||
|
|
||||||
|
ADD_SUBDIRECTORY( thirdparty )
|
||||||
ADD_SUBDIRECTORY( libportfwd )
|
ADD_SUBDIRECTORY( libportfwd )
|
||||||
ADD_SUBDIRECTORY( qxt )
|
ADD_SUBDIRECTORY( qxt )
|
||||||
ADD_SUBDIRECTORY( src/libtomahawk )
|
ADD_SUBDIRECTORY( src/libtomahawk )
|
||||||
|
@@ -236,6 +236,7 @@ SET( OS_SPECIFIC_LINK_LIBRARIES
|
|||||||
"dnsapi.dll"
|
"dnsapi.dll"
|
||||||
"dsound.dll"
|
"dsound.dll"
|
||||||
"winmm.dll"
|
"winmm.dll"
|
||||||
|
"advapi32.dll"
|
||||||
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../rtaudio/librtaudio.dll"
|
"${CMAKE_CURRENT_SOURCE_DIR}/../../rtaudio/librtaudio.dll"
|
||||||
)
|
)
|
||||||
@@ -282,6 +283,7 @@ target_link_libraries( tomahawklib
|
|||||||
vorbisfile
|
vorbisfile
|
||||||
ogg
|
ogg
|
||||||
FLAC++
|
FLAC++
|
||||||
|
jdns
|
||||||
)
|
)
|
||||||
|
|
||||||
install( TARGETS tomahawklib DESTINATION lib )
|
install( TARGETS tomahawklib DESTINATION lib )
|
||||||
|
1
thirdparty/CMakeLists.txt
vendored
Normal file
1
thirdparty/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
add_subdirectory( jdns )
|
44
thirdparty/jdns/CMakeLists.txt
vendored
Normal file
44
thirdparty/jdns/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
PROJECT(jdns)
|
||||||
|
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.6 FATAL_ERROR)
|
||||||
|
SET(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
|
|
||||||
|
SET( QT_USE_QTNETWORK TRUE )
|
||||||
|
INCLUDE( ${QT_USE_FILE} )
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
SET(PLATFORM_SPECIFIC_LIBS "ws2_32.dll" "advapi32.dll" )
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
set(JDNS_SOURCES
|
||||||
|
jdns_util.c
|
||||||
|
jdns_packet.c
|
||||||
|
jdns_mdnsd.c
|
||||||
|
jdns_sys.c
|
||||||
|
jdns.c
|
||||||
|
qjdns_sock.cpp
|
||||||
|
qjdns.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(JDNS_HEADERS
|
||||||
|
qjdns.h
|
||||||
|
)
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${QT_INCLUDE_DIR}
|
||||||
|
${QT_INCLUDES}
|
||||||
|
)
|
||||||
|
|
||||||
|
qt4_wrap_cpp( JDNS_MOC ${JDNS_HEADERS} )
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
ADD_LIBRARY(jdns SHARED ${JDNS_SOURCES} ${JDNS_MOC})
|
||||||
|
else()
|
||||||
|
ADD_LIBRARY(jdns STATIC ${JDNS_SOURCES} ${JDNS_MOC})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(jdns
|
||||||
|
${QT_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALL(TARGETS jdns ARCHIVE DESTINATION lib)
|
85
thirdparty/jdns/README
vendored
Normal file
85
thirdparty/jdns/README
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
JDNS
|
||||||
|
----
|
||||||
|
Date: October 1st, 2005
|
||||||
|
Author: Justin Karneges <justin@affinix.com>
|
||||||
|
|
||||||
|
JDNS is a simple DNS implementation that can perform normal DNS queries
|
||||||
|
of any record type (notably SRV), as well as Multicast DNS queries and
|
||||||
|
advertising. Multicast support is based on Jeremie Miller's "mdnsd"
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
For maximum flexibility, JDNS is written in C with no direct dependencies,
|
||||||
|
and is licensed under the MIT license. Your application must supply
|
||||||
|
functionality to JDNS, such as UDP sending/receiving, via callbacks.
|
||||||
|
|
||||||
|
For Qt users there is a wrapper available called QJDns. jdns.pri can
|
||||||
|
be used to include everything into a qmake project. jdns.pro will build
|
||||||
|
the sample Qt-based commandline tool 'jdns'.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- DNS client "stub" resolver
|
||||||
|
- Can fetch any record type, but provides handy decoding for many
|
||||||
|
known types: A, AAAA, SRV, MX, TXT, etc.
|
||||||
|
- Performs retries, caching/expiration, and CNAME following
|
||||||
|
- Algorithm logic adapted from Q3Dns
|
||||||
|
- Multicast queries
|
||||||
|
- Multicast advertising
|
||||||
|
|
||||||
|
Why?
|
||||||
|
- Trolltech is phasing out the Qt DNS implementation, which in Qt 4 has
|
||||||
|
been relegated to the Qt3Support module. A replacement was desired.
|
||||||
|
|
||||||
|
- While there are many DNS libraries available, at the time of this
|
||||||
|
writing it was (and still may be) hard to find one that satisfies
|
||||||
|
three essential conditions: cross-platform friendliness (and this
|
||||||
|
includes Windows 9x!), the ability to integrate into existing
|
||||||
|
eventloops, sensible licensing (ie, not GPL).
|
||||||
|
|
||||||
|
How to use:
|
||||||
|
- Prepare callbacks and call jdns_session_new()
|
||||||
|
- Call jdns_init_unicast() or jdns_init_multicast(), depending on
|
||||||
|
if you want regular or multicast DNS. If you want both kinds, you
|
||||||
|
can always make two sessions.
|
||||||
|
- Make queries and have fun
|
||||||
|
- Call jdns_step() at the right times to advance JDNS processing
|
||||||
|
|
||||||
|
What is left to you:
|
||||||
|
- The callback functions, obviously.
|
||||||
|
- Querying for several "qualified" names. Here is what Q3Dns does:
|
||||||
|
Query for name as provided
|
||||||
|
Query for name + '.domain' (for every domain the computer is in)
|
||||||
|
- Detecting for '.local' in a name to be queried, and using that
|
||||||
|
to decide whether to query via Multicast or normal DNS.
|
||||||
|
- Recognition of IP addresses. If you want an IP address to resolve
|
||||||
|
to itself, then do that yourself. Passing an IP address as a DNS
|
||||||
|
name to JDNS won't work (especially since it wouldn't make any
|
||||||
|
sense in some contexts, like SRV).
|
||||||
|
- Recognition of known hosts. If you want this, compare inputs against
|
||||||
|
jdns_system_dnsparams().
|
||||||
|
- For zeroconf/Bonjour, keep in mind that JDNS only provides Multicast
|
||||||
|
DNS capability. DNS-SD and any higher layers would be your job.
|
||||||
|
|
||||||
|
Using a custom DNS implementation has the drawback that it is difficult
|
||||||
|
to take advantage of platform-specific features (for example, an OS-wide
|
||||||
|
DNS cache or LDAP integration).
|
||||||
|
|
||||||
|
An application strategy for normal DNS should probably be:
|
||||||
|
- If an A or AAAA record is desired, use a native lookup.
|
||||||
|
- Else, if the platform has advanced DNS features already (ie,
|
||||||
|
res_query), use those.
|
||||||
|
- Else, use JDNS.
|
||||||
|
|
||||||
|
However, it may not be a bad idea at first to use JDNS for all occasions,
|
||||||
|
so that it can be debugged.
|
||||||
|
|
||||||
|
For Multicast DNS, awareness of the platform is doubly important. There
|
||||||
|
should only be one Multicast DNS "Responder" per computer, and using JDNS
|
||||||
|
at the same time could result in a conflict.
|
||||||
|
|
||||||
|
An application strategy for Multicast DNS should be:
|
||||||
|
- If the platform has a Multicast DNS daemon installed already, use
|
||||||
|
it somehow.
|
||||||
|
- Else, use JDNS.
|
||||||
|
|
||||||
|
Have fun!
|
||||||
|
|
20
thirdparty/jdns/TODO
vendored
Normal file
20
thirdparty/jdns/TODO
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
(nothing)
|
||||||
|
|
||||||
|
but, this stuff couldn't hurt:
|
||||||
|
fields that need to be an explicit size should use int16_t, etc
|
||||||
|
support for other DNS record types (SOA, NSPTR)
|
||||||
|
detect CNAME loops, rather than looping max times in order to fail
|
||||||
|
don't follow CNAME for SRV (or so I'm told?)
|
||||||
|
if it is not possible to implement DNSSEC outside of jdns, then add the
|
||||||
|
minimal number of hooks to jdns so that it becomes possible
|
||||||
|
use hash tables to speed up the list lookups
|
||||||
|
unit tests
|
||||||
|
qjdns debug lines reworking:
|
||||||
|
init should emit debugLinesReady, and debug should be available
|
||||||
|
immediately after call (the emit will break SS/DS, put a note about
|
||||||
|
this in a comment about init())
|
||||||
|
anywhere else, debugLines should conform to SS, but be emitted at the
|
||||||
|
proper time, not deferred. currently, the debug arrives out of
|
||||||
|
sequence with the other signals, resulting in strange output in the
|
||||||
|
commandline tool.
|
||||||
|
consideration for these changes in jdnsshared
|
3437
thirdparty/jdns/jdns.c
vendored
Normal file
3437
thirdparty/jdns/jdns.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
507
thirdparty/jdns/jdns.h
vendored
Normal file
507
thirdparty/jdns/jdns.h
vendored
Normal file
@@ -0,0 +1,507 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005,2006 Justin Karneges
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JDNS_H
|
||||||
|
#define JDNS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*jdns_object_dtor_func)(void *);
|
||||||
|
typedef void *(*jdns_object_cctor_func)(const void *);
|
||||||
|
|
||||||
|
#define JDNS_OBJECT \
|
||||||
|
jdns_object_dtor_func dtor; \
|
||||||
|
jdns_object_cctor_func cctor;
|
||||||
|
|
||||||
|
#define JDNS_OBJECT_NEW(name) \
|
||||||
|
(name##_t *)jdns_object_new(sizeof(name##_t), \
|
||||||
|
(jdns_object_dtor_func)name##_delete, \
|
||||||
|
(jdns_object_cctor_func)name##_copy);
|
||||||
|
|
||||||
|
typedef struct jdns_object
|
||||||
|
{
|
||||||
|
JDNS_OBJECT
|
||||||
|
} jdns_object_t;
|
||||||
|
|
||||||
|
void *jdns_object_new(int size, void (*dtor)(void *),
|
||||||
|
void *(*cctor)(const void *));
|
||||||
|
void *jdns_object_copy(const void *a);
|
||||||
|
void jdns_object_delete(void *a);
|
||||||
|
void jdns_object_free(void *a);
|
||||||
|
|
||||||
|
#define JDNS_LIST_DECLARE(name) \
|
||||||
|
JDNS_OBJECT \
|
||||||
|
int count; \
|
||||||
|
name##_t **item;
|
||||||
|
|
||||||
|
typedef struct jdns_list
|
||||||
|
{
|
||||||
|
JDNS_OBJECT
|
||||||
|
int count;
|
||||||
|
void **item;
|
||||||
|
int valueList;
|
||||||
|
int autoDelete;
|
||||||
|
} jdns_list_t;
|
||||||
|
|
||||||
|
jdns_list_t *jdns_list_new();
|
||||||
|
jdns_list_t *jdns_list_copy(const jdns_list_t *a);
|
||||||
|
void jdns_list_delete(jdns_list_t *a);
|
||||||
|
void jdns_list_clear(jdns_list_t *a);
|
||||||
|
void jdns_list_insert(jdns_list_t *a, void *item, int pos);
|
||||||
|
void jdns_list_insert_value(jdns_list_t *a, const void *item, int pos);
|
||||||
|
void jdns_list_remove(jdns_list_t *a, void *item);
|
||||||
|
void jdns_list_remove_at(jdns_list_t *a, int pos);
|
||||||
|
|
||||||
|
typedef struct jdns_string
|
||||||
|
{
|
||||||
|
JDNS_OBJECT
|
||||||
|
unsigned char *data;
|
||||||
|
int size;
|
||||||
|
} jdns_string_t;
|
||||||
|
|
||||||
|
jdns_string_t *jdns_string_new();
|
||||||
|
jdns_string_t *jdns_string_copy(const jdns_string_t *s);
|
||||||
|
void jdns_string_delete(jdns_string_t *s);
|
||||||
|
void jdns_string_set(jdns_string_t *s, const unsigned char *str,
|
||||||
|
int str_len);
|
||||||
|
void jdns_string_set_cstr(jdns_string_t *s, const char *str);
|
||||||
|
|
||||||
|
// overlays jdns_list
|
||||||
|
typedef struct jdns_stringlist
|
||||||
|
{
|
||||||
|
JDNS_OBJECT
|
||||||
|
int count;
|
||||||
|
jdns_string_t **item;
|
||||||
|
} jdns_stringlist_t;
|
||||||
|
|
||||||
|
jdns_stringlist_t *jdns_stringlist_new();
|
||||||
|
jdns_stringlist_t *jdns_stringlist_copy(const jdns_stringlist_t *a);
|
||||||
|
void jdns_stringlist_delete(jdns_stringlist_t *a);
|
||||||
|
void jdns_stringlist_append(jdns_stringlist_t *a, const jdns_string_t *str);
|
||||||
|
|
||||||
|
typedef struct jdns_address
|
||||||
|
{
|
||||||
|
int isIpv6;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
unsigned long int v4;
|
||||||
|
unsigned char *v6; // 16 bytes
|
||||||
|
} addr;
|
||||||
|
char *c_str;
|
||||||
|
} jdns_address_t;
|
||||||
|
|
||||||
|
jdns_address_t *jdns_address_new();
|
||||||
|
jdns_address_t *jdns_address_copy(const jdns_address_t *a);
|
||||||
|
void jdns_address_delete(jdns_address_t *a);
|
||||||
|
void jdns_address_set_ipv4(jdns_address_t *a, unsigned long int ipv4);
|
||||||
|
void jdns_address_set_ipv6(jdns_address_t *a, const unsigned char *ipv6);
|
||||||
|
// return 1 if string was ok, else 0. Note: IPv4 addresses only!
|
||||||
|
int jdns_address_set_cstr(jdns_address_t *a, const char *str);
|
||||||
|
// return 1 if the same, else 0
|
||||||
|
int jdns_address_cmp(const jdns_address_t *a, const jdns_address_t *b);
|
||||||
|
|
||||||
|
// convenient predefined addresses/ports
|
||||||
|
#define JDNS_UNICAST_PORT 53
|
||||||
|
#define JDNS_MULTICAST_PORT 5353
|
||||||
|
jdns_address_t *jdns_address_multicast4_new(); // 224.0.0.251
|
||||||
|
jdns_address_t *jdns_address_multicast6_new(); // FF02::FB
|
||||||
|
|
||||||
|
typedef struct jdns_server
|
||||||
|
{
|
||||||
|
unsigned char *name;
|
||||||
|
int port; // SRV only
|
||||||
|
int priority;
|
||||||
|
int weight; // SRV only
|
||||||
|
} jdns_server_t;
|
||||||
|
|
||||||
|
jdns_server_t *jdns_server_new();
|
||||||
|
jdns_server_t *jdns_server_copy(const jdns_server_t *s);
|
||||||
|
void jdns_server_delete(jdns_server_t *s);
|
||||||
|
void jdns_server_set_name(jdns_server_t *s, const unsigned char *name);
|
||||||
|
|
||||||
|
typedef struct jdns_nameserver
|
||||||
|
{
|
||||||
|
jdns_address_t *address;
|
||||||
|
int port;
|
||||||
|
} jdns_nameserver_t;
|
||||||
|
|
||||||
|
jdns_nameserver_t *jdns_nameserver_new();
|
||||||
|
jdns_nameserver_t *jdns_nameserver_copy(const jdns_nameserver_t *a);
|
||||||
|
void jdns_nameserver_delete(jdns_nameserver_t *a);
|
||||||
|
void jdns_nameserver_set(jdns_nameserver_t *a, const jdns_address_t *addr,
|
||||||
|
int port);
|
||||||
|
|
||||||
|
typedef struct jdns_nameserverlist
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
jdns_nameserver_t **item;
|
||||||
|
} jdns_nameserverlist_t;
|
||||||
|
|
||||||
|
jdns_nameserverlist_t *jdns_nameserverlist_new();
|
||||||
|
jdns_nameserverlist_t *jdns_nameserverlist_copy(
|
||||||
|
const jdns_nameserverlist_t *a);
|
||||||
|
void jdns_nameserverlist_delete(jdns_nameserverlist_t *a);
|
||||||
|
void jdns_nameserverlist_append(jdns_nameserverlist_t *a,
|
||||||
|
const jdns_address_t *addr, int port);
|
||||||
|
|
||||||
|
typedef struct jdns_dnshost
|
||||||
|
{
|
||||||
|
jdns_string_t *name;
|
||||||
|
jdns_address_t *address;
|
||||||
|
} jdns_dnshost_t;
|
||||||
|
|
||||||
|
typedef struct jdns_dnshostlist
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
jdns_dnshost_t **item;
|
||||||
|
} jdns_dnshostlist_t;
|
||||||
|
|
||||||
|
typedef struct jdns_dnsparams
|
||||||
|
{
|
||||||
|
jdns_nameserverlist_t *nameservers;
|
||||||
|
jdns_stringlist_t *domains;
|
||||||
|
jdns_dnshostlist_t *hosts;
|
||||||
|
} jdns_dnsparams_t;
|
||||||
|
|
||||||
|
jdns_dnsparams_t *jdns_dnsparams_new();
|
||||||
|
jdns_dnsparams_t *jdns_dnsparams_copy(jdns_dnsparams_t *a);
|
||||||
|
void jdns_dnsparams_delete(jdns_dnsparams_t *a);
|
||||||
|
void jdns_dnsparams_append_nameserver(jdns_dnsparams_t *a,
|
||||||
|
const jdns_address_t *addr, int port);
|
||||||
|
void jdns_dnsparams_append_domain(jdns_dnsparams_t *a,
|
||||||
|
const jdns_string_t *domain);
|
||||||
|
void jdns_dnsparams_append_host(jdns_dnsparams_t *a,
|
||||||
|
const jdns_string_t *name, const jdns_address_t *address);
|
||||||
|
|
||||||
|
#define JDNS_RTYPE_A 1
|
||||||
|
#define JDNS_RTYPE_AAAA 28
|
||||||
|
#define JDNS_RTYPE_MX 15
|
||||||
|
#define JDNS_RTYPE_SRV 33
|
||||||
|
#define JDNS_RTYPE_CNAME 5
|
||||||
|
#define JDNS_RTYPE_PTR 12
|
||||||
|
#define JDNS_RTYPE_TXT 16
|
||||||
|
#define JDNS_RTYPE_HINFO 13
|
||||||
|
#define JDNS_RTYPE_NS 2
|
||||||
|
#define JDNS_RTYPE_ANY 255
|
||||||
|
|
||||||
|
typedef struct jdns_rr
|
||||||
|
{
|
||||||
|
unsigned char *owner;
|
||||||
|
int ttl;
|
||||||
|
int type;
|
||||||
|
int qclass;
|
||||||
|
int rdlength;
|
||||||
|
unsigned char *rdata;
|
||||||
|
int haveKnown;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
jdns_address_t *address; // for A, AAAA
|
||||||
|
jdns_server_t *server; // for MX, SRV
|
||||||
|
unsigned char *name; // for CNAME, PTR, NS
|
||||||
|
jdns_stringlist_t *texts; // for TXT
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
jdns_string_t *cpu;
|
||||||
|
jdns_string_t *os;
|
||||||
|
} hinfo; // for HINFO
|
||||||
|
} data;
|
||||||
|
} jdns_rr_t;
|
||||||
|
|
||||||
|
jdns_rr_t *jdns_rr_new();
|
||||||
|
jdns_rr_t *jdns_rr_copy(const jdns_rr_t *r);
|
||||||
|
void jdns_rr_delete(jdns_rr_t *r);
|
||||||
|
void jdns_rr_set_owner(jdns_rr_t *r, const unsigned char *name);
|
||||||
|
void jdns_rr_set_record(jdns_rr_t *r, int type, const unsigned char *rdata,
|
||||||
|
int rdlength);
|
||||||
|
void jdns_rr_set_A(jdns_rr_t *r, const jdns_address_t *address);
|
||||||
|
void jdns_rr_set_AAAA(jdns_rr_t *r, const jdns_address_t *address);
|
||||||
|
void jdns_rr_set_MX(jdns_rr_t *r, const unsigned char *name, int priority);
|
||||||
|
void jdns_rr_set_SRV(jdns_rr_t *r, const unsigned char *name, int port,
|
||||||
|
int priority, int weight);
|
||||||
|
void jdns_rr_set_CNAME(jdns_rr_t *r, const unsigned char *name);
|
||||||
|
void jdns_rr_set_PTR(jdns_rr_t *r, const unsigned char *name);
|
||||||
|
void jdns_rr_set_TXT(jdns_rr_t *r, const jdns_stringlist_t *texts);
|
||||||
|
void jdns_rr_set_HINFO(jdns_rr_t *r, const jdns_string_t *cpu,
|
||||||
|
const jdns_string_t *os);
|
||||||
|
void jdns_rr_set_NS(jdns_rr_t *r, const unsigned char *name);
|
||||||
|
// note: only works on known types
|
||||||
|
int jdns_rr_verify(const jdns_rr_t *r);
|
||||||
|
|
||||||
|
typedef struct jdns_response
|
||||||
|
{
|
||||||
|
int answerCount;
|
||||||
|
jdns_rr_t **answerRecords;
|
||||||
|
int authorityCount;
|
||||||
|
jdns_rr_t **authorityRecords;
|
||||||
|
int additionalCount;
|
||||||
|
jdns_rr_t **additionalRecords;
|
||||||
|
} jdns_response_t;
|
||||||
|
|
||||||
|
jdns_response_t *jdns_response_new();
|
||||||
|
jdns_response_t *jdns_response_copy(const jdns_response_t *r);
|
||||||
|
void jdns_response_delete(jdns_response_t *r);
|
||||||
|
void jdns_response_append_answer(jdns_response_t *r, const jdns_rr_t *rr);
|
||||||
|
void jdns_response_append_authority(jdns_response_t *r, const jdns_rr_t *rr);
|
||||||
|
void jdns_response_append_additional(jdns_response_t *r,
|
||||||
|
const jdns_rr_t *rr);
|
||||||
|
|
||||||
|
#define JDNS_PUBLISH_SHARED 0x0001
|
||||||
|
#define JDNS_PUBLISH_UNIQUE 0x0002
|
||||||
|
|
||||||
|
#define JDNS_STEP_TIMER 0x0001
|
||||||
|
#define JDNS_STEP_HANDLE 0x0002
|
||||||
|
|
||||||
|
#define JDNS_EVENT_RESPONSE 0x0001
|
||||||
|
#define JDNS_EVENT_PUBLISH 0x0002
|
||||||
|
#define JDNS_EVENT_SHUTDOWN 0x0003
|
||||||
|
|
||||||
|
#define JDNS_STATUS_SUCCESS 0x0001
|
||||||
|
#define JDNS_STATUS_NXDOMAIN 0x0002
|
||||||
|
#define JDNS_STATUS_ERROR 0x0003
|
||||||
|
#define JDNS_STATUS_TIMEOUT 0x0004
|
||||||
|
#define JDNS_STATUS_CONFLICT 0x0005
|
||||||
|
|
||||||
|
typedef struct jdns_session jdns_session_t;
|
||||||
|
|
||||||
|
typedef struct jdns_callbacks
|
||||||
|
{
|
||||||
|
void *app; // user-supplied context
|
||||||
|
|
||||||
|
// time_now:
|
||||||
|
// s: session
|
||||||
|
// app: user-supplied context
|
||||||
|
// return: milliseconds since session started
|
||||||
|
int (*time_now)(jdns_session_t *s, void *app);
|
||||||
|
|
||||||
|
// rand_int:
|
||||||
|
// s: session
|
||||||
|
// app: user-supplied context
|
||||||
|
// return: random integer between 0-65535
|
||||||
|
int (*rand_int)(jdns_session_t *s, void *app);
|
||||||
|
|
||||||
|
// debug_line:
|
||||||
|
// s: session
|
||||||
|
// app: user-supplied context
|
||||||
|
// str: a line of debug text
|
||||||
|
// return: nothing
|
||||||
|
void (*debug_line)(jdns_session_t *s, void *app, const char *str);
|
||||||
|
|
||||||
|
// udp_bind:
|
||||||
|
// s: session
|
||||||
|
// app: user-supplied context
|
||||||
|
// addr: ip address of interface to bind to. 0 for all
|
||||||
|
// port: port of interface to bind to. 0 for any
|
||||||
|
// maddr: multicast address. 0 if not using multicast
|
||||||
|
// return: handle (>0) of bound socket, or 0 on error
|
||||||
|
// note: for multicast, the following must be done:
|
||||||
|
// use SO_REUSEPORT to share with other mdns programs
|
||||||
|
// use IP_ADD_MEMBERSHIP to associate addr and maddr
|
||||||
|
// set IP_MULTICAST_TTL to 255
|
||||||
|
int (*udp_bind)(jdns_session_t *s, void *app,
|
||||||
|
const jdns_address_t *addr, int port,
|
||||||
|
const jdns_address_t *maddr);
|
||||||
|
|
||||||
|
// udp_unbind:
|
||||||
|
// s: session
|
||||||
|
// app: user-supplied context
|
||||||
|
// handle: handle of socket obtained with udp_bind
|
||||||
|
// return: nothing
|
||||||
|
void (*udp_unbind)(jdns_session_t *s, void *app, int handle);
|
||||||
|
|
||||||
|
// udp_read:
|
||||||
|
// s: session
|
||||||
|
// app: user-supplied context
|
||||||
|
// handle: handle of socket obtained with udp_bind
|
||||||
|
// addr: store ip address of sender
|
||||||
|
// port: store port of sender
|
||||||
|
// buf: store packet content
|
||||||
|
// bufsize: value contains max size, to be changed to real size
|
||||||
|
// return: 1 if packet read, 0 if none available
|
||||||
|
int (*udp_read)(jdns_session_t *s, void *app, int handle,
|
||||||
|
jdns_address_t *addr, int *port, unsigned char *buf,
|
||||||
|
int *bufsize);
|
||||||
|
|
||||||
|
// udp_write:
|
||||||
|
// s: session
|
||||||
|
// app: user-supplied context
|
||||||
|
// handle: handle of socket obtained with udp_bind
|
||||||
|
// addr: ip address of recipient
|
||||||
|
// port: port of recipient
|
||||||
|
// buf: packet content
|
||||||
|
// bufsize: size of packet
|
||||||
|
// return: 1 if packet taken for writing, 0 if this is a bad time
|
||||||
|
int (*udp_write)(jdns_session_t *s, void *app, int handle,
|
||||||
|
const jdns_address_t *addr, int port, unsigned char *buf,
|
||||||
|
int bufsize);
|
||||||
|
} jdns_callbacks_t;
|
||||||
|
|
||||||
|
typedef struct jdns_event
|
||||||
|
{
|
||||||
|
int type; // JDNS_EVENT
|
||||||
|
int id; // query id or publish id
|
||||||
|
|
||||||
|
// for query, this can be SUCCESS, NXDOMAIN, ERROR, or TIMEOUT
|
||||||
|
// for publish, this can be SUCCESS, ERROR, or CONFLICT
|
||||||
|
int status;
|
||||||
|
|
||||||
|
// for query
|
||||||
|
jdns_response_t *response;
|
||||||
|
} jdns_event_t;
|
||||||
|
|
||||||
|
void jdns_event_delete(jdns_event_t *e);
|
||||||
|
|
||||||
|
// jdns_session_new:
|
||||||
|
// callbacks: the struct of callbacks
|
||||||
|
// return: newly allocated session
|
||||||
|
jdns_session_t *jdns_session_new(jdns_callbacks_t *callbacks);
|
||||||
|
|
||||||
|
// jdns_session_delete:
|
||||||
|
// s: session to free
|
||||||
|
// return: nothing
|
||||||
|
void jdns_session_delete(jdns_session_t *s);
|
||||||
|
|
||||||
|
// jdns_init_unicast:
|
||||||
|
// s: session
|
||||||
|
// addr: ip address of interface to bind to. NULL for all
|
||||||
|
// port: port of interface to bind to. 0 for any
|
||||||
|
// return: 1 on success, 0 on failure
|
||||||
|
int jdns_init_unicast(jdns_session_t *s, const jdns_address_t *addr,
|
||||||
|
int port);
|
||||||
|
|
||||||
|
// jdns_init_multicast:
|
||||||
|
// s: session
|
||||||
|
// addr: ip address of interface to bind to. NULL for all
|
||||||
|
// port: port of interface to bind to. 0 for any
|
||||||
|
// addr: multicast address to associate with. cannot be NULL
|
||||||
|
// return: 1 on success, 0 on failure
|
||||||
|
int jdns_init_multicast(jdns_session_t *s, const jdns_address_t *addr,
|
||||||
|
int port, const jdns_address_t *maddr);
|
||||||
|
|
||||||
|
// jdns_shutdown:
|
||||||
|
// s: session
|
||||||
|
// return: nothing
|
||||||
|
void jdns_shutdown(jdns_session_t *s);
|
||||||
|
|
||||||
|
// jdns_set_nameservers:
|
||||||
|
// s: session
|
||||||
|
// nslist: list of nameservers
|
||||||
|
// return nothing
|
||||||
|
void jdns_set_nameservers(jdns_session_t *s,
|
||||||
|
const jdns_nameserverlist_t *nslist);
|
||||||
|
|
||||||
|
// jdns_probe:
|
||||||
|
// s: session
|
||||||
|
// return: nothing
|
||||||
|
void jdns_probe(jdns_session_t *s);
|
||||||
|
|
||||||
|
// jdns_query:
|
||||||
|
// s: session
|
||||||
|
// name: the name to look up
|
||||||
|
// rtype: the record type
|
||||||
|
// return: id of this operation
|
||||||
|
int jdns_query(jdns_session_t *s, const unsigned char *name, int rtype);
|
||||||
|
|
||||||
|
// jdns_cancel_query:
|
||||||
|
// s: session
|
||||||
|
// id: the operation id to cancel
|
||||||
|
// return: nothing
|
||||||
|
void jdns_cancel_query(jdns_session_t *s, int id);
|
||||||
|
|
||||||
|
// jdns_publish:
|
||||||
|
// s: session
|
||||||
|
// mode: JDNS_PUBLISH shared or unique
|
||||||
|
// rec: the record data
|
||||||
|
// return: id of this operation
|
||||||
|
// note: supported record types: A, AAAA, SRV, CNAME, PTR, TXT, and HINFO.
|
||||||
|
// if the published type is not one of these, raw rdata must be set.
|
||||||
|
int jdns_publish(jdns_session_t *s, int mode, const jdns_rr_t *rec);
|
||||||
|
|
||||||
|
// jdns_update_publish:
|
||||||
|
// s: session
|
||||||
|
// id: the operation id to update
|
||||||
|
// rec: the record data
|
||||||
|
// return: nothing
|
||||||
|
// note: update only works on successfully published records, and no event
|
||||||
|
// is generated for a successful update.
|
||||||
|
void jdns_update_publish(jdns_session_t *s, int id, const jdns_rr_t *rec);
|
||||||
|
|
||||||
|
// jdns_cancel_publish:
|
||||||
|
// s: session
|
||||||
|
// id: the operation id to cancel
|
||||||
|
// return: nothing
|
||||||
|
void jdns_cancel_publish(jdns_session_t *s, int id);
|
||||||
|
|
||||||
|
// jdns_step:
|
||||||
|
// s: session
|
||||||
|
// return: JDNS_STEP flags OR'd together
|
||||||
|
int jdns_step(jdns_session_t *s);
|
||||||
|
|
||||||
|
// jdns_next_timer:
|
||||||
|
// s: session
|
||||||
|
// return: milliseconds until timeout
|
||||||
|
int jdns_next_timer(jdns_session_t *s);
|
||||||
|
|
||||||
|
// jdns_set_handle_readable:
|
||||||
|
// s: session
|
||||||
|
// handle: handle that is now readable
|
||||||
|
// return: nothing
|
||||||
|
void jdns_set_handle_readable(jdns_session_t *s, int handle);
|
||||||
|
|
||||||
|
// jdns_set_handle_writable:
|
||||||
|
// s: session
|
||||||
|
// handle: handle that is now writable
|
||||||
|
// return: nothing
|
||||||
|
void jdns_set_handle_writable(jdns_session_t *s, int handle);
|
||||||
|
|
||||||
|
// jdns_next_event:
|
||||||
|
// s: session
|
||||||
|
// return: newly allocated event, or zero if none are ready
|
||||||
|
jdns_event_t *jdns_next_event(jdns_session_t *s);
|
||||||
|
|
||||||
|
// jdns_system_dnsparams:
|
||||||
|
// return: newly allocated dnsparams from the system
|
||||||
|
jdns_dnsparams_t *jdns_system_dnsparams();
|
||||||
|
|
||||||
|
// jdns_set_hold_ids_enabled
|
||||||
|
// s: session
|
||||||
|
// enabled: whether to enable id holding. default is 0 (disabled)
|
||||||
|
// return: nothing
|
||||||
|
// normally, when a unicast query completes or any kind of query or publish
|
||||||
|
// operation results in an error, the operation is automatically "canceled".
|
||||||
|
// when id holding is enabled, the operation still stops internally, but the
|
||||||
|
// id value used by that operation is "held" until the application
|
||||||
|
// explicitly calls jdns_cancel_query() or jdns_cancel_publish() to release
|
||||||
|
// it. this allows the application to ensure there is no ambiguity when
|
||||||
|
// determining which operation a particular event belongs to. it is disabled
|
||||||
|
// be default so as to not introduce memory leaks in existing applications,
|
||||||
|
// however new applications really should use it.
|
||||||
|
void jdns_set_hold_ids_enabled(jdns_session_t *s, int enabled);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
27
thirdparty/jdns/jdns.pri
vendored
Normal file
27
thirdparty/jdns/jdns.pri
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# qmake project include file
|
||||||
|
|
||||||
|
QT *= network
|
||||||
|
|
||||||
|
windows:{
|
||||||
|
LIBS += -lWs2_32 -lAdvapi32
|
||||||
|
}
|
||||||
|
unix:{
|
||||||
|
#QMAKE_CFLAGS += -pedantic
|
||||||
|
}
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/jdns_packet.h \
|
||||||
|
$$PWD/jdns_mdnsd.h \
|
||||||
|
$$PWD/jdns_p.h \
|
||||||
|
$$PWD/jdns.h \
|
||||||
|
$$PWD/qjdns_sock.h \
|
||||||
|
$$PWD/qjdns.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/jdns_util.c \
|
||||||
|
$$PWD/jdns_packet.c \
|
||||||
|
$$PWD/jdns_mdnsd.c \
|
||||||
|
$$PWD/jdns_sys.c \
|
||||||
|
$$PWD/jdns.c \
|
||||||
|
$$PWD/qjdns_sock.cpp \
|
||||||
|
$$PWD/qjdns.cpp
|
9
thirdparty/jdns/jdns.pro
vendored
Normal file
9
thirdparty/jdns/jdns.pro
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
CONFIG += console
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
QT -= gui
|
||||||
|
QT += network
|
||||||
|
|
||||||
|
include(jdns.pri)
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
main.cpp
|
1125
thirdparty/jdns/jdns_mdnsd.c
vendored
Normal file
1125
thirdparty/jdns/jdns_mdnsd.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
120
thirdparty/jdns/jdns_mdnsd.h
vendored
Normal file
120
thirdparty/jdns/jdns_mdnsd.h
vendored
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Jeremie Miller
|
||||||
|
* Copyright (C) 2005,2006 Justin Karneges
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JDNS_MDNSD_H
|
||||||
|
#define JDNS_MDNSD_H
|
||||||
|
|
||||||
|
#include "jdns_p.h"
|
||||||
|
|
||||||
|
struct mytimeval
|
||||||
|
{
|
||||||
|
unsigned long int tv_sec; /* seconds */
|
||||||
|
unsigned long int tv_usec; /* microseconds */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct mdnsd_struct *mdnsd; // main daemon data
|
||||||
|
typedef struct mdnsdr_struct *mdnsdr; // record entry
|
||||||
|
// answer data
|
||||||
|
typedef struct mdnsda_struct
|
||||||
|
{
|
||||||
|
unsigned char *name;
|
||||||
|
unsigned short int type;
|
||||||
|
unsigned long int ttl;
|
||||||
|
unsigned long int real_ttl;
|
||||||
|
unsigned short int rdlen;
|
||||||
|
unsigned char *rdata;
|
||||||
|
unsigned long int ip; // A
|
||||||
|
unsigned char *rdname; // NS/CNAME/PTR/SRV
|
||||||
|
struct { unsigned short int priority, weight, port; } srv; // SRV
|
||||||
|
} *mdnsda;
|
||||||
|
|
||||||
|
///////////
|
||||||
|
// Global functions
|
||||||
|
//
|
||||||
|
// create a new mdns daemon for the given class of names (usually 1) and maximum frame size
|
||||||
|
mdnsd mdnsd_new(int class, int frame, int port, int (*time_now)(mdnsd d, void *arg), int (*rand_int)(mdnsd d, void *arg), void *arg);
|
||||||
|
//
|
||||||
|
// gracefully shutdown the daemon, use mdnsd_out() to get the last packets
|
||||||
|
void mdnsd_shutdown(mdnsd d);
|
||||||
|
//
|
||||||
|
// flush all cached records (network/interface changed)
|
||||||
|
void mdnsd_flush(mdnsd d);
|
||||||
|
//
|
||||||
|
// free given mdnsd (should have used mdnsd_shutdown() first!)
|
||||||
|
void mdnsd_free(mdnsd d);
|
||||||
|
//
|
||||||
|
///////////
|
||||||
|
|
||||||
|
///////////
|
||||||
|
// I/O functions
|
||||||
|
//
|
||||||
|
// incoming message from host (to be cached/processed)
|
||||||
|
void mdnsd_in(mdnsd d, const jdns_packet_t *m, const jdns_response_t *resp, const jdns_address_t *addr, unsigned short int port);
|
||||||
|
//
|
||||||
|
// outgoing messge to be delivered to host, returns >0 if one was returned and m/ip/port set
|
||||||
|
int mdnsd_out(mdnsd d, jdns_packet_t **m, jdns_address_t **addr, unsigned short int *port);
|
||||||
|
//
|
||||||
|
// returns the max wait-time until mdnsd_out() needs to be called again
|
||||||
|
struct mytimeval *mdnsd_sleep(mdnsd d);
|
||||||
|
//
|
||||||
|
////////////
|
||||||
|
|
||||||
|
///////////
|
||||||
|
// Q/A functions
|
||||||
|
//
|
||||||
|
// register a new query
|
||||||
|
// answer(record, arg) is called whenever one is found/changes/expires (immediate or anytime after, mdnsda valid until ->ttl==0)
|
||||||
|
// either answer returns -1, or another mdnsd_query with a NULL answer will remove/unregister this query
|
||||||
|
void mdnsd_query(mdnsd d, char *host, int type, int (*answer)(mdnsda a, void *arg), void *arg);
|
||||||
|
//
|
||||||
|
// returns the first (if last == NULL) or next answer after last from the cache
|
||||||
|
// mdnsda only valid until an I/O function is called
|
||||||
|
mdnsda mdnsd_list(mdnsd d, char *host, int type, mdnsda last);
|
||||||
|
//
|
||||||
|
///////////
|
||||||
|
|
||||||
|
///////////
|
||||||
|
// Publishing functions
|
||||||
|
//
|
||||||
|
// create a new unique record (try mdnsda_list first to make sure it's not used)
|
||||||
|
// conflict(arg) called at any point when one is detected and unable to recover
|
||||||
|
// after the first data is set_*(), any future changes effectively expire the old one and attempt to create a new unique record
|
||||||
|
mdnsdr mdnsd_unique(mdnsd d, char *host, int type, long int ttl, void (*pubresult)(int result, char *host, int type, void *arg), void *arg);
|
||||||
|
//
|
||||||
|
// create a new shared record
|
||||||
|
mdnsdr mdnsd_shared(mdnsd d, char *host, int type, long int ttl);
|
||||||
|
//
|
||||||
|
// de-list the given record
|
||||||
|
void mdnsd_done(mdnsd d, mdnsdr r);
|
||||||
|
//
|
||||||
|
// these all set/update the data for the given record, nothing is published until they are called
|
||||||
|
void mdnsd_set_raw(mdnsd d, mdnsdr r, char *data, int len);
|
||||||
|
void mdnsd_set_host(mdnsd d, mdnsdr r, char *name);
|
||||||
|
void mdnsd_set_ip(mdnsd d, mdnsdr r, unsigned long int ip);
|
||||||
|
void mdnsd_set_srv(mdnsd d, mdnsdr r, int priority, int weight, int port, char *name);
|
||||||
|
//
|
||||||
|
///////////
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
95
thirdparty/jdns/jdns_p.h
vendored
Normal file
95
thirdparty/jdns/jdns_p.h
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2008 Justin Karneges
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JDNS_P_H
|
||||||
|
#define JDNS_P_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||||||
|
# define JDNS_OS_WIN
|
||||||
|
#else
|
||||||
|
# define JDNS_OS_UNIX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||||
|
# define JDNS_OS_FREEBSD
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
# define JDNS_OS_NETBSD
|
||||||
|
#elif defined(sun) || defined(__sun)
|
||||||
|
# define JDNS_OS_SOLARIS
|
||||||
|
#elif defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__))
|
||||||
|
# define JDNS_OS_MAC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JDNS_OS_WIN
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JDNS_OS_UNIX
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "jdns.h"
|
||||||
|
#include "jdns_packet.h"
|
||||||
|
|
||||||
|
// jdns_util.c
|
||||||
|
void *jdns_alloc(int size);
|
||||||
|
void *jdns_realloc(void *p, int size);
|
||||||
|
void jdns_free(void *p);
|
||||||
|
char *jdns_strdup(const char *s);
|
||||||
|
unsigned char *jdns_copy_array(const unsigned char *src, int size);
|
||||||
|
int jdns_domain_cmp(const unsigned char *a, const unsigned char *b);
|
||||||
|
|
||||||
|
int jdns_sprintf_s(char *str, int n, const char *format, ...);
|
||||||
|
int jdns_vsprintf_s(char *str, int n, const char *format, va_list ap);
|
||||||
|
FILE *jdns_fopen(const char *path, const char *mode);
|
||||||
|
jdns_string_t *jdns_getenv(const char *name);
|
||||||
|
char *jdns_strcpy(char *dst, const char *src);
|
||||||
|
|
||||||
|
int jdns_string_indexOf(const jdns_string_t *s, unsigned char c, int pos);
|
||||||
|
jdns_stringlist_t *jdns_string_split(const jdns_string_t *s, unsigned char sep);
|
||||||
|
|
||||||
|
jdns_dnshost_t *jdns_dnshost_new();
|
||||||
|
jdns_dnshost_t *jdns_dnshost_copy(const jdns_dnshost_t *a);
|
||||||
|
void jdns_dnshost_delete(jdns_dnshost_t *a);
|
||||||
|
jdns_dnshostlist_t *jdns_dnshostlist_new();
|
||||||
|
jdns_dnshostlist_t *jdns_dnshostlist_copy(const jdns_dnshostlist_t *a);
|
||||||
|
void jdns_dnshostlist_delete(jdns_dnshostlist_t *a);
|
||||||
|
void jdns_dnshostlist_append(jdns_dnshostlist_t *a, const jdns_dnshost_t *host);
|
||||||
|
|
||||||
|
jdns_rr_t *jdns_rr_from_resource(const jdns_packet_resource_t *pr, const jdns_packet_t *ref);
|
||||||
|
void jdns_response_remove_extra(jdns_response_t *r);
|
||||||
|
void jdns_response_remove_answer(jdns_response_t *r, int pos);
|
||||||
|
|
||||||
|
#define alloc_type(type) (type *)jdns_alloc(sizeof(type))
|
||||||
|
#define _ustrdup(str) (unsigned char *)jdns_strdup((const char *)str)
|
||||||
|
#define _ustrlen(str) strlen((const char *)str)
|
||||||
|
#define _ustrcmp(a, b) strcmp((const char *)a, (const char *)b)
|
||||||
|
|
||||||
|
#endif
|
1008
thirdparty/jdns/jdns_packet.c
vendored
Normal file
1008
thirdparty/jdns/jdns_packet.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
116
thirdparty/jdns/jdns_packet.h
vendored
Normal file
116
thirdparty/jdns/jdns_packet.h
vendored
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2006 Justin Karneges
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JDNS_PACKET_H
|
||||||
|
#define JDNS_PACKET_H
|
||||||
|
|
||||||
|
#include "jdns.h"
|
||||||
|
|
||||||
|
// -- howto --
|
||||||
|
//
|
||||||
|
// writing packets:
|
||||||
|
// 1) call jdns_packet_new()
|
||||||
|
// 2) populate the jdns_packet_t structure, using the functions
|
||||||
|
// as necessary
|
||||||
|
// 3) call jdns_packet_export() to populate the raw data of the packet
|
||||||
|
//
|
||||||
|
// reading packets:
|
||||||
|
// 1) call jdns_packet_new()
|
||||||
|
// 2) call jdns_packet_import() with the raw data
|
||||||
|
// 3) the jdns_packet_t structure is now populated
|
||||||
|
//
|
||||||
|
// IMPORTANT: all names must be valid. that is, ending in a dot character
|
||||||
|
|
||||||
|
int jdns_packet_name_isvalid(const unsigned char *name, int size); // 0 if not valid
|
||||||
|
|
||||||
|
typedef struct jdns_packet_question
|
||||||
|
{
|
||||||
|
JDNS_OBJECT
|
||||||
|
jdns_string_t *qname;
|
||||||
|
unsigned short int qtype, qclass;
|
||||||
|
} jdns_packet_question_t;
|
||||||
|
|
||||||
|
jdns_packet_question_t *jdns_packet_question_new();
|
||||||
|
jdns_packet_question_t *jdns_packet_question_copy(const jdns_packet_question_t *a);
|
||||||
|
void jdns_packet_question_delete(jdns_packet_question_t *a);
|
||||||
|
|
||||||
|
typedef struct jdns_packet_write jdns_packet_write_t;
|
||||||
|
typedef struct jdns_packet jdns_packet_t;
|
||||||
|
|
||||||
|
typedef struct jdns_packet_resource
|
||||||
|
{
|
||||||
|
JDNS_OBJECT
|
||||||
|
jdns_string_t *qname;
|
||||||
|
unsigned short int qtype, qclass;
|
||||||
|
unsigned long int ttl; // 31-bit number, top bit always 0
|
||||||
|
unsigned short int rdlength;
|
||||||
|
unsigned char *rdata;
|
||||||
|
|
||||||
|
// private
|
||||||
|
jdns_list_t *writelog; // jdns_packet_write_t
|
||||||
|
} jdns_packet_resource_t;
|
||||||
|
|
||||||
|
jdns_packet_resource_t *jdns_packet_resource_new();
|
||||||
|
jdns_packet_resource_t *jdns_packet_resource_copy(const jdns_packet_resource_t *a);
|
||||||
|
void jdns_packet_resource_delete(jdns_packet_resource_t *a);
|
||||||
|
void jdns_packet_resource_add_bytes(jdns_packet_resource_t *a, const unsigned char *data, int size);
|
||||||
|
void jdns_packet_resource_add_name(jdns_packet_resource_t *a, const jdns_string_t *name);
|
||||||
|
int jdns_packet_resource_read_name(const jdns_packet_resource_t *a, const jdns_packet_t *p, int *at, jdns_string_t **name);
|
||||||
|
|
||||||
|
struct jdns_packet
|
||||||
|
{
|
||||||
|
JDNS_OBJECT
|
||||||
|
unsigned short int id;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned short qr, opcode, aa, tc, rd, ra, z, rcode;
|
||||||
|
} opts;
|
||||||
|
|
||||||
|
// item counts as specified by the packet. do not use these
|
||||||
|
// for iteration over the item lists, since they can be wrong
|
||||||
|
// if the packet is truncated.
|
||||||
|
int qdcount, ancount, nscount, arcount;
|
||||||
|
|
||||||
|
// value lists
|
||||||
|
jdns_list_t *questions; // jdns_packet_question_t
|
||||||
|
jdns_list_t *answerRecords; // jdns_packet_resource_t
|
||||||
|
jdns_list_t *authorityRecords; // jdns_packet_resource_t
|
||||||
|
jdns_list_t *additionalRecords; // jdns_packet_resource_t
|
||||||
|
|
||||||
|
// since dns packets are allowed to be truncated, it is possible
|
||||||
|
// for a packet to not get fully parsed yet still be considered
|
||||||
|
// successfully parsed. this flag means the packet was fully
|
||||||
|
// parsed also.
|
||||||
|
int fully_parsed;
|
||||||
|
|
||||||
|
int raw_size;
|
||||||
|
unsigned char *raw_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
jdns_packet_t *jdns_packet_new();
|
||||||
|
jdns_packet_t *jdns_packet_copy(const jdns_packet_t *a);
|
||||||
|
void jdns_packet_delete(jdns_packet_t *a);
|
||||||
|
int jdns_packet_import(jdns_packet_t **a, const unsigned char *data, int size); // 0 on fail
|
||||||
|
int jdns_packet_export(jdns_packet_t *a, int maxsize); // 0 on fail
|
||||||
|
|
||||||
|
#endif
|
850
thirdparty/jdns/jdns_sys.c
vendored
Normal file
850
thirdparty/jdns/jdns_sys.c
vendored
Normal file
@@ -0,0 +1,850 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2008 Justin Karneges
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
this code probes the system for dns settings. blah.
|
||||||
|
|
||||||
|
q3dns strategies
|
||||||
|
----------------
|
||||||
|
|
||||||
|
windows:
|
||||||
|
|
||||||
|
domain name, name server, "search list" found in windows registry here:
|
||||||
|
|
||||||
|
HKEY_LOCAL_MACHINE
|
||||||
|
System\CurrentControlSet\Services\Tcpip\Parameters <-- win nt+
|
||||||
|
System\CurrentControlSet\Services\VxD\MSTCP <-- win 98
|
||||||
|
|
||||||
|
for domain, try DhcpDomain else Domain
|
||||||
|
for name servers, try DhcpNameServer, else NameServer
|
||||||
|
for search list, try SearchList
|
||||||
|
|
||||||
|
iphlpapi.dll : GetNetworkParams(PFIXED_INFO, PULONG);
|
||||||
|
|
||||||
|
info->DomainName
|
||||||
|
info->DnsServerList (if not null, use it, and loop through ->Next until
|
||||||
|
null)
|
||||||
|
no search list
|
||||||
|
|
||||||
|
first try getnetworkparams. if that fails, try the nt regkey then the 98
|
||||||
|
regkey. it seems that search list can only come from the registry, so
|
||||||
|
maybe we need to grab that entry even if getnetworkparams works.
|
||||||
|
|
||||||
|
in the case of the registry, the nameserver and searchlist entries are
|
||||||
|
delimited by spaces on win nt and commas on win 98. probably a good
|
||||||
|
idea to simplify white space first (chop away space at start and end,
|
||||||
|
reduce all sections of spaces to one char). also, lowercase the search
|
||||||
|
list.
|
||||||
|
|
||||||
|
qt doesn't read the hosts file on windows. this might be a good idea, but
|
||||||
|
probably not worth it.
|
||||||
|
|
||||||
|
unix:
|
||||||
|
|
||||||
|
read /etc/resolv.conf manually:
|
||||||
|
for each line, split at spaces
|
||||||
|
if the first item is "nameserver", then there should be an IP address
|
||||||
|
following it. note: may contain mixed ipv4 and ipv6 addresses
|
||||||
|
if the first item is "search", all other items are added to the domain
|
||||||
|
list
|
||||||
|
if the first item is "domain", then the next item should be added to the
|
||||||
|
domain list.
|
||||||
|
do case-insensitive matching for the item types
|
||||||
|
for search/domain, the items are in the 8-bit system locale
|
||||||
|
|
||||||
|
info can also be fetched using system calls. we use the res_* stuff here.
|
||||||
|
first we should detect for a "modern res api". this is available from
|
||||||
|
glibc 2.3 and onward. use the following scheme to check for it:
|
||||||
|
|
||||||
|
#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2)
|
||||||
|
&& (__GLIBC_MINOR__ >= 3)))
|
||||||
|
// modern res api
|
||||||
|
#endif
|
||||||
|
|
||||||
|
on mac we should look up res_init in the system library. see:
|
||||||
|
qt_mac_resolve_sys(RTLD_NEXT, "res_init"); for a hint.
|
||||||
|
otherwise we can just use res_init() straight.
|
||||||
|
|
||||||
|
under a modern res api, we do:
|
||||||
|
struct __res_state res;
|
||||||
|
res_ninit(&res);
|
||||||
|
otherwise, we simply call res_init(). for the modern api, we use the "res"
|
||||||
|
struct that we made. otherwise, we use the global "_res" struct.
|
||||||
|
|
||||||
|
read the res struct to obtain the name servers, search list, and domain.
|
||||||
|
lowercase the search list and domain.
|
||||||
|
|
||||||
|
qt tries the file, and if that fails it tries the syscalls. we may want to
|
||||||
|
do the syscalls first, or even just do both all the time.
|
||||||
|
|
||||||
|
read /etc/hosts manually:
|
||||||
|
for each line
|
||||||
|
if there is a '#' character in the line, remove it and everything to
|
||||||
|
the right
|
||||||
|
simplify white space
|
||||||
|
convert to lowercase
|
||||||
|
split the line at spaces
|
||||||
|
first item is the ip address
|
||||||
|
all remaining items are hostnames
|
||||||
|
|
||||||
|
note: these hosts could also be used for reverse-dns too
|
||||||
|
note2: Windows has a hosts file as well (like C:\WINDOWS\hosts)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jdns_p.h"
|
||||||
|
|
||||||
|
#ifdef JDNS_OS_WIN
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JDNS_OS_UNIX
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# include <arpa/nameser.h>
|
||||||
|
# include <resolv.h>
|
||||||
|
# include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define string_indexOf jdns_string_indexOf
|
||||||
|
#define string_split jdns_string_split
|
||||||
|
|
||||||
|
static int char_isspace(unsigned char c)
|
||||||
|
{
|
||||||
|
if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char *string_getnextword(unsigned char *in, int size, int pos, int *newpos)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
int at;
|
||||||
|
int len;
|
||||||
|
unsigned char *out;
|
||||||
|
|
||||||
|
at = pos;
|
||||||
|
|
||||||
|
// skip any space at the start
|
||||||
|
while(at < size && char_isspace(in[at]))
|
||||||
|
++at;
|
||||||
|
|
||||||
|
// all space? no word then
|
||||||
|
if(at >= size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// skip until a space or end
|
||||||
|
n = at;
|
||||||
|
while(n < size && !char_isspace(in[n]))
|
||||||
|
++n;
|
||||||
|
len = n - at;
|
||||||
|
|
||||||
|
// allocate length + zero byte
|
||||||
|
out = (unsigned char *)jdns_alloc(len + 1);
|
||||||
|
if(!out)
|
||||||
|
return 0;
|
||||||
|
memcpy(out, in + at, len);
|
||||||
|
out[len] = 0;
|
||||||
|
*newpos = at + len;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jdns_string_t *string_simplify(const jdns_string_t *in)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
int pos;
|
||||||
|
int total;
|
||||||
|
unsigned char *out;
|
||||||
|
int outlen;
|
||||||
|
jdns_string_t *outstr;
|
||||||
|
jdns_stringlist_t *wordlist;
|
||||||
|
|
||||||
|
// gather words and total of lengths
|
||||||
|
pos = 0;
|
||||||
|
total = 0;
|
||||||
|
wordlist = jdns_stringlist_new();
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
jdns_string_t *word;
|
||||||
|
unsigned char *str = string_getnextword(in->data, in->size, pos, &pos);
|
||||||
|
if(!str)
|
||||||
|
break;
|
||||||
|
word = jdns_string_new();
|
||||||
|
jdns_string_set_cstr(word, (char *)str);
|
||||||
|
jdns_free(str);
|
||||||
|
jdns_stringlist_append(wordlist, word);
|
||||||
|
total += word->size;
|
||||||
|
jdns_string_delete(word);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(total == 0)
|
||||||
|
{
|
||||||
|
jdns_stringlist_delete(wordlist);
|
||||||
|
|
||||||
|
outstr = jdns_string_new();
|
||||||
|
jdns_string_set_cstr(outstr, "");
|
||||||
|
return outstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to allocate space for total lengths and wordcount-1 spaces
|
||||||
|
outlen = total + (wordlist->count - 1);
|
||||||
|
out = (unsigned char *)jdns_alloc(outlen);
|
||||||
|
|
||||||
|
// lay out the words
|
||||||
|
pos = 0;
|
||||||
|
for(n = 0; n < wordlist->count; ++n)
|
||||||
|
{
|
||||||
|
unsigned char *data = wordlist->item[n]->data;
|
||||||
|
int size = wordlist->item[n]->size;
|
||||||
|
memcpy(out + pos, data, size);
|
||||||
|
pos += size;
|
||||||
|
|
||||||
|
// if this is not the last word, append a space
|
||||||
|
if(n + 1 < wordlist->count)
|
||||||
|
out[pos++] = ' ';
|
||||||
|
}
|
||||||
|
jdns_stringlist_delete(wordlist);
|
||||||
|
|
||||||
|
outstr = jdns_string_new();
|
||||||
|
jdns_string_set(outstr, out, outlen);
|
||||||
|
jdns_free(out);
|
||||||
|
return outstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jdns_string_t *string_tolower(const jdns_string_t *in)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
jdns_string_t *out = jdns_string_copy(in);
|
||||||
|
for(n = 0; n < out->size; ++n)
|
||||||
|
out->data[n] = tolower(out->data[n]);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jdns_string_t *file_nextline(FILE *f)
|
||||||
|
{
|
||||||
|
int at, size;
|
||||||
|
unsigned char *buf;
|
||||||
|
jdns_string_t *str;
|
||||||
|
|
||||||
|
size = 1023;
|
||||||
|
buf = (unsigned char *)jdns_alloc(size);
|
||||||
|
at = 0;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
unsigned char c = fgetc(f);
|
||||||
|
if(feof(f))
|
||||||
|
{
|
||||||
|
if(at > 0)
|
||||||
|
{
|
||||||
|
// if we read at least one char, take it as a
|
||||||
|
// line
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jdns_free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(c == '\n')
|
||||||
|
break;
|
||||||
|
if(c == '\r')
|
||||||
|
continue;
|
||||||
|
if(at < 1023)
|
||||||
|
buf[at++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = jdns_string_new();
|
||||||
|
jdns_string_set(str, buf, at);
|
||||||
|
jdns_free(buf);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jdns_dnshostlist_t *read_hosts_file(const char *path)
|
||||||
|
{
|
||||||
|
jdns_dnshostlist_t *out;
|
||||||
|
FILE *f;
|
||||||
|
jdns_string_t *line, *simp;
|
||||||
|
jdns_stringlist_t *parts;
|
||||||
|
jdns_address_t *addr;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
out = jdns_dnshostlist_new();
|
||||||
|
|
||||||
|
f = jdns_fopen(path, "r");
|
||||||
|
if(!f)
|
||||||
|
return out;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
line = file_nextline(f);
|
||||||
|
if(!line)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// truncate at comment
|
||||||
|
n = string_indexOf(line, '#', 0);
|
||||||
|
if(n != -1)
|
||||||
|
{
|
||||||
|
line->size = n;
|
||||||
|
line->data[n] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
simp = string_simplify(line);
|
||||||
|
jdns_string_delete(line);
|
||||||
|
|
||||||
|
parts = string_split(simp, ' ');
|
||||||
|
jdns_string_delete(simp);
|
||||||
|
|
||||||
|
if(parts->count < 2)
|
||||||
|
{
|
||||||
|
jdns_stringlist_delete(parts);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = jdns_address_new();
|
||||||
|
if(!jdns_address_set_cstr(addr, (const char *)parts->item[0]->data))
|
||||||
|
{
|
||||||
|
jdns_address_delete(addr);
|
||||||
|
jdns_stringlist_delete(parts);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(n = 1; n < parts->count; ++n)
|
||||||
|
{
|
||||||
|
jdns_dnshost_t *h = jdns_dnshost_new();
|
||||||
|
h->name = jdns_string_copy(parts->item[n]);
|
||||||
|
h->address = jdns_address_copy(addr);
|
||||||
|
jdns_dnshostlist_append(out, h);
|
||||||
|
jdns_dnshost_delete(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
jdns_address_delete(addr);
|
||||||
|
jdns_stringlist_delete(parts);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apply_hosts_file(jdns_dnsparams_t *a, const char *path)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
jdns_dnshostlist_t *list;
|
||||||
|
|
||||||
|
list = read_hosts_file(path);
|
||||||
|
for(n = 0; n < list->count; ++n)
|
||||||
|
jdns_dnshostlist_append(a->hosts, list->item[n]);
|
||||||
|
jdns_dnshostlist_delete(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dnsparams_have_domain(const jdns_dnsparams_t *a, const jdns_string_t *domain)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
for(n = 0; n < a->domains->count; ++n)
|
||||||
|
{
|
||||||
|
jdns_string_t *str = a->domains->item[n];
|
||||||
|
if(strcmp((const char *)str->data, (const char *)domain->data) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JDNS_OS_WIN
|
||||||
|
|
||||||
|
// from Microsoft IPTypes.h
|
||||||
|
#ifndef IP_TYPES_INCLUDED
|
||||||
|
#define MAX_HOSTNAME_LEN 128
|
||||||
|
#define MAX_DOMAIN_NAME_LEN 128
|
||||||
|
#define MAX_SCOPE_ID_LEN 256
|
||||||
|
typedef struct {
|
||||||
|
char String[4 * 4];
|
||||||
|
} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
|
||||||
|
typedef struct _IP_ADDR_STRING {
|
||||||
|
struct _IP_ADDR_STRING* Next;
|
||||||
|
IP_ADDRESS_STRING IpAddress;
|
||||||
|
IP_MASK_STRING IpMask;
|
||||||
|
DWORD Context;
|
||||||
|
} IP_ADDR_STRING, *PIP_ADDR_STRING;
|
||||||
|
typedef struct {
|
||||||
|
char HostName[MAX_HOSTNAME_LEN + 4] ;
|
||||||
|
char DomainName[MAX_DOMAIN_NAME_LEN + 4];
|
||||||
|
PIP_ADDR_STRING CurrentDnsServer;
|
||||||
|
IP_ADDR_STRING DnsServerList;
|
||||||
|
UINT NodeType;
|
||||||
|
char ScopeId[MAX_SCOPE_ID_LEN + 4];
|
||||||
|
UINT EnableRouting;
|
||||||
|
UINT EnableProxy;
|
||||||
|
UINT EnableDns;
|
||||||
|
} FIXED_INFO, *PFIXED_INFO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef DWORD (WINAPI *GetNetworkParamsFunc)(PFIXED_INFO, PULONG);
|
||||||
|
|
||||||
|
static jdns_string_t *reg_readString(HKEY hk, const char *subkey)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
DWORD bufsize;
|
||||||
|
int ret;
|
||||||
|
jdns_string_t *str = 0;
|
||||||
|
|
||||||
|
bufsize = 1024;
|
||||||
|
buf = (char *)jdns_alloc((int)bufsize);
|
||||||
|
if(!buf)
|
||||||
|
return 0;
|
||||||
|
ret = RegQueryValueExA(hk, subkey, 0, 0, (LPBYTE)buf, &bufsize);
|
||||||
|
if(ret == ERROR_MORE_DATA)
|
||||||
|
{
|
||||||
|
buf = (char *)jdns_realloc(buf, bufsize);
|
||||||
|
if(!buf)
|
||||||
|
{
|
||||||
|
jdns_free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret = RegQueryValueExA(hk, subkey, 0, 0, (LPBYTE)buf, &bufsize);
|
||||||
|
}
|
||||||
|
if(ret == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
str = jdns_string_new();
|
||||||
|
jdns_string_set_cstr(str, (char *)buf);
|
||||||
|
}
|
||||||
|
jdns_free(buf);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jdns_dnsparams_t *dnsparams_get_winreg()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
jdns_dnsparams_t *params;
|
||||||
|
HKEY key;
|
||||||
|
int ret;
|
||||||
|
char sep;
|
||||||
|
jdns_string_t *str_domain, *str_nameserver, *str_searchlist;
|
||||||
|
jdns_stringlist_t *list_nameserver, *list_searchlist;
|
||||||
|
|
||||||
|
sep = ' ';
|
||||||
|
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
|
||||||
|
0, KEY_READ, &key);
|
||||||
|
if(ret != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
sep = ',';
|
||||||
|
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
"System\\CurrentControlSet\\Services\\VxD\\MSTCP",
|
||||||
|
0, KEY_READ, &key);
|
||||||
|
if(ret != ERROR_SUCCESS)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
str_domain = reg_readString(key, "DhcpDomain");
|
||||||
|
if(!str_domain)
|
||||||
|
str_domain = reg_readString(key, "Domain");
|
||||||
|
str_nameserver = reg_readString(key, "DhcpNameServer");
|
||||||
|
if(!str_nameserver)
|
||||||
|
str_nameserver = reg_readString(key, "NameServer");
|
||||||
|
str_searchlist = reg_readString(key, "SearchList");
|
||||||
|
|
||||||
|
RegCloseKey(key);
|
||||||
|
|
||||||
|
list_nameserver = 0;
|
||||||
|
if(str_nameserver)
|
||||||
|
{
|
||||||
|
list_nameserver = string_split(str_nameserver, sep);
|
||||||
|
jdns_string_delete(str_nameserver);
|
||||||
|
}
|
||||||
|
list_searchlist = 0;
|
||||||
|
if(str_searchlist)
|
||||||
|
{
|
||||||
|
// lowercase the string
|
||||||
|
jdns_string_t *p = string_tolower(str_searchlist);
|
||||||
|
jdns_string_delete(str_searchlist);
|
||||||
|
str_searchlist = p;
|
||||||
|
|
||||||
|
list_searchlist = string_split(str_searchlist, sep);
|
||||||
|
jdns_string_delete(str_searchlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
params = jdns_dnsparams_new();
|
||||||
|
if(list_nameserver)
|
||||||
|
{
|
||||||
|
// qt seems to do a strange thing here by running each name
|
||||||
|
// server address through the q3dns setLabel function, and
|
||||||
|
// then pulls the result as a list of addresses. i have
|
||||||
|
// no idea why they do this, or how one IP address would
|
||||||
|
// turn into anything else, let alone several addresses.
|
||||||
|
// so, uh, we're not going to do that.
|
||||||
|
for(n = 0; n < list_nameserver->count; ++n)
|
||||||
|
{
|
||||||
|
jdns_address_t *addr = jdns_address_new();
|
||||||
|
if(jdns_address_set_cstr(addr, (char *)list_nameserver->item[n]->data))
|
||||||
|
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||||
|
jdns_address_delete(addr);
|
||||||
|
}
|
||||||
|
jdns_stringlist_delete(list_nameserver);
|
||||||
|
}
|
||||||
|
if(str_domain)
|
||||||
|
{
|
||||||
|
if(str_domain->size > 0)
|
||||||
|
jdns_dnsparams_append_domain(params, str_domain);
|
||||||
|
jdns_string_delete(str_domain);
|
||||||
|
}
|
||||||
|
if(list_searchlist)
|
||||||
|
{
|
||||||
|
for(n = 0; n < list_searchlist->count; ++n)
|
||||||
|
{
|
||||||
|
if(list_searchlist->item[n]->size > 0)
|
||||||
|
jdns_dnsparams_append_domain(params, list_searchlist->item[n]);
|
||||||
|
}
|
||||||
|
jdns_stringlist_delete(list_searchlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jdns_dnsparams_t *dnsparams_get_winsys()
|
||||||
|
{
|
||||||
|
jdns_dnsparams_t *params;
|
||||||
|
GetNetworkParamsFunc myGetNetworkParams;
|
||||||
|
DWORD ret;
|
||||||
|
HINSTANCE lib;
|
||||||
|
jdns_address_t *addr;
|
||||||
|
jdns_string_t *str;
|
||||||
|
IP_ADDR_STRING *ipstr;
|
||||||
|
|
||||||
|
lib = LoadLibraryA("iphlpapi");
|
||||||
|
if(!lib)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
params = 0;
|
||||||
|
myGetNetworkParams = (GetNetworkParamsFunc)GetProcAddress(lib, "GetNetworkParams");
|
||||||
|
if(myGetNetworkParams)
|
||||||
|
{
|
||||||
|
ULONG bufsize = 0;
|
||||||
|
ret = myGetNetworkParams(0, &bufsize);
|
||||||
|
if(ret == ERROR_BUFFER_OVERFLOW)
|
||||||
|
{
|
||||||
|
FIXED_INFO *info = (FIXED_INFO *)jdns_alloc((int)bufsize);
|
||||||
|
ret = myGetNetworkParams(info, &bufsize);
|
||||||
|
if(ret == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
params = jdns_dnsparams_new();
|
||||||
|
ipstr = &info->DnsServerList;
|
||||||
|
while(ipstr)
|
||||||
|
{
|
||||||
|
addr = jdns_address_new();
|
||||||
|
if(jdns_address_set_cstr(addr, (char *)ipstr->IpAddress.String))
|
||||||
|
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||||
|
jdns_address_delete(addr);
|
||||||
|
ipstr = ipstr->Next;
|
||||||
|
}
|
||||||
|
str = jdns_string_new();
|
||||||
|
jdns_string_set_cstr(str, info->DomainName);
|
||||||
|
if(str->size > 0)
|
||||||
|
jdns_dnsparams_append_domain(params, str);
|
||||||
|
jdns_string_delete(str);
|
||||||
|
}
|
||||||
|
jdns_free(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeLibrary(lib);
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apply_hosts_var_filepath(jdns_dnsparams_t *a, const char *envvar, const char *path)
|
||||||
|
{
|
||||||
|
jdns_string_t *e;
|
||||||
|
char *str;
|
||||||
|
int elen, plen;
|
||||||
|
|
||||||
|
e = jdns_getenv(envvar);
|
||||||
|
if(!e)
|
||||||
|
return;
|
||||||
|
elen = strlen((char *)e->data);
|
||||||
|
plen = strlen(path);
|
||||||
|
str = (char *)jdns_alloc(elen + plen + 1);
|
||||||
|
memcpy(str, e->data, elen);
|
||||||
|
jdns_string_delete(e);
|
||||||
|
|
||||||
|
jdns_strcpy(str + elen, path);
|
||||||
|
apply_hosts_file(a, str);
|
||||||
|
jdns_free(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apply_win_hosts_file(jdns_dnsparams_t *a)
|
||||||
|
{
|
||||||
|
// windows 64-bit
|
||||||
|
apply_hosts_var_filepath(a, "SystemRoot", "\\SysWOW64\\drivers\\etc\\hosts");
|
||||||
|
|
||||||
|
// winnt+
|
||||||
|
apply_hosts_var_filepath(a, "SystemRoot", "\\system32\\drivers\\etc\\hosts");
|
||||||
|
|
||||||
|
// win9x
|
||||||
|
apply_hosts_var_filepath(a, "WINDIR", "\\hosts");
|
||||||
|
}
|
||||||
|
|
||||||
|
static jdns_dnsparams_t *dnsparams_get_win()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
jdns_dnsparams_t *sys_params, *reg_params;
|
||||||
|
|
||||||
|
reg_params = dnsparams_get_winreg();
|
||||||
|
sys_params = dnsparams_get_winsys();
|
||||||
|
|
||||||
|
// no sys params? take the reg params then
|
||||||
|
if(!sys_params)
|
||||||
|
{
|
||||||
|
apply_win_hosts_file(reg_params);
|
||||||
|
return reg_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sys params don't have a search list, so merge the domains from
|
||||||
|
// the registry if possible
|
||||||
|
if(reg_params)
|
||||||
|
{
|
||||||
|
for(n = 0; n < reg_params->domains->count; ++n)
|
||||||
|
{
|
||||||
|
jdns_string_t *reg_str = reg_params->domains->item[n];
|
||||||
|
|
||||||
|
// don't add dups
|
||||||
|
if(!dnsparams_have_domain(sys_params, reg_str))
|
||||||
|
jdns_dnsparams_append_domain(sys_params, reg_str);
|
||||||
|
}
|
||||||
|
jdns_dnsparams_delete(reg_params);
|
||||||
|
}
|
||||||
|
apply_win_hosts_file(sys_params);
|
||||||
|
return sys_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JDNS_OS_UNIX
|
||||||
|
|
||||||
|
static jdns_dnsparams_t *dnsparams_get_unixfiles()
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int n;
|
||||||
|
jdns_dnsparams_t *params;
|
||||||
|
jdns_string_t *line, *simp;
|
||||||
|
jdns_stringlist_t *parts;
|
||||||
|
|
||||||
|
params = jdns_dnsparams_new();
|
||||||
|
|
||||||
|
f = jdns_fopen("/etc/resolv.conf", "r");
|
||||||
|
if(!f)
|
||||||
|
return params;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
line = file_nextline(f);
|
||||||
|
if(!line)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// truncate at comment
|
||||||
|
n = string_indexOf(line, '#', 0);
|
||||||
|
if(n != -1)
|
||||||
|
{
|
||||||
|
line->size = n;
|
||||||
|
line->data[n] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
simp = string_simplify(line);
|
||||||
|
jdns_string_delete(line);
|
||||||
|
|
||||||
|
parts = string_split(simp, ' ');
|
||||||
|
jdns_string_delete(simp);
|
||||||
|
|
||||||
|
if(parts->count < 2)
|
||||||
|
{
|
||||||
|
jdns_stringlist_delete(parts);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
simp = string_tolower(parts->item[0]);
|
||||||
|
if(strcmp((char *)simp->data, "nameserver") == 0)
|
||||||
|
{
|
||||||
|
jdns_address_t *addr = jdns_address_new();
|
||||||
|
jdns_address_set_cstr(addr, (const char *)parts->item[1]->data);
|
||||||
|
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||||
|
jdns_address_delete(addr);
|
||||||
|
}
|
||||||
|
else if(strcmp((char *)simp->data, "search") == 0)
|
||||||
|
{
|
||||||
|
for(n = 1; n < parts->count; ++n)
|
||||||
|
{
|
||||||
|
jdns_dnsparams_append_domain(params, parts->item[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(strcmp((char *)simp->data, "domain") == 0)
|
||||||
|
{
|
||||||
|
jdns_dnsparams_append_domain(params, parts->item[1]);
|
||||||
|
}
|
||||||
|
jdns_string_delete(simp);
|
||||||
|
|
||||||
|
jdns_stringlist_delete(parts);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 3)))
|
||||||
|
# define JDNS_MODERN_RES_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JDNS_MODERN_RES_API
|
||||||
|
typedef int (*res_init_func)();
|
||||||
|
static int my_res_init()
|
||||||
|
{
|
||||||
|
#ifdef JDNS_OS_MAC
|
||||||
|
res_init_func mac_res_init;
|
||||||
|
|
||||||
|
// look up res_init in the system library (qt does this, not sure why)
|
||||||
|
mac_res_init = (res_init_func)dlsym(RTLD_NEXT, "res_init");
|
||||||
|
if(!mac_res_init)
|
||||||
|
return -1;
|
||||||
|
return mac_res_init();
|
||||||
|
#else
|
||||||
|
return res_init();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// on some platforms, __res_state_ext exists as a struct but it is not
|
||||||
|
// a define, so the #ifdef doesn't work. as a workaround, we'll explicitly
|
||||||
|
// specify the platforms that have __res_state_ext
|
||||||
|
//#ifdef __res_state_ext
|
||||||
|
#if defined(JDNS_OS_MAC) || defined(JDNS_OS_FREEBSD) || \
|
||||||
|
defined(JDNS_OS_NETBSD) || defined (JDNS_OS_SOLARIS)
|
||||||
|
# define USE_EXTEXT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static jdns_dnsparams_t *dnsparams_get_unixsys()
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
jdns_dnsparams_t *params;
|
||||||
|
|
||||||
|
#ifdef JDNS_MODERN_RES_API
|
||||||
|
struct __res_state res;
|
||||||
|
memset(&res, 0, sizeof(struct __res_state));
|
||||||
|
n = res_ninit(&res);
|
||||||
|
#define RESVAR res
|
||||||
|
#else
|
||||||
|
n = my_res_init();
|
||||||
|
#define RESVAR _res
|
||||||
|
#endif
|
||||||
|
|
||||||
|
params = jdns_dnsparams_new();
|
||||||
|
|
||||||
|
// error initializing?
|
||||||
|
if(n == -1)
|
||||||
|
return params;
|
||||||
|
|
||||||
|
// nameservers - ipv6
|
||||||
|
for(n = 0; n < MAXNS && n < RESVAR._u._ext.nscount; ++n)
|
||||||
|
{
|
||||||
|
jdns_address_t *addr;
|
||||||
|
struct sockaddr_in6 *sa6;
|
||||||
|
|
||||||
|
#ifdef USE_EXTEXT
|
||||||
|
sa6 = ((struct sockaddr_in6 *)RESVAR._u._ext.ext) + n;
|
||||||
|
#else
|
||||||
|
sa6 = RESVAR._u._ext.nsaddrs[n];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(sa6 == NULL)
|
||||||
|
continue;
|
||||||
|
addr = jdns_address_new();
|
||||||
|
jdns_address_set_ipv6(addr, sa6->sin6_addr.s6_addr);
|
||||||
|
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||||
|
jdns_address_delete(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nameservers - ipv4
|
||||||
|
for(n = 0; n < MAXNS && n < RESVAR.nscount; ++n)
|
||||||
|
{
|
||||||
|
jdns_address_t *addr = jdns_address_new();
|
||||||
|
jdns_address_set_ipv4(addr, ntohl(RESVAR.nsaddr_list[n].sin_addr.s_addr));
|
||||||
|
jdns_dnsparams_append_nameserver(params, addr, JDNS_UNICAST_PORT);
|
||||||
|
jdns_address_delete(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// domain name
|
||||||
|
if(strlen(RESVAR.defdname) > 0)
|
||||||
|
{
|
||||||
|
jdns_string_t *str;
|
||||||
|
jdns_string_t *p;
|
||||||
|
str = jdns_string_new();
|
||||||
|
jdns_string_set_cstr(str, RESVAR.defdname);
|
||||||
|
p = string_tolower(str);
|
||||||
|
jdns_string_delete(str);
|
||||||
|
str = p;
|
||||||
|
jdns_dnsparams_append_domain(params, str);
|
||||||
|
jdns_string_delete(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// search list
|
||||||
|
#ifdef MAXDFLSRCH
|
||||||
|
for(n = 0; n < MAXDFLSRCH && RESVAR.dnsrch[n]; ++n)
|
||||||
|
{
|
||||||
|
if(strlen(RESVAR.dnsrch[n]) > 0)
|
||||||
|
{
|
||||||
|
jdns_string_t *str;
|
||||||
|
jdns_string_t *p;
|
||||||
|
str = jdns_string_new();
|
||||||
|
jdns_string_set_cstr(str, RESVAR.dnsrch[n]);
|
||||||
|
p = string_tolower(str);
|
||||||
|
jdns_string_delete(str);
|
||||||
|
str = p;
|
||||||
|
|
||||||
|
// don't add dups
|
||||||
|
if(!dnsparams_have_domain(params, str))
|
||||||
|
jdns_dnsparams_append_domain(params, str);
|
||||||
|
|
||||||
|
jdns_string_delete(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jdns_dnsparams_t *dnsparams_get_unix()
|
||||||
|
{
|
||||||
|
jdns_dnsparams_t *params;
|
||||||
|
|
||||||
|
// prefer system calls over files
|
||||||
|
params = dnsparams_get_unixsys();
|
||||||
|
if(params->nameservers->count == 0)
|
||||||
|
{
|
||||||
|
jdns_dnsparams_delete(params);
|
||||||
|
params = dnsparams_get_unixfiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_hosts_file(params, "/etc/hosts");
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
jdns_dnsparams_t *jdns_system_dnsparams()
|
||||||
|
{
|
||||||
|
#ifdef JDNS_OS_WIN
|
||||||
|
return dnsparams_get_win();
|
||||||
|
#else
|
||||||
|
return dnsparams_get_unix();
|
||||||
|
#endif
|
||||||
|
}
|
1553
thirdparty/jdns/jdns_util.c
vendored
Normal file
1553
thirdparty/jdns/jdns_util.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
596
thirdparty/jdns/main.cpp
vendored
Normal file
596
thirdparty/jdns/main.cpp
vendored
Normal file
@@ -0,0 +1,596 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Justin Karneges
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QtNetwork>
|
||||||
|
#include "qjdns.h"
|
||||||
|
|
||||||
|
QString dataToString(const QByteArray &buf)
|
||||||
|
{
|
||||||
|
QString out;
|
||||||
|
for(int n = 0; n < buf.size(); ++n)
|
||||||
|
{
|
||||||
|
unsigned char c = (unsigned char)buf[n];
|
||||||
|
if(c == '\\')
|
||||||
|
out += "\\\\";
|
||||||
|
else if(c >= 0x20 && c < 0x7f)
|
||||||
|
out += c;
|
||||||
|
else
|
||||||
|
out += QString().sprintf("\\x%02x", (unsigned int)c);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_record(const QJDns::Record &r)
|
||||||
|
{
|
||||||
|
switch(r.type)
|
||||||
|
{
|
||||||
|
case QJDns::A:
|
||||||
|
printf(" A: [%s] (ttl=%d)\n", qPrintable(r.address.toString()), r.ttl);
|
||||||
|
break;
|
||||||
|
case QJDns::Aaaa:
|
||||||
|
printf(" AAAA: [%s] (ttl=%d)\n", qPrintable(r.address.toString()), r.ttl);
|
||||||
|
break;
|
||||||
|
case QJDns::Mx:
|
||||||
|
printf(" MX: [%s] priority=%d (ttl=%d)\n", r.name.data(), r.priority, r.ttl);
|
||||||
|
break;
|
||||||
|
case QJDns::Srv:
|
||||||
|
printf(" SRV: [%s] port=%d priority=%d weight=%d (ttl=%d)\n", r.name.data(), r.port, r.priority, r.weight, r.ttl);
|
||||||
|
break;
|
||||||
|
case QJDns::Cname:
|
||||||
|
printf(" CNAME: [%s] (ttl=%d)\n", r.name.data(), r.ttl);
|
||||||
|
break;
|
||||||
|
case QJDns::Ptr:
|
||||||
|
printf(" PTR: [%s] (ttl=%d)\n", r.name.data(), r.ttl);
|
||||||
|
break;
|
||||||
|
case QJDns::Txt:
|
||||||
|
{
|
||||||
|
printf(" TXT: count=%d (ttl=%d)\n", r.texts.count(), r.ttl);
|
||||||
|
for(int n = 0; n < r.texts.count(); ++n)
|
||||||
|
printf(" len=%d [%s]\n", r.texts[n].size(), qPrintable(dataToString(r.texts[n])));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QJDns::Hinfo:
|
||||||
|
printf(" HINFO: [%s] [%s] (ttl=%d)\n", r.cpu.data(), r.os.data(), r.ttl);
|
||||||
|
break;
|
||||||
|
case QJDns::Ns:
|
||||||
|
printf(" NS: [%s] (ttl=%d)\n", r.name.data(), r.ttl);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf(" (Unknown): type=%d, size=%d (ttl=%d)\n", r.type, r.rdata.size(), r.ttl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class App : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
bool opt_debug, opt_ipv6, opt_quit;
|
||||||
|
int quit_time;
|
||||||
|
QString mode, type, name, ipaddr;
|
||||||
|
QStringList nslist;
|
||||||
|
QList<QJDns::Record> pubitems;
|
||||||
|
QJDns jdns;
|
||||||
|
int req_id;
|
||||||
|
|
||||||
|
App()
|
||||||
|
{
|
||||||
|
connect(&jdns, SIGNAL(resultsReady(int, const QJDns::Response &)), SLOT(jdns_resultsReady(int, const QJDns::Response &)));
|
||||||
|
connect(&jdns, SIGNAL(published(int)), SLOT(jdns_published(int)));
|
||||||
|
connect(&jdns, SIGNAL(error(int, QJDns::Error)), SLOT(jdns_error(int, QJDns::Error)));
|
||||||
|
connect(&jdns, SIGNAL(shutdownFinished()), SLOT(jdns_shutdownFinished()));
|
||||||
|
connect(&jdns, SIGNAL(debugLinesReady()), SLOT(jdns_debugLinesReady()));
|
||||||
|
}
|
||||||
|
|
||||||
|
~App()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
if(mode == "uni")
|
||||||
|
{
|
||||||
|
if(!jdns.init(QJDns::Unicast, opt_ipv6 ? QHostAddress::AnyIPv6 : QHostAddress::Any))
|
||||||
|
{
|
||||||
|
jdns_debugLinesReady();
|
||||||
|
printf("unable to bind\n");
|
||||||
|
emit quit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QJDns::NameServer> addrs;
|
||||||
|
for(int n = 0; n < nslist.count(); ++n)
|
||||||
|
{
|
||||||
|
QJDns::NameServer host;
|
||||||
|
QString str = nslist[n];
|
||||||
|
if(str == "mul")
|
||||||
|
{
|
||||||
|
if(opt_ipv6)
|
||||||
|
host.address = QHostAddress("FF02::FB");
|
||||||
|
else
|
||||||
|
host.address = QHostAddress("224.0.0.251");
|
||||||
|
host.port = 5353;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int at = str.indexOf(';');
|
||||||
|
if(at != -1)
|
||||||
|
{
|
||||||
|
host.address = QHostAddress(str.mid(0, at));
|
||||||
|
host.port = str.mid(at + 1).toInt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
host.address = QHostAddress(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(host.address.isNull() || host.port <= 0)
|
||||||
|
{
|
||||||
|
printf("bad nameserver: [%s]\n", qPrintable(nslist[n]));
|
||||||
|
emit quit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addrs += host;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addrs.isEmpty())
|
||||||
|
addrs = QJDns::systemInfo().nameServers;
|
||||||
|
|
||||||
|
if(addrs.isEmpty())
|
||||||
|
{
|
||||||
|
printf("no nameservers were detected or specified\n");
|
||||||
|
emit quit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jdns.setNameServers(addrs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!jdns.init(QJDns::Multicast, opt_ipv6 ? QHostAddress::AnyIPv6 : QHostAddress::Any))
|
||||||
|
{
|
||||||
|
jdns_debugLinesReady();
|
||||||
|
printf("unable to bind\n");
|
||||||
|
emit quit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode == "uni" || mode == "mul")
|
||||||
|
{
|
||||||
|
int x = QJDns::A;
|
||||||
|
if(type == "ptr")
|
||||||
|
x = QJDns::Ptr;
|
||||||
|
else if(type == "srv")
|
||||||
|
x = QJDns::Srv;
|
||||||
|
else if(type == "a")
|
||||||
|
x = QJDns::A;
|
||||||
|
else if(type == "aaaa")
|
||||||
|
x = QJDns::Aaaa;
|
||||||
|
else if(type == "mx")
|
||||||
|
x = QJDns::Mx;
|
||||||
|
else if(type == "txt")
|
||||||
|
x = QJDns::Txt;
|
||||||
|
else if(type == "hinfo")
|
||||||
|
x = QJDns::Hinfo;
|
||||||
|
else if(type == "cname")
|
||||||
|
x = QJDns::Cname;
|
||||||
|
else if(type == "any")
|
||||||
|
x = QJDns::Any;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
int y = type.toInt(&ok);
|
||||||
|
if(ok)
|
||||||
|
x = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
req_id = jdns.queryStart(name.toLatin1(), x);
|
||||||
|
printf("[%d] Querying for [%s] type=%d ...\n", req_id, qPrintable(name), x);
|
||||||
|
}
|
||||||
|
else // publish
|
||||||
|
{
|
||||||
|
for(int n = 0; n < pubitems.count(); ++n)
|
||||||
|
{
|
||||||
|
const QJDns::Record &rr = pubitems[n];
|
||||||
|
QJDns::PublishMode m = QJDns::Unique;
|
||||||
|
if(rr.type == QJDns::Ptr)
|
||||||
|
m = QJDns::Shared;
|
||||||
|
int id = jdns.publishStart(m, rr);
|
||||||
|
printf("[%d] Publishing [%s] type=%d ...\n", id, rr.owner.data(), rr.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(opt_quit)
|
||||||
|
QTimer::singleShot(quit_time * 1000, this, SLOT(doShutdown()));
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void quit();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void jdns_resultsReady(int id, const QJDns::Response &results)
|
||||||
|
{
|
||||||
|
printf("[%d] Results\n", id);
|
||||||
|
for(int n = 0; n < results.answerRecords.count(); ++n)
|
||||||
|
print_record(results.answerRecords[n]);
|
||||||
|
|
||||||
|
if(mode == "uni")
|
||||||
|
jdns.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void jdns_published(int id)
|
||||||
|
{
|
||||||
|
printf("[%d] Published\n", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jdns_error(int id, QJDns::Error e)
|
||||||
|
{
|
||||||
|
QString str;
|
||||||
|
if(e == QJDns::ErrorGeneric)
|
||||||
|
str = "Generic";
|
||||||
|
else if(e == QJDns::ErrorNXDomain)
|
||||||
|
str = "NXDomain";
|
||||||
|
else if(e == QJDns::ErrorTimeout)
|
||||||
|
str = "Timeout";
|
||||||
|
else if(e == QJDns::ErrorConflict)
|
||||||
|
str = "Conflict";
|
||||||
|
printf("[%d] Error: %s\n", id, qPrintable(str));
|
||||||
|
jdns.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void jdns_shutdownFinished()
|
||||||
|
{
|
||||||
|
emit quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void jdns_debugLinesReady()
|
||||||
|
{
|
||||||
|
QStringList lines = jdns.debugLines();
|
||||||
|
if(opt_debug)
|
||||||
|
{
|
||||||
|
for(int n = 0; n < lines.count(); ++n)
|
||||||
|
printf("jdns: %s\n", qPrintable(lines[n]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doShutdown()
|
||||||
|
{
|
||||||
|
jdns.shutdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "main.moc"
|
||||||
|
|
||||||
|
void usage()
|
||||||
|
{
|
||||||
|
printf("usage: jdns (options) uni [type] [name] (nameserver(;port)|mul ...)\n");
|
||||||
|
printf(" jdns (options) mul [type] [name]\n");
|
||||||
|
printf(" jdns (options) pub [items ...]\n");
|
||||||
|
printf(" jdns sys\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("options:\n");
|
||||||
|
printf(" -d show debug output\n");
|
||||||
|
printf(" -6 use ipv6\n");
|
||||||
|
printf(" -q x quit x seconds after starting\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("uni/mul types: a aaaa ptr srv mx txt hinfo cname any\n");
|
||||||
|
printf("pub items: ptr:name,answer srv:name,answer,port a:name,ipaddr\n");
|
||||||
|
printf(" txt:name,str0,...,strn aaaa:name,ipaddr\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("examples:\n");
|
||||||
|
printf(" jdns uni a jabber.org 192.168.0.1\n");
|
||||||
|
printf(" jdns uni srv _xmpp-client._tcp.jabber.org 192.168.0.1;53\n");
|
||||||
|
printf(" jdns uni 10 user@host._presence._tcp.local mul\n");
|
||||||
|
printf(" jdns mul a foobar.local\n");
|
||||||
|
printf(" jdns mul ptr _services._dns-sd._udp.local\n");
|
||||||
|
printf(" jdns pub a:mybox.local.,192.168.0.55\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
QCoreApplication app(argc, argv);
|
||||||
|
|
||||||
|
if(argc < 2)
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get args
|
||||||
|
QStringList args;
|
||||||
|
for(int n = 1; n < argc; ++n)
|
||||||
|
args += QString(argv[n]);
|
||||||
|
|
||||||
|
bool opt_debug = false;
|
||||||
|
bool opt_ipv6 = false;
|
||||||
|
bool opt_quit = false;
|
||||||
|
int quit_time = 0;
|
||||||
|
QString mode, type, name, ipaddr;
|
||||||
|
QStringList nslist;
|
||||||
|
QList<QJDns::Record> pubitems;
|
||||||
|
|
||||||
|
// options
|
||||||
|
for(int n = 0; n < args.count(); ++n)
|
||||||
|
{
|
||||||
|
if(args[n].left(1) == "-")
|
||||||
|
{
|
||||||
|
if(args[n] == "-d")
|
||||||
|
opt_debug = true;
|
||||||
|
else if(args[n] == "-6")
|
||||||
|
opt_ipv6 = true;
|
||||||
|
else if(args[n] == "-q")
|
||||||
|
{
|
||||||
|
if(n + 1 >= args.count())
|
||||||
|
{
|
||||||
|
printf("need to specify number of seconds\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = args[n + 1].toInt();
|
||||||
|
if(x < 1)
|
||||||
|
x = 30;
|
||||||
|
|
||||||
|
opt_quit = true;
|
||||||
|
quit_time = x;
|
||||||
|
|
||||||
|
args.removeAt(n + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("bad option\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
args.removeAt(n);
|
||||||
|
--n; // adjust position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = args[0];
|
||||||
|
if(mode == "uni" || mode == "mul")
|
||||||
|
{
|
||||||
|
if(args.count() < 3)
|
||||||
|
{
|
||||||
|
printf("not enough args\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
type = args[1];
|
||||||
|
name = args[2];
|
||||||
|
if(mode == "uni")
|
||||||
|
{
|
||||||
|
for(int n = 3; n < args.count(); ++n)
|
||||||
|
nslist += QString(args[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(mode == "pub")
|
||||||
|
{
|
||||||
|
if(args.count() < 2)
|
||||||
|
{
|
||||||
|
printf("not enough args\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for(int n = 1; n < args.count(); ++n)
|
||||||
|
{
|
||||||
|
QString arg = args[n];
|
||||||
|
int at = arg.indexOf(':');
|
||||||
|
if(at == -1)
|
||||||
|
{
|
||||||
|
printf("missing colon\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
QString type = arg.mid(0, at).toLower();
|
||||||
|
QString val = arg.mid(at + 1);
|
||||||
|
if(type == "a")
|
||||||
|
{
|
||||||
|
QStringList list = val.split(',');
|
||||||
|
if(list.count() != 2)
|
||||||
|
{
|
||||||
|
printf("bad format for A type\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
QHostAddress host(list[1]);
|
||||||
|
if(host.isNull() || host.protocol() != QAbstractSocket::IPv4Protocol)
|
||||||
|
{
|
||||||
|
printf("bad format for A type IP address\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJDns::Record rec;
|
||||||
|
rec.owner = list[0].toLatin1();
|
||||||
|
rec.type = QJDns::A;
|
||||||
|
rec.ttl = 120;
|
||||||
|
rec.haveKnown = true;
|
||||||
|
rec.address = host;
|
||||||
|
pubitems += rec;
|
||||||
|
}
|
||||||
|
else if(type == "aaaa")
|
||||||
|
{
|
||||||
|
QStringList list = val.split(',');
|
||||||
|
if(list.count() != 2)
|
||||||
|
{
|
||||||
|
printf("bad format for AAAA type\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
QHostAddress host(list[1]);
|
||||||
|
if(host.isNull() || host.protocol() != QAbstractSocket::IPv6Protocol)
|
||||||
|
{
|
||||||
|
printf("bad format for AAAA type IP address\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJDns::Record rec;
|
||||||
|
rec.owner = list[0].toLatin1();
|
||||||
|
rec.type = QJDns::Aaaa;
|
||||||
|
rec.ttl = 120;
|
||||||
|
rec.haveKnown = true;
|
||||||
|
rec.address = host;
|
||||||
|
pubitems += rec;
|
||||||
|
}
|
||||||
|
else if(type == "srv")
|
||||||
|
{
|
||||||
|
QStringList list = val.split(',');
|
||||||
|
if(list.count() != 3)
|
||||||
|
{
|
||||||
|
printf("bad format for SRV type\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJDns::Record rec;
|
||||||
|
rec.owner = list[0].toLatin1();
|
||||||
|
rec.type = QJDns::Srv;
|
||||||
|
rec.ttl = 120;
|
||||||
|
rec.haveKnown = true;
|
||||||
|
rec.name = list[1].toLatin1();
|
||||||
|
rec.priority = 0;
|
||||||
|
rec.weight = 0;
|
||||||
|
rec.port = list[2].toInt();
|
||||||
|
pubitems += rec;
|
||||||
|
}
|
||||||
|
else if(type == "ptr")
|
||||||
|
{
|
||||||
|
QStringList list = val.split(',');
|
||||||
|
if(list.count() != 2)
|
||||||
|
{
|
||||||
|
printf("bad format for PTR type\n");
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJDns::Record rec;
|
||||||
|
rec.owner = list[0].toLatin1();
|
||||||
|
rec.type = QJDns::Ptr;
|
||||||
|
rec.ttl = 120;
|
||||||
|
rec.haveKnown = true;
|
||||||
|
rec.name = list[1].toLatin1();
|
||||||
|
pubitems += rec;
|
||||||
|
}
|
||||||
|
else if(type == "txt")
|
||||||
|
{
|
||||||
|
QStringList list = val.split(',');
|
||||||
|
QList<QByteArray> texts;
|
||||||
|
for(int n = 1; n < list.count(); ++n)
|
||||||
|
texts += list[n].toLatin1();
|
||||||
|
|
||||||
|
QJDns::Record rec;
|
||||||
|
rec.owner = list[0].toLatin1();
|
||||||
|
rec.type = QJDns::Txt;
|
||||||
|
rec.ttl = 120;
|
||||||
|
rec.haveKnown = true;
|
||||||
|
rec.texts = texts;
|
||||||
|
pubitems += rec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("bad record type [%s]\n", qPrintable(type));
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(mode == "sys")
|
||||||
|
{
|
||||||
|
QJDns::SystemInfo info = QJDns::systemInfo();
|
||||||
|
|
||||||
|
printf("DNS System Information\n");
|
||||||
|
printf(" Name Servers:\n");
|
||||||
|
if(!info.nameServers.isEmpty())
|
||||||
|
{
|
||||||
|
for(int n = 0; n < info.nameServers.count(); ++n)
|
||||||
|
printf(" %s\n", qPrintable(info.nameServers[n].address.toString()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf(" (None)\n");
|
||||||
|
|
||||||
|
printf(" Domains:\n");
|
||||||
|
if(!info.domains.isEmpty())
|
||||||
|
{
|
||||||
|
for(int n = 0; n < info.domains.count(); ++n)
|
||||||
|
printf(" [%s]\n", info.domains[n].data());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf(" (None)\n");
|
||||||
|
|
||||||
|
printf(" Hosts:\n");
|
||||||
|
if(!info.hosts.isEmpty())
|
||||||
|
{
|
||||||
|
for(int n = 0; n < info.hosts.count(); ++n)
|
||||||
|
{
|
||||||
|
const QJDns::DnsHost &h = info.hosts[n];
|
||||||
|
printf(" [%s] -> %s\n", h.name.data(), qPrintable(h.address.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf(" (None)\n");
|
||||||
|
|
||||||
|
QHostAddress addr;
|
||||||
|
printf("Primary IPv4 Multicast Address: ");
|
||||||
|
addr = QJDns::detectPrimaryMulticast(QHostAddress::Any);
|
||||||
|
if(!addr.isNull())
|
||||||
|
printf("%s\n", qPrintable(addr.toString()));
|
||||||
|
else
|
||||||
|
printf("(None)\n");
|
||||||
|
printf("Primary IPv6 Multicast Address: ");
|
||||||
|
addr = QJDns::detectPrimaryMulticast(QHostAddress::AnyIPv6);
|
||||||
|
if(!addr.isNull())
|
||||||
|
printf("%s\n", qPrintable(addr.toString()));
|
||||||
|
else
|
||||||
|
printf("(None)\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
App a;
|
||||||
|
a.opt_debug = opt_debug;
|
||||||
|
a.opt_ipv6 = opt_ipv6;
|
||||||
|
a.opt_quit = opt_quit;
|
||||||
|
a.quit_time = quit_time;
|
||||||
|
a.mode = mode;
|
||||||
|
a.type = type.toLower();
|
||||||
|
a.name = name;
|
||||||
|
a.ipaddr = ipaddr;
|
||||||
|
a.nslist = nslist;
|
||||||
|
a.pubitems = pubitems;
|
||||||
|
QObject::connect(&a, SIGNAL(quit()), &app, SLOT(quit()));
|
||||||
|
QTimer::singleShot(0, &a, SLOT(start()));
|
||||||
|
app.exec();
|
||||||
|
return 0;
|
||||||
|
}
|
1047
thirdparty/jdns/qjdns.cpp
vendored
Normal file
1047
thirdparty/jdns/qjdns.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
158
thirdparty/jdns/qjdns.h
vendored
Normal file
158
thirdparty/jdns/qjdns.h
vendored
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005,2006 Justin Karneges
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// this is the Qt wrapper to jdns. it requires Qt 4.1+
|
||||||
|
|
||||||
|
#ifndef QJDNS_H
|
||||||
|
#define QJDNS_H
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QtNetwork>
|
||||||
|
|
||||||
|
class QJDns : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum Mode
|
||||||
|
{
|
||||||
|
Unicast,
|
||||||
|
Multicast
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PublishMode
|
||||||
|
{
|
||||||
|
Unique,
|
||||||
|
Shared
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
A = 1,
|
||||||
|
Aaaa = 28,
|
||||||
|
Mx = 15,
|
||||||
|
Srv = 33,
|
||||||
|
Cname = 5,
|
||||||
|
Ptr = 12,
|
||||||
|
Txt = 16,
|
||||||
|
Hinfo = 13,
|
||||||
|
Ns = 2,
|
||||||
|
Any = 255
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Error
|
||||||
|
{
|
||||||
|
ErrorGeneric,
|
||||||
|
ErrorNXDomain, // query only
|
||||||
|
ErrorTimeout, // query only
|
||||||
|
ErrorConflict // publish only
|
||||||
|
};
|
||||||
|
|
||||||
|
class NameServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QHostAddress address;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
NameServer();
|
||||||
|
};
|
||||||
|
|
||||||
|
class DnsHost
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QByteArray name;
|
||||||
|
QHostAddress address;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SystemInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QList<NameServer> nameServers;
|
||||||
|
QList<QByteArray> domains;
|
||||||
|
QList<DnsHost> hosts;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Record
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QByteArray owner;
|
||||||
|
int ttl;
|
||||||
|
int type;
|
||||||
|
QByteArray rdata;
|
||||||
|
bool haveKnown;
|
||||||
|
|
||||||
|
// known
|
||||||
|
QHostAddress address; // for A, Aaaa
|
||||||
|
QByteArray name; // for Mx, Srv, Cname, Ptr, Ns
|
||||||
|
int priority; // for Mx, Srv
|
||||||
|
int weight; // for Srv
|
||||||
|
int port; // for Srv
|
||||||
|
QList<QByteArray> texts; // for Txt
|
||||||
|
QByteArray cpu; // for Hinfo
|
||||||
|
QByteArray os; // for Hinfo
|
||||||
|
|
||||||
|
Record();
|
||||||
|
bool verify() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Response
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QList<Record> answerRecords;
|
||||||
|
QList<Record> authorityRecords;
|
||||||
|
QList<Record> additionalRecords;
|
||||||
|
};
|
||||||
|
|
||||||
|
QJDns(QObject *parent = 0);
|
||||||
|
~QJDns();
|
||||||
|
|
||||||
|
bool init(Mode mode, const QHostAddress &address);
|
||||||
|
void shutdown();
|
||||||
|
QStringList debugLines();
|
||||||
|
|
||||||
|
static SystemInfo systemInfo();
|
||||||
|
static QHostAddress detectPrimaryMulticast(const QHostAddress &address);
|
||||||
|
|
||||||
|
void setNameServers(const QList<NameServer> &list);
|
||||||
|
|
||||||
|
int queryStart(const QByteArray &name, int type);
|
||||||
|
void queryCancel(int id);
|
||||||
|
|
||||||
|
// for multicast mode only
|
||||||
|
int publishStart(PublishMode m, const Record &record);
|
||||||
|
void publishUpdate(int id, const Record &record);
|
||||||
|
void publishCancel(int id);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultsReady(int id, const QJDns::Response &results);
|
||||||
|
void published(int id);
|
||||||
|
void error(int id, QJDns::Error e);
|
||||||
|
void shutdownFinished();
|
||||||
|
void debugLinesReady();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Private;
|
||||||
|
friend class Private;
|
||||||
|
Private *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
184
thirdparty/jdns/qjdns_sock.cpp
vendored
Normal file
184
thirdparty/jdns/qjdns_sock.cpp
vendored
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005,2006 Justin Karneges
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qjdns_sock.h"
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
# include <winsock2.h>
|
||||||
|
# include <ws2tcpip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
# include <sys/time.h>
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# include <fcntl.h>
|
||||||
|
# include <errno.h>
|
||||||
|
# include <signal.h>
|
||||||
|
# include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef QT_NO_IPV6
|
||||||
|
# define HAVE_IPV6
|
||||||
|
# ifndef s6_addr
|
||||||
|
# define IPPROTO_IPV6 41
|
||||||
|
struct in6_addr
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
unsigned char _S6_u8[16];
|
||||||
|
unsigned short _S6_u16[8];
|
||||||
|
unsigned long _S6_u32[4];
|
||||||
|
} _S6_un;
|
||||||
|
};
|
||||||
|
# define s6_addr _S6_un._S6_u8
|
||||||
|
# endif
|
||||||
|
# ifndef IPV6_JOIN_GROUP
|
||||||
|
# define IPV6_JOIN_GROUP 12
|
||||||
|
# define IPV6_MULTICAST_HOPS 10
|
||||||
|
struct ipv6_mreq
|
||||||
|
{
|
||||||
|
struct in6_addr ipv6mr_multiaddr;
|
||||||
|
unsigned int ipv6mr_interface;
|
||||||
|
};
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int get_last_error()
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
x = WSAGetLastError();
|
||||||
|
#else
|
||||||
|
x = errno;
|
||||||
|
#endif
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qjdns_sock_setMulticast4(int s, unsigned long int addr, int *errorCode)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct ip_mreq mc;
|
||||||
|
|
||||||
|
memset(&mc, 0, sizeof(mc));
|
||||||
|
mc.imr_multiaddr.s_addr = htonl(addr);
|
||||||
|
mc.imr_interface.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&mc, sizeof(mc));
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
if(errorCode)
|
||||||
|
*errorCode = get_last_error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qjdns_sock_setMulticast6(int s, unsigned char *addr, int *errorCode)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
int ret;
|
||||||
|
struct ipv6_mreq mc;
|
||||||
|
|
||||||
|
memset(&mc, 0, sizeof(mc));
|
||||||
|
memcpy(mc.ipv6mr_multiaddr.s6_addr, addr, 16);
|
||||||
|
mc.ipv6mr_interface = 0;
|
||||||
|
|
||||||
|
ret = setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char *)&mc, sizeof(mc));
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
if(errorCode)
|
||||||
|
*errorCode = get_last_error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
Q_UNUSED(s);
|
||||||
|
Q_UNUSED(addr);
|
||||||
|
Q_UNUSED(errorCode);
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qjdns_sock_setTTL4(int s, int ttl)
|
||||||
|
{
|
||||||
|
unsigned char cttl;
|
||||||
|
int ret, ittl;
|
||||||
|
|
||||||
|
cttl = ttl;
|
||||||
|
ittl = ttl;
|
||||||
|
|
||||||
|
// IP_MULTICAST_TTL might take 1 byte or 4, try both
|
||||||
|
ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&cttl, sizeof(cttl));
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&ittl, sizeof(ittl));
|
||||||
|
if(ret != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qjdns_sock_setTTL6(int s, int ttl)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
unsigned char cttl;
|
||||||
|
int ret, ittl;
|
||||||
|
|
||||||
|
cttl = ttl;
|
||||||
|
ittl = ttl;
|
||||||
|
|
||||||
|
// IPV6_MULTICAST_HOPS might take 1 byte or 4, try both
|
||||||
|
ret = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&cttl, sizeof(cttl));
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
ret = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&ittl, sizeof(ittl));
|
||||||
|
if(ret != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
Q_UNUSED(s);
|
||||||
|
Q_UNUSED(ttl);
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qjdns_sock_setIPv6Only(int s)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_IPV6) && defined(IPV6_V6ONLY)
|
||||||
|
int x = 1;
|
||||||
|
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&x, sizeof(x)) != 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
Q_UNUSED(s);
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
33
thirdparty/jdns/qjdns_sock.h
vendored
Normal file
33
thirdparty/jdns/qjdns_sock.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005,2006 Justin Karneges
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QJDNS_SOCK_H
|
||||||
|
#define QJDNS_SOCK_H
|
||||||
|
|
||||||
|
bool qjdns_sock_setMulticast4(int s, unsigned long int addr, int *errorCode);
|
||||||
|
bool qjdns_sock_setMulticast6(int s, unsigned char *addr, int *errorCode);
|
||||||
|
bool qjdns_sock_setTTL4(int s, int ttl);
|
||||||
|
bool qjdns_sock_setTTL6(int s, int ttl);
|
||||||
|
bool qjdns_sock_setIPv6Only(int s);
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user