mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-31 15:44:21 +00:00
Merge branch 'master' into smgmaster
This commit is contained in:
commit
bf23a0a38b
127 files changed
+3185
-8895
No files matched your search
@@ -1104,3 +1104,25 @@
|
||||
/tiff-3.8.2/a.out.dSYM/
|
||||
/tiff-3.8.2/tiff-Makefile.tgz
|
||||
/unimrcp/a.out.dSYM/
|
||||
/esl/fs_cli.dSYM/
|
||||
/esl/ivrd.dSYM/
|
||||
/esl/testclient.dSYM/
|
||||
/esl/testserver.dSYM/
|
||||
|
||||
/openssl-1.0.0a/
|
||||
/esl/Debug/
|
||||
/esl/Release/
|
||||
/freetdm/msvc/Release/
|
||||
/freetdm/msvc/Debug/
|
||||
|
||||
/spandsp/src/msvc/All/BuildLog make_at_dictionary.htm
|
||||
/spandsp/src/msvc/All/BuildLog make_modem_filter.htm
|
||||
|
||||
BuildLog*.htm
|
||||
/win32/tmp*.bat
|
||||
|
||||
/speex/win32/VS2008/libspeex/*/*/libspeex.log
|
||||
/speex/win32/VS2008/libspeexdsp/*/*/libspeexdsp.log
|
||||
/win32/celt/*/*/libcelt.log
|
||||
/win32/libg722_1/*/*/libg722_1.log
|
||||
/win32/libshout/*/*/libshout.log
|
||||
@@ -92,6 +92,9 @@ javamod: $(MYLIB)
|
||||
managedmod: $(MYLIB)
|
||||
$(MAKE) MYLIB="../$(MYLIB)" SOLINK="$(SOLINK)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CXX_CFLAGS="$(CXX_CFLAGS)" -C managed
|
||||
|
||||
perlmod-install: perlmod
|
||||
$(MAKE) -C perl install
|
||||
|
||||
phpmod-install: phpmod
|
||||
$(MAKE) -C php install
|
||||
|
||||
|
||||
+1
-1
@@ -578,7 +578,7 @@ static int usage(char *name){
|
||||
printf(" -P, --port=port Port to connect (1 - 65535)\n");
|
||||
printf(" -u, --user=user@domain user@domain\n");
|
||||
printf(" -p, --password=password Password\n");
|
||||
printf(" -i, --interrupt Allow Control-c to interrupt");
|
||||
printf(" -i, --interrupt Allow Control-c to interrupt\n");
|
||||
printf(" -x, --execute=command Execute Command and Exit\n");
|
||||
printf(" -l, --loglevel=command Log Level\n");
|
||||
printf(" -q, --quiet Disable logging\n");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
PERL=$(shell which perl)
|
||||
PERL_SITEDIR=$(shell perl -MConfig -e 'print $$Config{sitelibexp}')
|
||||
PERL_LIBDIR=-L$(shell perl -MConfig -e 'print $$Config{archlib}')/CORE
|
||||
PERL_LIBS=$(shell perl -MConfig -e 'print $$Config{libs}')
|
||||
LOCAL_CFLAGS=-w -DMULTIPLICITY $(shell $(PERL) -MExtUtils::Embed -e ccopts) -DEMBED_PERL
|
||||
@@ -30,3 +31,8 @@ swigclean:
|
||||
|
||||
reswig: swigclean esl_wrap.cpp perlxsi.c
|
||||
|
||||
install: ESL.so
|
||||
install -m 755 ESL.so $(PERL_SITEDIR)
|
||||
install -m 755 ESL.pm $(PERL_SITEDIR)
|
||||
install -d -m 755 ESL $(PERL_SITEDIR)/ESL
|
||||
install -m 755 ESL/* $(PERL_SITEDIR)/ESL
|
||||
@@ -18,6 +18,7 @@ FreeSWITCH Logger Utility
|
||||
|
||||
USAGE:
|
||||
-h --help This help
|
||||
-H --host Choose host
|
||||
-p --port <port> Choose port
|
||||
-P -pass <pass> Choose password
|
||||
-f --file <file> Output file
|
||||
@@ -42,12 +43,12 @@ sub parse(\$\$$) {
|
||||
}
|
||||
|
||||
for($i = 0; $i < $argc; $i++) {
|
||||
if ($ARGV[$i] =~ /^\-help$|^\-\-help$/) {
|
||||
if ($ARGV[$i] =~ /^\-h$|^\-\-help$/) {
|
||||
print $USAGE;
|
||||
exit;
|
||||
}
|
||||
|
||||
if (! (parse($i, $host, '^-h$|^--host$') ||
|
||||
if (! (parse($i, $host, '^-H$|^--host$') ||
|
||||
parse($i, $port, '^-p$|^--port$') ||
|
||||
parse($i, $pass, '^-P$|^--pass$') ||
|
||||
parse($i, $file, '^-f$|^--file$') ||
|
||||
|
||||
+1
-1
@@ -934,7 +934,6 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
|
||||
goto fail;
|
||||
}
|
||||
|
||||
esl_event_safe_destroy(&handle->last_event);
|
||||
esl_event_safe_destroy(&handle->last_ievent);
|
||||
|
||||
if (check_q && handle->race_event) {
|
||||
@@ -1053,6 +1052,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
|
||||
*save_event = revent;
|
||||
revent = NULL;
|
||||
} else {
|
||||
esl_event_safe_destroy(&handle->last_event);
|
||||
handle->last_event = revent;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,3 +29,8 @@ testtones
|
||||
!/sample/boost/Makefile
|
||||
!/sample/dso/Makefile
|
||||
|
||||
freetdm.2010.sdf
|
||||
/mod_freetdm/Win32/
|
||||
/msvc/Win32/
|
||||
/src/ftmod/*/Win32/
|
||||
/src/ftmod/*/x64/
|
||||
@@ -20,6 +20,9 @@ cpu_reset_alarm_threshold => 70
|
||||
; cpu_alarm_action => warn,reject
|
||||
cpu_alarm_action => warn
|
||||
|
||||
; Where to dump DTMF debug files (see per span debugdtmf=yes option)
|
||||
debugdtmf_directory=/full/path/to/dtmf/directory
|
||||
|
||||
; spans are defined with [span <span type> <span name>]
|
||||
; the span type can either be zt, wanpipe or pika
|
||||
; the span name can be any unique string
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
[defaults]
|
||||
; User space interval at which data will be delivered
|
||||
codec_ms => 20
|
||||
|
||||
; wink and flash interval
|
||||
wink_ms => 150
|
||||
flash_ms => 750
|
||||
|
||||
; size of the driver queue of elements of MTU size
|
||||
; typical case is 10 elements of 80 bytes each (10ms of ulaw/alaw)
|
||||
; don't mess with this if you don't know what you're doing
|
||||
; txqueue_size => 10
|
||||
; rxqueue_size => 10
|
||||
@@ -10,6 +10,7 @@ example #1a - Making an outbound call:
|
||||
|
||||
To make an outbound call:
|
||||
ftdm_usrmsg_t usrmsg;
|
||||
memset(&usrmsg, 0, sizeof(usrmsg));
|
||||
|
||||
/* Attach variable to usrmsg */
|
||||
ftdm_usrmsg_add_var(&usrmsg, "isdn.prog_ind.descr", "inband-info-available");
|
||||
@@ -22,6 +23,7 @@ When using ftmod_sangoma_isdn, user want to specify progress indicator inside PR
|
||||
|
||||
|
||||
ftdm_usrmsg_t usrmsg;
|
||||
memset(&usrmsg, 0, sizeof(usrmsg));
|
||||
|
||||
/* Attach variable to usrmsg */
|
||||
ftdm_usrmsg_add_var(&usrmsg, "isdn.prog_ind.descr", "inband-info-available");
|
||||
@@ -40,6 +42,8 @@ When using ftmod_sangoma_isdn, user wants to transmit a custom Facility IE, insi
|
||||
uint8_t *my_facility_ie = ftdm_calloc(1, 200); /*memory has to be allocated using ftdm_calloc !! */
|
||||
unsigned my_facility_ie_len = 0;
|
||||
|
||||
memset(&usrmsg, 0, sizeof(usrmsg));
|
||||
|
||||
/* Fill my_facility_ie with custom data here */
|
||||
my_facility_ie[my_facility_ie_len++] = 0x1C; /* Q.931 Facility IE ID */
|
||||
my_facility_ie[my_facility_ie_len++] = 0x03; /* Length of facility IE */
|
||||
@@ -49,7 +53,7 @@ When using ftmod_sangoma_isdn, user wants to transmit a custom Facility IE, insi
|
||||
|
||||
ftdm_usrmsg_set_raw_data(&usrmsg, my_facility_ie, my_facility_ie_len);
|
||||
|
||||
ftdm_channel_call_indicate(ftdmchan, FTDM_CHANNEL_INDICATE_FACILITY, &usrmsg);
|
||||
ftdm_channel_call_indicate_ex(ftdmchan, FTDM_CHANNEL_INDICATE_FACILITY, &usrmsg);
|
||||
|
||||
/* FreeTDM will automatically free my_facility_ie */
|
||||
|
||||
|
||||
@@ -3621,8 +3621,9 @@ void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *
|
||||
"ftdm trace <path> <span_id|span_name> [<chan_id>]\n" \
|
||||
"ftdm notrace <span_id|span_name> [<chan_id>]\n" \
|
||||
"ftdm q931_pcap <span_id> on|off [pcapfilename without suffix]\n" \
|
||||
"ftdm gains <txgain> <rxgain> <span_id> [<chan_id>]\n" \
|
||||
"ftdm gains <rxgain> <txgain> <span_id> [<chan_id>]\n" \
|
||||
"ftdm dtmf on|off <span_id> [<chan_id>]\n" \
|
||||
"ftdm queuesize <rxsize> <txsize> <span_id> [<chan_id>]\n" \
|
||||
"--------------------------------------------------------------------------------\n"
|
||||
SWITCH_STANDARD_API(ft_function)
|
||||
{
|
||||
@@ -4059,7 +4060,7 @@ SWITCH_STANDARD_API(ft_function)
|
||||
ftdm_channel_t *chan;
|
||||
ftdm_span_t *span = NULL;
|
||||
if (argc < 4) {
|
||||
stream->write_function(stream, "-ERR Usage: ft gains <txgain> <rxgain> <span_id> [<chan_id>]\n");
|
||||
stream->write_function(stream, "-ERR Usage: ftdm gains <rxgain> <txgain> <span_id> [<chan_id>]\n");
|
||||
goto end;
|
||||
}
|
||||
ftdm_span_find_by_name(argv[3], &span);
|
||||
@@ -4094,6 +4095,50 @@ SWITCH_STANDARD_API(ft_function)
|
||||
}
|
||||
}
|
||||
stream->write_function(stream, "+OK gains set to Rx %f and Tx %f\n", rxgain, txgain);
|
||||
} else if (!strcasecmp(argv[0], "queuesize")) {
|
||||
unsigned int i = 0;
|
||||
uint32_t rxsize = 10;
|
||||
uint32_t txsize = 10;
|
||||
uint32_t chan_id = 0;
|
||||
uint32_t ccount = 0;
|
||||
ftdm_channel_t *chan;
|
||||
ftdm_span_t *span = NULL;
|
||||
if (argc < 4) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm queuesize <rxsize> <txsize> <span_id> [<chan_id>]\n");
|
||||
goto end;
|
||||
}
|
||||
ftdm_span_find_by_name(argv[3], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
goto end;
|
||||
}
|
||||
if (argc > 4) {
|
||||
chan_id = atoi(argv[4]);
|
||||
if (chan_id > ftdm_span_get_chan_count(span)) {
|
||||
stream->write_function(stream, "-ERR invalid chan\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
i = sscanf(argv[1], "%u", &rxsize);
|
||||
i += sscanf(argv[2], "%u", &txsize);
|
||||
if (i != 2) {
|
||||
stream->write_function(stream, "-ERR invalid queue sizes provided\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (chan_id) {
|
||||
chan = ftdm_span_get_channel(span, chan_id);
|
||||
ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &rxsize);
|
||||
ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &txsize);
|
||||
} else {
|
||||
ccount = ftdm_span_get_chan_count(span);
|
||||
for (i = 1; i < ccount; i++) {
|
||||
chan = ftdm_span_get_channel(span, i);
|
||||
ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &rxsize);
|
||||
ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &txsize);
|
||||
}
|
||||
}
|
||||
stream->write_function(stream, "+OK queue sizes set to Rx %d and Tx %d\n", rxsize, txsize);
|
||||
} else if (!strcasecmp(argv[0], "restart")) {
|
||||
uint32_t chan_id = 0;
|
||||
ftdm_channel_t *chan;
|
||||
@@ -4243,6 +4288,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
|
||||
switch_console_set_complete("add ftdm notrace");
|
||||
switch_console_set_complete("add ftdm q931_pcap");
|
||||
switch_console_set_complete("add ftdm gains");
|
||||
switch_console_set_complete("add ftdm queuesize");
|
||||
switch_console_set_complete("add ftdm dtmf on");
|
||||
switch_console_set_complete("add ftdm dtmf off");
|
||||
switch_console_set_complete("add ftdm core state");
|
||||
|
||||
+25
-21
@@ -244,6 +244,7 @@ static struct {
|
||||
ftdm_caller_data_t *call_ids[MAX_CALLIDS+1];
|
||||
ftdm_mutex_t *call_id_mutex;
|
||||
uint32_t last_call_id;
|
||||
char dtmfdebug_directory[1024];
|
||||
} globals;
|
||||
|
||||
enum ftdm_enum_cpu_alarm_action_flags
|
||||
@@ -2310,7 +2311,9 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
|
||||
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING);
|
||||
}
|
||||
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||
if (indication != FTDM_CHANNEL_INDICATE_FACILITY &&
|
||||
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||
|
||||
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Cannot indicate %s in outgoing channel in state %s\n",
|
||||
ftdm_channel_indication2str(indication), ftdm_channel_state2str(ftdmchan->state));
|
||||
status = FTDM_EINVAL;
|
||||
@@ -2525,20 +2528,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *fchan, ftd
|
||||
|
||||
ftdm_channel_lock(fchan);
|
||||
|
||||
if (ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) {
|
||||
ftdm_log_chan_msg(fchan, FTDM_LOG_WARNING, "You can not set the signaling status of an alarmed channel\n");
|
||||
res = FTDM_EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sigstatus == FTDM_SIG_STATE_DOWN) {
|
||||
ftdm_log_chan_msg(fchan, FTDM_LOG_WARNING, "You can not set the signaling status to DOWN, valid states are UP or SUSPENDED\n");
|
||||
res = FTDM_EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
res = fchan->span->set_channel_sig_status(fchan, sigstatus);
|
||||
done:
|
||||
|
||||
ftdm_channel_unlock(fchan);
|
||||
|
||||
@@ -3469,7 +3459,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
|
||||
if (!ftdmchan->dtmfdbg.file) {
|
||||
struct tm currtime;
|
||||
time_t currsec;
|
||||
char dfile[512];
|
||||
char dfile[1024];
|
||||
|
||||
currsec = time(NULL);
|
||||
|
||||
@@ -3480,10 +3470,18 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, cons
|
||||
localtime_r(&currsec, &currtime);
|
||||
#endif
|
||||
|
||||
snprintf(dfile, sizeof(dfile), "dtmf-s%dc%d-20%d-%d-%d-%d:%d:%d.%s",
|
||||
ftdmchan->span_id, ftdmchan->chan_id,
|
||||
currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday,
|
||||
currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln");
|
||||
if (ftdm_strlen_zero(globals.dtmfdebug_directory)) {
|
||||
snprintf(dfile, sizeof(dfile), "dtmf-s%dc%d-20%d-%d-%d-%d:%d:%d.%s",
|
||||
ftdmchan->span_id, ftdmchan->chan_id,
|
||||
currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday,
|
||||
currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln");
|
||||
} else {
|
||||
snprintf(dfile, sizeof(dfile), "%s/dtmf-s%dc%d-20%d-%d-%d-%d:%d:%d.%s",
|
||||
globals.dtmfdebug_directory,
|
||||
ftdmchan->span_id, ftdmchan->chan_id,
|
||||
currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday,
|
||||
currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln");
|
||||
}
|
||||
ftdmchan->dtmfdbg.file = fopen(dfile, "wb");
|
||||
if (!ftdmchan->dtmfdbg.file) {
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "failed to open debug dtmf file %s\n", dfile);
|
||||
@@ -4697,6 +4695,9 @@ static ftdm_status_t load_config(void)
|
||||
globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN;
|
||||
}
|
||||
}
|
||||
} else if (!strncasecmp(var, "debugdtmf_directory", sizeof("debugdtmf_directory")-1)) {
|
||||
ftdm_set_string(globals.dtmfdebug_directory, val);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Debug DTMF directory set to '%s'\n", globals.dtmfdebug_directory);
|
||||
} else if (!strncasecmp(var, "cpu_monitoring_interval", sizeof("cpu_monitoring_interval")-1)) {
|
||||
if (atoi(val) > 0) {
|
||||
globals.cpu_monitor.interval = atoi(val);
|
||||
@@ -6057,9 +6058,12 @@ FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data_detached(ftdm_sigmsg_t *sigms
|
||||
if (!sigmsg || !sigmsg->raw.len) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
|
||||
*data = sigmsg->raw.data;
|
||||
*datalen = sigmsg->raw.len;
|
||||
*datalen = sigmsg->raw.len;
|
||||
|
||||
sigmsg->raw.data = NULL;
|
||||
sigmsg->raw.len = 0;
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -943,12 +943,12 @@ static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
|
||||
|
||||
if (chan) {
|
||||
/* Open channel if inband information is available */
|
||||
if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
|
||||
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
|
||||
ftdm_channel_get_span_id(chan),
|
||||
ftdm_channel_get_id(chan));
|
||||
|
||||
if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
|
||||
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && (ftdm_channel_open_chan(chan) != FTDM_SUCCESS)) {
|
||||
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
|
||||
|
||||
ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
|
||||
@@ -985,12 +985,12 @@ static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
|
||||
|
||||
if (chan) {
|
||||
/* Open channel if inband information is available */
|
||||
if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
|
||||
if (pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
|
||||
ftdm_channel_get_span_id(chan),
|
||||
ftdm_channel_get_id(chan));
|
||||
|
||||
if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
|
||||
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && (ftdm_channel_open_chan(chan) != FTDM_SUCCESS)) {
|
||||
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
|
||||
|
||||
ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
|
||||
@@ -1028,8 +1028,6 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
|
||||
ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->ringing.channel);
|
||||
|
||||
if (chan) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", ftdm_span_get_id(span), pevent->ringing.channel);
|
||||
|
||||
/* we may get on_ringing even when we're already in FTDM_CHANNEL_STATE_PROGRESS_MEDIA */
|
||||
// if (ftdm_channel_get_state(chan) == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
|
||||
// /* dont try to move to STATE_PROGRESS to avoid annoying veto warning */
|
||||
@@ -1037,12 +1035,12 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
|
||||
// }
|
||||
|
||||
/* Open channel if inband information is available */
|
||||
if ((pevent->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
|
||||
if ((pevent->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, B-Channel %d:%d\n",
|
||||
ftdm_channel_get_span_id(chan),
|
||||
ftdm_channel_get_id(chan));
|
||||
|
||||
if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
|
||||
if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && (ftdm_channel_open_chan(chan) != FTDM_SUCCESS)) {
|
||||
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
|
||||
|
||||
ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
|
||||
@@ -1053,9 +1051,13 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
|
||||
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
goto out;
|
||||
}
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d with media\n", ftdm_span_get_id(span), pevent->proceeding.channel);
|
||||
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
} else {
|
||||
// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel);
|
||||
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RINGING);
|
||||
}
|
||||
// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
|
||||
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RINGING);
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d but it's not in the span?\n",
|
||||
ftdm_span_get_id(span), pevent->ringing.channel);
|
||||
|
||||
@@ -520,6 +520,28 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status)
|
||||
openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
|
||||
openr2_cas_signal_t rxcas, txcas;
|
||||
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG,
|
||||
"Received request to change sig status of alarmed channel to %s", ftdm_signaling_status2str(status));
|
||||
|
||||
switch (status) {
|
||||
case FTDM_SIG_STATE_SUSPENDED:
|
||||
openr2_chan_set_blocked(r2chan);
|
||||
/* Need to send sig status change to SUSPENDED once out of alarm */
|
||||
R2CALL(ftdmchan)->localsuspend_on_alarm = 1;
|
||||
break;
|
||||
case FTDM_SIG_STATE_UP:
|
||||
openr2_chan_set_blocked(r2chan);
|
||||
/* DO NOT send sig status change to SUSPENDED once out of alarm */
|
||||
R2CALL(ftdmchan)->localsuspend_on_alarm = 0;
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
/* get the current rx and tx cas bits */
|
||||
openr2_chan_get_cas(r2chan, &rxcas, &txcas);
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""C:\Program Files\sangoma\sng_isdn\include";../../include;"C:\Program Files\Sangoma\include""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="2"
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
@@ -157,7 +157,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
|
||||
@@ -333,7 +333,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
|
||||
parse_yesno(var, val, &signal_data->setup_arb);
|
||||
} else if (!strcasecmp(var, "facility")) {
|
||||
parse_yesno(var, val, &signal_data->facility);
|
||||
} else if (!strcasecmp(var, "min_digits")) {
|
||||
} else if (!strcasecmp(var, "min-digits") ||
|
||||
!strcasecmp(var, "min_digits")) {
|
||||
signal_data->min_digits = atoi(val);
|
||||
} else if (!strcasecmp(var, "outbound-called-ton")) {
|
||||
ftdm_set_ton(val, &span->default_caller_data.dnis.type);
|
||||
@@ -347,11 +348,11 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
|
||||
ftdm_set_ton(val, &span->default_caller_data.rdnis.type);
|
||||
} else if (!strcasecmp(var, "outbound-rdnis-npi")) {
|
||||
ftdm_set_npi(val, &span->default_caller_data.rdnis.plan);
|
||||
} else if (!strcasecmp(var, "outbound-bearer_cap") ||
|
||||
!strcasecmp(var, "outbound-bc-transfer-cap")) {
|
||||
} else if (!strcasecmp(var, "outbound-bc-transfer-cap") ||
|
||||
!strcasecmp(var, "outbound-bearer_cap")) {
|
||||
ftdm_set_bearer_capability(val, (uint8_t*)&span->default_caller_data.bearer_capability);
|
||||
} else if (!strcasecmp(var, "outbound-bearer_layer1") ||
|
||||
!strcasecmp(var, "outbound-bc-user-layer1")) {
|
||||
} else if (!strcasecmp(var, "outbound-bc-user-layer1") ||
|
||||
!strcasecmp(var, "outbound-bearer_layer1")) {
|
||||
ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1);
|
||||
} else if (!strcasecmp(var, "channel-restart-on-link-up")) {
|
||||
parse_yesno(var, val, &signal_data->restart_opt);
|
||||
|
||||
@@ -807,17 +807,10 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
|
||||
|
||||
if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
|
||||
/* If Facility decoding is disabled, we do not care about current call state, just pass event up to user */
|
||||
ftdm_sigmsg_t sigev;
|
||||
if (facEvnt->facElmt.facStr.pres) {
|
||||
get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len-2);
|
||||
sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_FACILITY);
|
||||
}
|
||||
memset(&sigev, 0, sizeof(sigev));
|
||||
sigev.chan_id = ftdmchan->chan_id;
|
||||
sigev.span_id = ftdmchan->span_id;
|
||||
sigev.channel = ftdmchan;
|
||||
|
||||
sigev.event_id = FTDM_SIGEVENT_FACILITY;
|
||||
ftdm_span_send_signal(ftdmchan->span, &sigev);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -677,20 +677,20 @@ void sngisdn_rcv_q921_ind(BdMngmt *status)
|
||||
}
|
||||
|
||||
switch (status->t.usta.alarm.category) {
|
||||
case (LCM_CATEGORY_INTERFACE):
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
|
||||
ftdmspan->name,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
case (LCM_CATEGORY_PROTOCOL):
|
||||
ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
|
||||
ftdmspan->name,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
|
||||
ftdmspan->name,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
|
||||
ftdmspan->name,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
|
||||
switch (status->t.usta.alarm.event) {
|
||||
case ENTR_CONG: /* Entering Congestion */
|
||||
ftdm_log(FTDM_LOG_WARNING, "s%d: Entering Congestion\n", ftdmspan->span_id);
|
||||
|
||||
@@ -370,7 +370,7 @@ ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8
|
||||
my_data[1] = data_len;
|
||||
memcpy(&my_data[2], data, data_len);
|
||||
|
||||
sngisdn_add_raw_data((sngisdn_chan_data_t*)ftdmchan->call_data, data, data_len+2);
|
||||
sngisdn_add_raw_data((sngisdn_chan_data_t*)ftdmchan->call_data, my_data, data_len+2);
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Raw Facility IE copied available\n");
|
||||
} else {
|
||||
|
||||
@@ -114,7 +114,7 @@ void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace
|
||||
{
|
||||
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
|
||||
sngisdn_decode_q921(data_str, data, data_len);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
|
||||
ftdm_safe_free(data_str);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ typedef enum {
|
||||
*/
|
||||
static struct {
|
||||
uint32_t codec_ms;
|
||||
uint32_t rxqueue_size;
|
||||
uint32_t txqueue_size;
|
||||
uint32_t wink_ms;
|
||||
uint32_t flash_ms;
|
||||
uint32_t ring_on_ms;
|
||||
@@ -406,6 +408,20 @@ static FIO_CONFIGURE_FUNCTION(wanpipe_configure)
|
||||
} else {
|
||||
wp_globals.codec_ms = num;
|
||||
}
|
||||
} else if (!strcasecmp(var, "rxqueue_size")) {
|
||||
num = atoi(val);
|
||||
if (num < 1 || num > 1000) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "invalid rx queue size at line %d\n", lineno);
|
||||
} else {
|
||||
wp_globals.rxqueue_size = num;
|
||||
}
|
||||
} else if (!strcasecmp(var, "txqueue_size")) {
|
||||
num = atoi(val);
|
||||
if (num < 1 || num > 1000) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "invalid tx queue size at line %d\n", lineno);
|
||||
} else {
|
||||
wp_globals.txqueue_size = num;
|
||||
}
|
||||
} else if (!strcasecmp(var, "wink_ms")) {
|
||||
num = atoi(val);
|
||||
if (num < 50 || num > 3000) {
|
||||
@@ -544,6 +560,13 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
|
||||
ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL);
|
||||
ftdmchan->effective_interval = ftdmchan->native_interval = wp_globals.codec_ms;
|
||||
ftdmchan->packet_len = ftdmchan->native_interval * 8;
|
||||
|
||||
if (wp_globals.txqueue_size > 0) {
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &wp_globals.txqueue_size);
|
||||
}
|
||||
if (wp_globals.rxqueue_size > 0) {
|
||||
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &wp_globals.rxqueue_size);
|
||||
}
|
||||
}
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
@@ -1315,14 +1338,12 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
|
||||
status = FTDM_BREAK;
|
||||
} else {
|
||||
ftdm_status_t status;
|
||||
wanpipe_tdm_api_t onhook_tdm_api;
|
||||
memset(&onhook_tdm_api, 0, sizeof(onhook_tdm_api));
|
||||
status = sangoma_tdm_txsig_onhook(fchan->sockfd, &onhook_tdm_api);
|
||||
status = sangoma_tdm_txsig_onhook(fchan->sockfd, tdm_api);
|
||||
if (status) {
|
||||
snprintf(fchan->last_error, sizeof(fchan->last_error), "ONHOOK Failed");
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
*event_id = onhook_tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP;
|
||||
*event_id = tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_ONHOOK : FTDM_OOB_NOOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1575,6 +1596,9 @@ static FIO_IO_LOAD_FUNCTION(wanpipe_init)
|
||||
wp_globals.flash_ms = 750;
|
||||
wp_globals.ring_on_ms = 2000;
|
||||
wp_globals.ring_off_ms = 4000;
|
||||
/* 0 for queue size will leave driver defaults */
|
||||
wp_globals.txqueue_size = 0;
|
||||
wp_globals.rxqueue_size = 0;
|
||||
wanpipe_interface.name = "wanpipe";
|
||||
wanpipe_interface.configure_span = wanpipe_configure_span;
|
||||
wanpipe_interface.configure = wanpipe_configure;
|
||||
|
||||
@@ -1064,6 +1064,20 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
|
||||
fchan->rx_cas_bits = bits;
|
||||
}
|
||||
break;
|
||||
case ZT_EVENT_BADFCS:
|
||||
{
|
||||
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Bad frame checksum (ZT_EVENT_BADFCS)!\n");
|
||||
/* What else could we do? */
|
||||
*event_id = FTDM_OOB_NOOP;
|
||||
}
|
||||
break;
|
||||
case ZT_EVENT_OVERRUN:
|
||||
{
|
||||
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Driver overrun! (ZT_EVENT_OVERRUN)\n");
|
||||
/* What else could we do? */
|
||||
*event_id = FTDM_OOB_NOOP;
|
||||
}
|
||||
break;
|
||||
case ZT_EVENT_NONE:
|
||||
{
|
||||
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "No event\n");
|
||||
|
||||
@@ -1463,11 +1463,6 @@ FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter);
|
||||
*/
|
||||
FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter);
|
||||
|
||||
/*! \brief Clears all the temporary data attached to this call
|
||||
* \note Clears caller_data->variables and caller_data->raw_data.
|
||||
* */
|
||||
FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data);
|
||||
|
||||
/*! \brief Get the span pointer associated to the channel */
|
||||
FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan);
|
||||
|
||||
|
||||
@@ -384,9 +384,12 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
|
||||
}
|
||||
|
||||
while(xml) {
|
||||
char *type = xtype ? xtype : iks_find_attrib(xml, "type");
|
||||
char *type = NULL;
|
||||
iks *tag;
|
||||
|
||||
|
||||
if (iks_type(xml)!=IKS_CDATA)
|
||||
type = xtype ? xtype : iks_find_attrib(xml, "type");
|
||||
|
||||
if (type) {
|
||||
|
||||
if (!strcasecmp(type, "redirect")) {
|
||||
@@ -994,9 +997,9 @@ static int on_commands(void *user_data, ikspak *pak)
|
||||
uint8_t is_result = strcasecmp(type, "result") ? 0 : 1;
|
||||
uint8_t is_error = strcasecmp(type, "error") ? 0 : 1;
|
||||
iks *xml, *xsession, *xerror = NULL, *xredir = NULL;
|
||||
|
||||
struct iks_tag* tmp;
|
||||
xml = iks_child (pak->x);
|
||||
|
||||
tmp = (struct iks_tag*) xml;
|
||||
if (is_error) {
|
||||
if ((xerror = working_find(xml, "error"))) {
|
||||
char *code = iks_find_attrib(xerror, "code");
|
||||
|
||||
@@ -1 +1 @@
|
||||
Wed Nov 3 13:53:34 EDT 2010
|
||||
Tue Mar 22 15:01:49 CDT 2011
|
||||
@@ -7781,7 +7781,7 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
|
||||
if (tpn) {
|
||||
/* CANCEL or ACK to [3456]XX */
|
||||
invalid = tport_name_dup(home, orq->orq_tpn, tpn);
|
||||
#if HAVE_SOFIA_SRESOLV
|
||||
#if 0 //HAVE_SOFIA_SRESOLV
|
||||
/* We send ACK or CANCEL only if original request was really sent */
|
||||
assert(tport_name_is_resolved(orq->orq_tpn));
|
||||
#endif
|
||||
|
||||
@@ -251,6 +251,8 @@ int su_pthreaded_port_start(su_port_create_f *create,
|
||||
|
||||
int thread_created = 0;
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
struct sched_param param;
|
||||
|
||||
arg.create = create;
|
||||
arg.parent = parent;
|
||||
@@ -258,11 +260,19 @@ int su_pthreaded_port_start(su_port_create_f *create,
|
||||
arg.init = init;
|
||||
arg.deinit = deinit;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, 244);
|
||||
pthread_attr_getschedparam(&attr, ¶m);
|
||||
param.sched_priority = 1;
|
||||
pthread_attr_setschedparam(&attr, ¶m);
|
||||
|
||||
pthread_mutex_lock(arg.mutex);
|
||||
if (pthread_create(&tid, NULL, su_pthread_port_clone_main, &arg) == 0) {
|
||||
if (pthread_create(&tid, &attr, su_pthread_port_clone_main, &arg) == 0) {
|
||||
pthread_cond_wait(arg.cv, arg.mutex);
|
||||
thread_created = 1;
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
pthread_mutex_unlock(arg.mutex);
|
||||
|
||||
pthread_mutex_destroy(arg.mutex);
|
||||
|
||||
@@ -652,6 +652,7 @@ static __inline__ void force_drop_rx_bits(t4_state_t *s, int bits)
|
||||
static int rx_put_bits(t4_state_t *s, uint32_t bit_string, int quantity)
|
||||
{
|
||||
int bits;
|
||||
int old_a0;
|
||||
|
||||
/* We decompress bit by bit, as the data stream is received. We need to
|
||||
scan continuously for EOLs, so we might as well work this way. */
|
||||
@@ -809,8 +810,23 @@ static int rx_put_bits(t4_state_t *s, uint32_t bit_string, int quantity)
|
||||
s->t4_t6_rx.a0,
|
||||
s->t4_t6_rx.b1,
|
||||
s->t4_t6_rx.run_length);
|
||||
s->t4_t6_rx.run_length += (s->t4_t6_rx.b1 - s->t4_t6_rx.a0 + t4_2d_table[bits].param);
|
||||
old_a0 = s->t4_t6_rx.a0;
|
||||
s->t4_t6_rx.a0 = s->t4_t6_rx.b1 + t4_2d_table[bits].param;
|
||||
/* We need to check if a bad or malicious image is failing to move forward along the row.
|
||||
Going back is obviously bad. We also need to avoid a stall on the spot, except for the
|
||||
special case of the start of the row. Zero movement as the very first element in the
|
||||
row is perfectly normal. */
|
||||
if (s->t4_t6_rx.a0 <= old_a0)
|
||||
{
|
||||
if (s->t4_t6_rx.a0 < old_a0 || s->t4_t6_rx.b_cursor > 1)
|
||||
{
|
||||
/* Undo the update we just started, and carry on as if this code does not exist */
|
||||
/* TODO: we really should record that something wasn't right at this point. */
|
||||
s->t4_t6_rx.a0 = old_a0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s->t4_t6_rx.run_length += (s->t4_t6_rx.a0 - old_a0);
|
||||
add_run_to_row(s);
|
||||
/* We need to move one step in one direction or the other, to change to the
|
||||
opposite colour */
|
||||
@@ -832,8 +848,9 @@ static int rx_put_bits(t4_state_t *s, uint32_t bit_string, int quantity)
|
||||
s->ref_runs[s->t4_t6_rx.b_cursor],
|
||||
s->ref_runs[s->t4_t6_rx.b_cursor + 1]);
|
||||
s->t4_t6_rx.b1 += s->ref_runs[s->t4_t6_rx.b_cursor++];
|
||||
s->t4_t6_rx.run_length += (s->t4_t6_rx.b1 - s->t4_t6_rx.a0);
|
||||
old_a0 = s->t4_t6_rx.a0;
|
||||
s->t4_t6_rx.a0 = s->t4_t6_rx.b1;
|
||||
s->t4_t6_rx.run_length += (s->t4_t6_rx.a0 - old_a0);
|
||||
s->t4_t6_rx.b1 += s->ref_runs[s->t4_t6_rx.b_cursor++];
|
||||
break;
|
||||
case S_Ext:
|
||||
|
||||
+8
-2
@@ -428,6 +428,12 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void
|
||||
|
||||
i->ts_drift = ts + (i->ts_offset - timer_ts);
|
||||
|
||||
if (i->ts_offset && i->ts_drift > 0) {
|
||||
i->ts_offset = timer_ts - ts;
|
||||
i->ts_drift = ts + (i->ts_offset - timer_ts);
|
||||
}
|
||||
|
||||
|
||||
if (i->max_drift) {
|
||||
if (i->ts_drift < i->max_drift) {
|
||||
if (++i->drift_dropped_packets < i->drift_max_dropped) {
|
||||
@@ -518,8 +524,8 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void
|
||||
|
||||
|
||||
if (stfu_log != null_logger && i->debug) {
|
||||
stfu_log(STFU_LOG_EMERG, "I: %s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d %d/%d\n", i->name,
|
||||
i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count,
|
||||
stfu_log(STFU_LOG_EMERG, "I: %s %u/%u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d %d/%d\n", i->name,
|
||||
i->qlen, i->max_qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count,
|
||||
i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count,
|
||||
ts, ts / i->samples_per_packet,
|
||||
i->period_missing_count, i->period_need_range_avg,
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Fri Mar 16 17:20:44 EDT 2007
|
||||
@@ -1,504 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
#! /usr/bin/make -rf
|
||||
# $Id: Makefile,v 1.42 2006/11/29 21:27:01 mjt Exp $
|
||||
# libudns Makefile
|
||||
#
|
||||
# Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
# This file is part of UDNS library, an async DNS stub resolver.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library, in file named COPYING.LGPL; if not,
|
||||
# write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
# Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
VERS = 0.0.9pre
|
||||
SRCS = udns_dn.c udns_dntosp.c udns_parse.c udns_resolver.c udns_misc.c \
|
||||
udns_rr_a.c udns_rr_ptr.c udns_rr_mx.c udns_rr_txt.c udns_bl.c \
|
||||
udns_rr_srv.c udns_rr_naptr.c udns_codes.c
|
||||
USRCS = dnsget.c rblcheck.c ex-rdns.c
|
||||
DEB = debian/copyright debian/changelog debian/control debian/rules
|
||||
DIST = COPYING.LGPL udns.h udns.3 dnsget.1 rblcheck.1 $(SRCS) $(USRCS) \
|
||||
Makefile TODO NOTES
|
||||
|
||||
OBJS = $(SRCS:.c=.o) $(GEN:.c=.o)
|
||||
LIB = libudns.a
|
||||
|
||||
SOVER = 0
|
||||
SOBJS = $(OBJS:.o=.lo)
|
||||
SOLIB = libudns.so
|
||||
SOLIBV = $(SOLIB).$(SOVER)
|
||||
|
||||
LIBS = $(LIB) $(SOLIBV)
|
||||
|
||||
UTILS = $(USRCS:.c=)
|
||||
SOUTILS = $(USRCS:.c=.shared)
|
||||
|
||||
NAMEPFX = udns-$(VERS)
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -W -Wmissing-prototypes -O2 -fPIC
|
||||
CDEFS = -DHAVE_POLL
|
||||
PICFLAGS = -fPIC
|
||||
AWK = awk
|
||||
|
||||
all: static
|
||||
|
||||
.SUFFIXES: .c .o .lo .shared
|
||||
|
||||
static: $(LIB) $(UTILS)
|
||||
staticlib: $(LIB)
|
||||
$(LIB): $(OBJS)
|
||||
-rm -f $@
|
||||
$(AR) rv $@ $(OBJS)
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(CDEFS) -c $<
|
||||
$(OBJS): udns.h
|
||||
|
||||
$(UTILS): udns.h $(LIB)
|
||||
.c:
|
||||
$(CC) $(CFLAGS) $(CDEFS) -o $@ $< $(LIB)
|
||||
|
||||
shared: $(SOLIBV) $(SOUTILS)
|
||||
sharedlib: $(SOLIBV)
|
||||
|
||||
$(SOLIBV): $(SOBJS)
|
||||
$(CC) -shared -Wl,--soname,$(SOLIBV) -o $@ $(SOBJS)
|
||||
rm -f $(SOLIB)
|
||||
ln -s $(SOLIBV) $(SOLIB)
|
||||
.c.lo:
|
||||
$(CC) $(CFLAGS) $(PICFLAGS) $(CDEFS) -o $@ -c $<
|
||||
$(SOBJS): udns.h
|
||||
|
||||
$(SOUTILS): udns.h $(SOLIB)
|
||||
.c.shared:
|
||||
$(CC) $(CFLAGS) $(CDEFS) -o $@ $< $(SOLIB)
|
||||
|
||||
# udns_codes.c is generated from udns.h
|
||||
udns_codes.c: udns.h Makefile
|
||||
@echo Generating $@
|
||||
@set -e; exec >$@.tmp; \
|
||||
set T type C class R rcode; \
|
||||
echo "/* Automatically generated. */"; \
|
||||
echo "#include \"udns.h\""; \
|
||||
while [ "$$1" ]; do \
|
||||
echo; \
|
||||
echo "const struct dns_nameval dns_$${2}tab[] = {"; \
|
||||
$(AWK) "/^ DNS_$${1}_[A-Z0-9_]+[ ]*=/ \
|
||||
{ printf \" {%s,\\\"%s\\\"},\\n\", \$$1, substr(\$$1,7) }" \
|
||||
udns.h ; \
|
||||
echo " {0,0}};"; \
|
||||
echo "const char *dns_$${2}name(enum dns_$${2} code) {"; \
|
||||
echo " static char nm[20];"; \
|
||||
echo " switch(code) {"; \
|
||||
$(AWK) "BEGIN{i=0} \
|
||||
/^ DNS_$${1}_[A-Z0-9_]+[ ]*=/ \
|
||||
{printf \" case %s: return dns_$${2}tab[%d].name;\\n\",\$$1,i++}\
|
||||
" udns.h ; \
|
||||
echo " }"; \
|
||||
echo " return _dns_format_code(nm,\"$$2\",code);"; \
|
||||
echo "}"; \
|
||||
shift 2; \
|
||||
done
|
||||
@mv $@.tmp $@
|
||||
|
||||
udns.3.html: udns.3
|
||||
groff -man -Thtml udns.3 > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
dist: $(NAMEPFX).tar.gz
|
||||
$(NAMEPFX).tar.gz: $(DIST) $(DEB)
|
||||
mkdir $(NAMEPFX) $(NAMEPFX)/debian
|
||||
ln $(DIST) $(NAMEPFX)
|
||||
ln $(DEB) $(NAMEPFX)/debian
|
||||
tar cvfz $@ $(NAMEPFX)
|
||||
rm -rf $(NAMEPFX)
|
||||
subdist:
|
||||
cp -p $(DIST) $(TARGET)/
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(SOBJS) build-stamp
|
||||
distclean: clean
|
||||
rm -f $(LIBS) libudns.so udns.3.html $(UTILS) $(SOUTILS)
|
||||
|
||||
.PHONY: all static staticlib shared sharedlib dist clean distclean subdist
|
||||
-193
@@ -1,193 +0,0 @@
|
||||
Assorted notes about udns (library).
|
||||
|
||||
UDP-only mode
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
First of all, since udns is (currently) UDP-only, there are some
|
||||
shortcomings.
|
||||
|
||||
It assumes that a reply will fit into a UDP buffer. With adoption of EDNS0,
|
||||
and general robustness of IP stacks, in most cases it's not an issue. But
|
||||
in some cases there may be problems:
|
||||
|
||||
- if an RRset is "very large" so it does not fit even in buffer of size
|
||||
requested by the library (current default is 4096; some servers limits
|
||||
it further), we will not see the reply, or will only see "damaged"
|
||||
reply (depending on the server)
|
||||
|
||||
- many DNS servers ignores EDNS0 option requests. In this case, no matter
|
||||
which buffer size udns library will request, such servers reply is limited
|
||||
to 512 bytes (standard pre-EDNS0 DNS packet size).
|
||||
|
||||
- some DNS servers, notable the ones used by Verisign for certain top-level
|
||||
domains, chokes on EDNS0-enabled queries, returning FORMERR. Such
|
||||
behavior isn't prohibited by DNS standards, but in my opinion it's at
|
||||
least weird - the server can easily ignore EDNS0 options and send a
|
||||
reply, instead of sending error.
|
||||
Currently, udns does nothing in this situation, completely ignoring the
|
||||
error returned by the server, and continue waiting for reply. It probably
|
||||
should grok that this server does not understand EDNS0 and retry w/o the
|
||||
options, but it does not. The end result - esp. if your local DNS
|
||||
server or - worse - broken firewall which inspects DNS packets and drops
|
||||
the ones which - from its point of view - are "broken" - is that you
|
||||
see only TEMPFAIL errors from the library trying to resolve ANY names.
|
||||
|
||||
Implementing TCP mode (together with non-EDNS0 fall-back as above) isn't
|
||||
difficult, but it complicates API significantly. Currently udns uses only
|
||||
single UDP socket (or - maybe in the future - two, see below), but in case of
|
||||
TCP, it will need to open and close sockets for TCP connections left and
|
||||
right, and that have to be integrated into an application's event loop in
|
||||
an easy and efficient way. Plus all the timeouts - different for connect(),
|
||||
write, and several stages of read.
|
||||
|
||||
IPv6 vs IPv4 usage
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is only relevant for nameservers reachable over IPv6, NOT for IPv6
|
||||
queries. I.e., if you've IPv6 addresses in 'nameservers' line in your
|
||||
/etc/resolv.conf file. Even more: if you have BOTH IPv6 AND IPv4 addresses
|
||||
there. Or pass them to udns initialization routines.
|
||||
|
||||
Since udns uses a single UDP socket to communicate with all nameservers,
|
||||
it should support both v4 and v6 communications. Most current platforms
|
||||
supports this mode - using PF_INET6 socket and V4MAPPED addresses, i.e,
|
||||
"tunnelling" IPv4 inside IPv6. But not all systems supports this. And
|
||||
more, it has been said that such mode is deprecated.
|
||||
|
||||
So, list only IPv4 or only IPv6 addresses, but don't mix them, in your
|
||||
/etc/resolv.conf.
|
||||
|
||||
An alternative is to use two sockets instead of 1 - one for IPv6 and one
|
||||
for IPv4. For now I'm not sure if it's worth the complexity - again, of
|
||||
the API, not the library itself (but this will not simplify library either).
|
||||
|
||||
Single socket for all queries
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Using single UDP socket for sending queries to all nameservers has obvious
|
||||
advantages. First it's, again, trivial, simple to use API. And simple
|
||||
library too. Also, after sending queries to all nameservers (in case first
|
||||
didn't reply in time), we will be able to receive late reply from first
|
||||
nameserver and accept it.
|
||||
|
||||
But this mode has disadvantages too. Most important is that it's much easier
|
||||
to send fake reply to us, as the UDP port where we expects the reply to come
|
||||
to is constant during the whole lifetime of an application. More secure
|
||||
implementations uses random port for every single query. While port number
|
||||
(16 bits integer) can not hold much randomness, it's still of some help.
|
||||
Ok, udns is a stub resolver, so it expects sorta friendly environment, but
|
||||
on LAN it's usually much easier to fire an attack, due to the speed of local
|
||||
network, where a bad guy can generate alot of packets in a short time.
|
||||
|
||||
Choosing of DNS QueryID
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is more a TODO item really. Currently, udns uses sequential number for
|
||||
query IDs. Which simplifies attacks even more (c.f. the previous item about
|
||||
single UDP port), making them nearly trivial. The library should use random
|
||||
number for query ID. But there's no portable way to get random numbers, even
|
||||
on various flavors of Unix. It's possible to use low bits from tv_nsec field
|
||||
returned by gettimeofday() (current time, nanoseconds), but I wrote the library
|
||||
in a way to avoid making system calls where possible, because many syscalls
|
||||
means many context switches and slow processes as a result. Maybe use some
|
||||
application-supplied callback to get random values will be a better way,
|
||||
defaulting to gettimeofday() method.
|
||||
|
||||
Note that a single query - even if (re)sent to different nameservers, several
|
||||
times (due to no reply received in time), uses the same qID assigned when it
|
||||
was first dispatched. So we have: single UDP socket (fixed port number),
|
||||
sequential (= trivially predictable) qIDs, and long lifetime of those qIDs.
|
||||
This all makes (local) attacks against the library really trivial.
|
||||
|
||||
Assumptions about RRs returned
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Currently udns processes records in the reply it received sequentially.
|
||||
This means that order of the records is significant. For example, if
|
||||
we asked for foo.bar A, but the server returned that foo.bar is a CNAME
|
||||
(alias) for bar.baz, and bar.baz, in turn, has address 1.2.3.4, when
|
||||
the CNAME should come first in reply, followed by A. While DNS specs
|
||||
does not say anything about order of records - it's an rrSET - unordered, -
|
||||
I think an implementation which returns the records in "wrong" order is
|
||||
somewhat insane... Well ok, to be fair, I don't really remember how
|
||||
udns handles this now - need to check this in source... ;)
|
||||
|
||||
CNAME recursion
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Another dark point of udns is the handling of CNAMEs returned as replies
|
||||
to non-CNAME queries. If we asked for foo.bar A, but it's a CNAME, udns
|
||||
expects BOTH the CNAME itself and the target DN to be present in the reply.
|
||||
In other words, udns DOES NOT RECURSE CNAMES. If we asked for foo.bar A,
|
||||
but only record in reply was that foo.bar is a CNAME for bar.baz, udns will
|
||||
return no records to an application (NXDOMAIN). Strictly speaking, udns
|
||||
should repeat the query asking for bar.baz A, and recurse. But since it's
|
||||
stub resolver, recursive resolver should recurse for us instead.
|
||||
|
||||
It's not very difficult to implement, however. Probably with some (global?)
|
||||
flag to en/dis-able the feature. Provided there's some demand for it.
|
||||
|
||||
To clarify: udns handles CNAME recursion in a single reply packet just fine.
|
||||
|
||||
Error reporting
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Too many places in the code (various failure paths) sets generic "TEMPFAIL"
|
||||
error condition. For example, if no nameserver replied to our query, an
|
||||
application will get generic TEMPFAIL, instead of something like TIMEDOUT.
|
||||
This probably should be fixed, but most applications don't care about the
|
||||
exact reasons of failure - 4 common cases are already too much:
|
||||
- query returned some valid data
|
||||
- NXDOMAIN
|
||||
- valid domain but no data of requested type - =NXDOMAIN in most cases
|
||||
- temporary error - this one sometimes (incorrectly!) treated as NXDOMAIN
|
||||
by (naive) applications.
|
||||
DNS isn't yes/no, it's at least 3 variants, temp err being the 3rd important
|
||||
case! And adding more variations for the temp error case is complicating things
|
||||
even more - again, from an application writer standpoint. For diagnostics,
|
||||
such more specific error cases are of good help.
|
||||
|
||||
Planned API changes
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
At least one thing I want to change for 0.1 version is a way how queries are
|
||||
submitted.
|
||||
|
||||
I want to made dns_query object to be owned by an application. So that instead
|
||||
of udns library allocating it for the lifetime of query, it will be pre-
|
||||
allocated by an application. This simplifies and enhances query submitting
|
||||
interface, and complicates it a bit too, in simplest cases.
|
||||
|
||||
Currently, we have:
|
||||
|
||||
dns_submit_dn(dn, cls, typ, flags, parse, cbck, data)
|
||||
dns_submit_p(name, cls, typ, flags, parse, cbck, data)
|
||||
dns_submit_a4(ctx, name, flags, cbck, data)
|
||||
|
||||
and so on -- with many parameters missed for type-specific cases, but generic
|
||||
cases being too complex for most common usage.
|
||||
|
||||
Instead, with dns_query being owned by an app, we will be able to separately
|
||||
set up various parts of the query - domain name (various forms), type&class,
|
||||
parser, flags, callback... and even change them at runtime. And we will also
|
||||
be able to reuse query structures, instead of allocating/freeing them every
|
||||
time. So the whole thing will look something like:
|
||||
|
||||
q = dns_alloc_query();
|
||||
dns_submit(dns_q_flags(dns_q_a4(q, name, cbck), DNS_F_NOSRCH), data);
|
||||
|
||||
The idea is to have a set of functions accepting struct dns_query* and
|
||||
returning it (so the calls can be "nested" like the above), to set up
|
||||
relevant parts of the query - specific type of callback, conversion from
|
||||
(type-specific) query parameters into a domain name (this is for type-
|
||||
specific query initializers), and setting various flags and options and
|
||||
type&class things.
|
||||
|
||||
One example where this is almost essential - if we want to support
|
||||
per-query set of nameservers (which isn't at all useless: imagine a
|
||||
high-volume mail server, were we want to direct DNSBL queries to a separate
|
||||
set of nameservers, and rDNS queries to their own set and so on). Adding
|
||||
another argument (set of nameservers to use) to EVERY query submitting
|
||||
routine is.. insane. Especially since in 99% cases it will be set to
|
||||
default NULL. But with such "nesting" of query initializers, it becomes
|
||||
trivial.
|
||||
@@ -1,74 +0,0 @@
|
||||
$Id: TODO,v 1.10 2005/04/19 21:48:09 mjt Exp $
|
||||
|
||||
The following is mostly an internal, not user-visible stuff.
|
||||
|
||||
* rearrange an API to make dns_query object owned by application,
|
||||
so that it'll look like this:
|
||||
struct dns_query *q;
|
||||
q = udns_query_alloc(ctx);
|
||||
udns_query_set(q, options, domain_name, flags, ...);
|
||||
udns_query_submit(ctx, q);
|
||||
or
|
||||
udns_query_resolve(ctx, q);
|
||||
|
||||
* allow NULL callbacks? Or provide separate resolver
|
||||
context list of queries which are done but wich did not
|
||||
have callback, and dns_pick() routine to retrieve results
|
||||
from this query, i.e. allow non-callback usage? The
|
||||
non-callback usage may be handy sometimes (any *good*
|
||||
example?), but it will be difficult to provide type-safe
|
||||
non-callback interface due to various RR-specific types
|
||||
in use.
|
||||
|
||||
* DNS_OPT_FLAGS should be DNS_OPT_ADDFLAGS and DNS_OPT_SETFLAGS.
|
||||
Currently one can't add a single flag bit but preserve
|
||||
existing bits... at least not without retrieving all current
|
||||
flags before, which isn't that bad anyway.
|
||||
|
||||
* dns_set_opts() may process flags too (such as aaonly etc)
|
||||
|
||||
* a way to disable $NSCACHEIP et al processing?
|
||||
|
||||
* initialize/open the context automatically, and be more
|
||||
liberal about initialization in general?
|
||||
|
||||
* dns_init(do_open) - make the parameter opposite, aka
|
||||
dns_init(skip_open) ?
|
||||
|
||||
* for the above. Use separate routine for initializing the context
|
||||
from system files, to not link stuff reading resolv.conf if it's
|
||||
not needed. So that automatic init will not be possible.
|
||||
|
||||
* allow TCP queue?
|
||||
|
||||
* detect servers which don't understand EDNS0 (returning FORMERR),
|
||||
and fall back to pre-EDNS0 for them.
|
||||
|
||||
* for the above to work, we have to be able to find query object by
|
||||
only ID, not ID + qdn.
|
||||
|
||||
* And oh, qID should really be random.
|
||||
|
||||
* more accurate error reporting. Currently, udns always returns TEMPFAIL,
|
||||
but don't specify why it happened (ENOMEM, timeout, etc).
|
||||
|
||||
* check the error value returned by recvfrom() and
|
||||
sendto() and determine which errors to ignore.
|
||||
|
||||
* maybe merge dns_timeouts() and dns_ioevent(), to have
|
||||
only one entry point for everything? For traditional
|
||||
select-loop-based eventloop it may be easier, but for
|
||||
callback-driven event loops the two should be separate.
|
||||
Provide an option, or a single dns_events() entry point
|
||||
for select-loop approach, or just call dns_ioevent()
|
||||
from within dns_timeouts() (probably after renaming
|
||||
it to be dns_events()) ?
|
||||
|
||||
* implement /etc/hosts lookup too, ala [c-]ares??
|
||||
|
||||
* sortlist support?
|
||||
|
||||
* windows port? Oh no please!.. At least, I can't do it myself
|
||||
because of the lack of platform.
|
||||
Ok ok, the Windows port is in progress. Christian Prahauser
|
||||
from cosy.sbg.ac.at is helping with that.
|
||||
@@ -1,94 +0,0 @@
|
||||
udns (0.0.9pre) unstable; urgency=low
|
||||
|
||||
* s/EOVERFLOW/ENFILE, partly to make win32 happy
|
||||
|
||||
* several win32 fixes
|
||||
|
||||
* don't use `class' in udns.h, to make C++ happy
|
||||
(thanks Markus Koetter for pointing this out)
|
||||
|
||||
* fixed CNAME handling in dnsget tool. Another Thank You! goes
|
||||
to Markus Koetter.
|
||||
|
||||
* NAPTR (RFC3403) support, thanks to Mikael Magnusson
|
||||
<mikma at users.sourceforge.net> for this.
|
||||
|
||||
* more Win32 fixes from Mikael Magnusson. I have to admit
|
||||
I never tried to compile it on Win32.
|
||||
|
||||
* added NOTES file
|
||||
|
||||
-- Michael Tokarev <mjt@corpit.ru> Wed, 29 Nov 2006 04:16:21 +0300
|
||||
|
||||
udns (0.0.8) unstable; urgency=low
|
||||
|
||||
* don't compare sockaddr_in's, but individual parts only
|
||||
(on some OSes, there are additional fields in this structure
|
||||
so memcmp() does not quite work)
|
||||
|
||||
* use dnsc_t instead of unsigned char for DNs everywhere
|
||||
|
||||
* SRV records (rfc2782) parsing, thanks to
|
||||
Thadeu Lima de Souza Cascardo.
|
||||
|
||||
* manpage fixes
|
||||
|
||||
-- Michael Tokarev <mjt@corpit.ru> Mon, 12 Sep 2005 16:06:45 +0400
|
||||
|
||||
udns (0.0.7) unstable; urgency=low
|
||||
|
||||
* added dnsget.1 and rblcheck.1 manpages.
|
||||
|
||||
* internal: use generic list implementation in udns_resolver.c
|
||||
|
||||
* don't assume only backward DN pointers in replies, allow forward
|
||||
pointers too. This is quite large change, involves changing
|
||||
parsing API all over the places.
|
||||
|
||||
* internal: typedef dnsc_t and dnscc_t for [const] unsigned char, to
|
||||
make function prototypes shorter to better fit on a single line.
|
||||
|
||||
* in parsing routines, verify (assert) that the query type
|
||||
is the one we can handle.
|
||||
|
||||
* recognize names (and resolve them) as nameservers in dnsget.
|
||||
|
||||
* when new request is submitted, don't send it immediately, but
|
||||
add it into the head of the active queue with deadline=0.
|
||||
This will allow us to tweak some query settings before it will
|
||||
be processed.
|
||||
Note API change: removed `now' argument from all dns_submit_*()
|
||||
routines.
|
||||
|
||||
* use single per-context user timer, not per-query.
|
||||
Note API change: different user timer callback
|
||||
|
||||
* add dnsc_salen field -- length of the socket address used
|
||||
|
||||
* fix dns_set_opt(DNS_OPT_FLAGS) which didn't work before
|
||||
|
||||
* allow to set some options for a context wich is open but with no
|
||||
active queries
|
||||
|
||||
-- Michael Tokarev <mjt@corpit.ru> Thu, 5 May 2005 23:14:29 +0400
|
||||
|
||||
udns (0.0.6) unstable; urgency=low
|
||||
|
||||
* 0.0.6 release.
|
||||
ALOT of changes all over. Keep 'em in CVS logs!
|
||||
|
||||
-- Michael Tokarev <mjt@corpit.ru> Fri, 8 Apr 2005 19:51:38 +0400
|
||||
|
||||
udns (0.0.5) unstable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
* Provides 3 packages:
|
||||
libudns0 - shared library
|
||||
libudns-dev - development files and static library
|
||||
udns-utils - dnsget, rblcheck
|
||||
|
||||
-- Michael Tokarev <mjt@corpit.ru> Thu, 7 Apr 2005 00:05:24 +0400
|
||||
|
||||
Local variables:
|
||||
mode: debian-changelog
|
||||
End:
|
||||
@@ -1,33 +0,0 @@
|
||||
Source: udns
|
||||
Priority: optional
|
||||
Maintainer: Michael Tokarev <mjt@corpit.ru>
|
||||
Build-Depends: debhelper (>= 4.0.0)
|
||||
Standards-Version: 3.6.1
|
||||
|
||||
Package: libudns0
|
||||
Section: lib
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Description: async-capable DNS stub resolver library
|
||||
libudns0 package provides libudns shared library needed
|
||||
to run programs using it
|
||||
|
||||
Package: libudns-dev
|
||||
Section: libdev
|
||||
Architecture: any
|
||||
Depends: libudns0 (= ${Source-Version})
|
||||
Description: async-capable DNS stub resolver library, development files
|
||||
This package provides development files needed
|
||||
to build programs using udns library
|
||||
|
||||
Package: udns-utils
|
||||
Section: net
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Conflicts: rblcheck
|
||||
Description: Several DNS-related utilities built on top of udns library
|
||||
This package includes the following utilities:
|
||||
dnsget - a simple DNS query tool, like `host' or `dig' for usage from
|
||||
a command line, and dnsip, dnsname etc for usage in scripts
|
||||
rblcheck - DNSBL (rbl) checker
|
||||
All the utilities are built using udns library
|
||||
@@ -1,24 +0,0 @@
|
||||
This is udns, written and maintained by Michael Tokarev <mjt@corpit.ru>
|
||||
|
||||
The original source can always be found at:
|
||||
http://www.corpit.ru/mjt/udns.html
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this package; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License can be found in `/usr/share/common-licenses/GPL'.
|
||||
@@ -1,91 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
# This file was originally written by Joey Hess and Craig Small.
|
||||
# As a special exception, when this file is copied by dh-make into a
|
||||
# dh-make output file, you may use that output file without restriction.
|
||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
export DH_COMPAT=4
|
||||
|
||||
CFLAGS = -Wall -W -Wmissing-prototypes -g
|
||||
CDEFS = -DHAVE_POOL
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_PROGRAM = $(INSTALL) -p
|
||||
INSTALL_DATA = $(INSTALL) -p -m0644
|
||||
|
||||
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
|
||||
CFLAGS += -O0
|
||||
else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
INSTALL_PROGRAM += -s
|
||||
endif
|
||||
ifeq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
|
||||
# CDEFS += -DNDEBUG
|
||||
endif
|
||||
|
||||
SOVER = 0
|
||||
|
||||
configure: # nothing
|
||||
dh_testdir
|
||||
|
||||
build: build-stamp
|
||||
build-stamp:
|
||||
dh_testdir
|
||||
$(MAKE) CFLAGS="$(CFLAGS)" CDEFS="$(CDEFS)" SOVER=$(SOVER) \
|
||||
staticlib sharedlib rblcheck.shared dnsget.shared
|
||||
mv -f rblcheck.shared rblcheck
|
||||
mv -f dnsget.shared dnsget
|
||||
touch $@
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
rm -f build-stamp
|
||||
$(MAKE) distclean
|
||||
dh_clean
|
||||
|
||||
install: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean
|
||||
dh_installdirs
|
||||
dh_installdocs -A NEWS
|
||||
|
||||
# libudns
|
||||
dh_install -plibudns$(SOVER) libudns.so.$(SOVER) usr/lib
|
||||
|
||||
# libudns-dev
|
||||
dh_install -plibudns-dev libudns.a libudns.so usr/lib
|
||||
dh_install -plibudns-dev udns.h usr/include
|
||||
dh_installman -plibudns-dev udns.3
|
||||
dh_installdocs -plibudns-dev TODO NOTES
|
||||
dh_installexamples -plibudns-dev ex-rdns.c
|
||||
|
||||
# udns-utils
|
||||
dh_installdirs -pudns-utils usr/bin
|
||||
dh_install -pudns-utils dnsget rblcheck usr/bin
|
||||
dh_installman -pudns-utils dnsget.1 rblcheck.1
|
||||
|
||||
binary-indep: build install
|
||||
|
||||
binary-arch: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installchangelogs
|
||||
dh_installdocs
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
dh_makeshlibs
|
||||
dh_installdeb
|
||||
dh_shlibdeps -L libudns$(SOVER) -l debian/libudns$(SOVER)/usr/lib
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install configure
|
||||
@@ -1,182 +0,0 @@
|
||||
.\" $Id: dnsget.1,v 1.3 2005/04/20 00:55:34 mjt Exp $
|
||||
.\" dnsget manpage
|
||||
.\"
|
||||
.\" Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
.\" This file is part of UDNS library, an async DNS stub resolver.
|
||||
.\"
|
||||
.\" This library is free software; you can redistribute it and/or
|
||||
.\" modify it under the terms of the GNU Lesser General Public
|
||||
.\" License as published by the Free Software Foundation; either
|
||||
.\" version 2.1 of the License, or (at your option) any later version.
|
||||
.\"
|
||||
.\" This library is distributed in the hope that it will be useful,
|
||||
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
.\" Lesser General Public License for more details.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU Lesser General Public
|
||||
.\" License along with this library, in file named COPYING.LGPL; if not,
|
||||
.\" write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
.\" Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
.TH dnsget 1 "Apr 2005" "User Utilities"
|
||||
|
||||
.SH NAME
|
||||
dnsget \- DNS lookup utility
|
||||
|
||||
.SH SYNOPSYS
|
||||
.B dnsget
|
||||
.RB [\| \-v \||\| \-q \|]
|
||||
.RB [\| \-c
|
||||
.IR class \|]
|
||||
.RB [\| \-t
|
||||
.IR type \|]
|
||||
.RB [\| \-o
|
||||
.IR option : value \]
|
||||
.IR name \|.\|.\|.
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B dnsget
|
||||
is a simple command-line to perform DNS lookups, similar to
|
||||
.BR host (1)
|
||||
and
|
||||
.BR dig (1).
|
||||
It is useable for both interactive/debugging scenarious and
|
||||
in scripts.
|
||||
The program is implemented using
|
||||
.BR udns (3)
|
||||
library.
|
||||
|
||||
.PP
|
||||
By default,
|
||||
.B dnsget
|
||||
produces a human-readable output, similar to
|
||||
.RS
|
||||
.nf
|
||||
alias.example.com. CNAME www.example.com.
|
||||
www.example.com. A 192.168.1.1
|
||||
www.example.com. MX 10 mx.example.com.
|
||||
.fi
|
||||
.RE
|
||||
which is just sufficient to see how a given name resolves.
|
||||
Output format is controllable with
|
||||
.B \-v
|
||||
and
|
||||
.B \-q
|
||||
options -- the former increases verbosity level up to printing
|
||||
the whole DNS contents of all packets sent and received, which
|
||||
is suitable for debugging DNS problems, while the latter reduces
|
||||
the level, making output more quiet, up to bare result with no
|
||||
error messages, which is good for scripts.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
The following options are recognized by
|
||||
.BR dnsget :
|
||||
|
||||
.TP
|
||||
.B \-v
|
||||
produce more detailed output. More
|
||||
.BR \-v 's
|
||||
means more details will be produced. With single
|
||||
.BR \-v , dnsget
|
||||
will print contents of all received DNS packets (in a readable format),
|
||||
while with
|
||||
.BR \-vv ,
|
||||
it will output all outgoing DNS packets too.
|
||||
|
||||
.TP
|
||||
.B \-q
|
||||
the opposite for \fB\-v\fR -- produce less detailed output.
|
||||
With single
|
||||
.BR \-q , dnsget
|
||||
will only show (decoded) data from final DNS resource records (RR),
|
||||
while
|
||||
.B \-qq
|
||||
also suppresses error messages.
|
||||
|
||||
.TP
|
||||
\fB\-t \fItype\fR
|
||||
request record(s) of the given type \fItype\fR. By default,
|
||||
.B dnsget
|
||||
will ask for IPv4 address (A) record, or for PTR record if the
|
||||
argument in question is an IPv4 or IPv6 address. Recognized
|
||||
types include A, AAAA, MX, TXT, CNAME, PTR, NS, SOA, ANY and
|
||||
others.
|
||||
|
||||
.TP
|
||||
\fB\-c \fIclass\fR
|
||||
request DNS record(s) of the given class \fIclass\fR. By
|
||||
default
|
||||
.B dnsget
|
||||
uses IN class. Valid classes include IN, CH, HS, ANY.
|
||||
|
||||
.TP
|
||||
.B \-a
|
||||
(compatibility option). Equivalent to setting query type to
|
||||
.B ANY
|
||||
and increasing verbosity level
|
||||
.RB ( \-v ).
|
||||
|
||||
.TP
|
||||
.B \-C
|
||||
(planned)
|
||||
|
||||
.TP
|
||||
.B \-x
|
||||
(planned)
|
||||
|
||||
.TP
|
||||
\fB\-o \fIoption\fR:\fIvalue\fR
|
||||
Set resolver option \fIoption\fR to the value \fIvalue\fR
|
||||
(may be specified several times). The same as setting
|
||||
.RB $ RES_OPTIONS
|
||||
environment variable. The following options are recognized:
|
||||
.RS
|
||||
.TP
|
||||
\fBtimeout\fR:\fIsec\fR
|
||||
Set initial query timeout to \fIsec\fR.
|
||||
.TP
|
||||
\fBattempts\fR:\fInum\fR
|
||||
(re)try every query \fInum\fR times before failing.
|
||||
.TP
|
||||
\fBudpbuf\fR:\fIbytes\fR
|
||||
set DNS UDP buffer size to \fIbytes\fR bytes. Valid values
|
||||
are from 512 to 65535. If \fIbytes\fR is greather than 512,
|
||||
EDNS0 (RFC 2671) extensions will be used.
|
||||
.TP
|
||||
\fBport\fR:\fInum\fR
|
||||
Use given UDP port number \fInum\fR instead of the default port 53 (domain).
|
||||
.RE
|
||||
|
||||
.TP
|
||||
\fB\-n \fInameserver\fR
|
||||
Use the given nameserver(s) (may be specified more than once)
|
||||
instead of the default. Using this option has the same same effect as
|
||||
.RB $ NSCACHEIP
|
||||
or
|
||||
.RB $ NAMESERVERS
|
||||
environment variables, with the only difference that only IPv4 addresses
|
||||
are recognized for now, and it is possible to specify names (which will
|
||||
be resolved using default settings) instead of IP addresses.
|
||||
|
||||
.TP
|
||||
.B \-h
|
||||
print short help and exit.
|
||||
|
||||
.SH "RETURN VALUE"
|
||||
When all names where resovled successefully,
|
||||
.B dnsget
|
||||
exits with zero exit status. If at least one name was not found,
|
||||
.B dnsget
|
||||
will exit with return code 100. If some other error occured during
|
||||
name resolution, it will exit with code 99. In case of usage or
|
||||
initialization error,
|
||||
.B dnsget
|
||||
will return 1.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR host (1)
|
||||
.BR dig (1)
|
||||
.BR resolv.conf (5)
|
||||
.BR udns (3).
|
||||
@@ -1,709 +0,0 @@
|
||||
/* $Id: dnsget.c,v 1.22 2006/11/29 21:28:49 mjt Exp $
|
||||
simple host/dig-like application using UDNS library
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include "udns.h"
|
||||
|
||||
static char *progname;
|
||||
static int verbose = 1;
|
||||
static int errors;
|
||||
static int notfound;
|
||||
|
||||
/* verbosity level:
|
||||
* <0 - bare result
|
||||
* 0 - bare result and error messages
|
||||
* 1 - readable result
|
||||
* 2 - received packet contents and `trying ...' stuff
|
||||
* 3 - sent and received packet contents
|
||||
*/
|
||||
|
||||
static void die(int errnum, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap);
|
||||
if (errnum) fprintf(stderr, ": %s\n", strerror(errnum));
|
||||
else putc('\n', stderr);
|
||||
fflush(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct query {
|
||||
const char *name; /* original query string */
|
||||
unsigned char *dn; /* the DN being looked up */
|
||||
enum dns_type qtyp; /* type of the query */
|
||||
};
|
||||
|
||||
static void query_free(struct query *q) {
|
||||
free(q->dn);
|
||||
free(q);
|
||||
}
|
||||
|
||||
static struct query *
|
||||
query_new(const char *name, const unsigned char *dn, enum dns_type qtyp) {
|
||||
struct query *q = malloc(sizeof(*q));
|
||||
unsigned l = dns_dnlen(dn);
|
||||
unsigned char *cdn = malloc(l);
|
||||
if (!q || !cdn) die(0, "out of memory");
|
||||
memcpy(cdn, dn, l);
|
||||
q->name = name;
|
||||
q->dn = cdn;
|
||||
q->qtyp = qtyp;
|
||||
return q;
|
||||
}
|
||||
|
||||
static enum dns_class qcls = DNS_C_IN;
|
||||
|
||||
static void
|
||||
dnserror(struct query *q, int errnum) {
|
||||
if (verbose >= 0)
|
||||
fprintf(stderr, "%s: unable to lookup %s record for %s: %s\n", progname,
|
||||
dns_typename(q->qtyp), dns_dntosp(q->dn), dns_strerror(errnum));
|
||||
if (errnum == DNS_E_NXDOMAIN || errnum == DNS_E_NODATA)
|
||||
++notfound;
|
||||
else
|
||||
++errors;
|
||||
query_free(q);
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
printtxt(const unsigned char *c) {
|
||||
unsigned n = *c++;
|
||||
const unsigned char *e = c + n;
|
||||
if (verbose > 0) while(c < e) {
|
||||
if (*c < ' ' || *c >= 127) printf("\\%02x", *c);
|
||||
else if (*c == '\\' || *c == '"') printf("\\%c", *c);
|
||||
else putchar(*c);
|
||||
++c;
|
||||
}
|
||||
else
|
||||
fwrite(c, n, 1, stdout);
|
||||
return e;
|
||||
}
|
||||
|
||||
static void
|
||||
printhex(const unsigned char *c, const unsigned char *e) {
|
||||
while(c < e)
|
||||
printf("%02x", *c++);
|
||||
}
|
||||
|
||||
static unsigned char to_b64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static void
|
||||
printb64(const unsigned char *c, const unsigned char *e) {
|
||||
while(c < e) {
|
||||
putchar(to_b64[c[0] >> 2]);
|
||||
if (c+1 < e) {
|
||||
putchar(to_b64[(c[0] & 0x3) << 4 | c[1] >> 4]);
|
||||
if (c+2 < e) {
|
||||
putchar(to_b64[(c[1] & 0xf) << 2 | c[2] >> 6]);
|
||||
putchar(to_b64[c[2] & 0x3f]);
|
||||
}
|
||||
else {
|
||||
putchar(to_b64[(c[1] & 0xf) << 2]);
|
||||
putchar('=');
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
putchar(to_b64[(c[0] & 0x3) << 4]);
|
||||
putchar('=');
|
||||
putchar('=');
|
||||
break;
|
||||
}
|
||||
c += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
printdate(time_t time) {
|
||||
struct tm *tm = gmtime(&time);
|
||||
printf("%04d%02d%02d%02d%02d%02d",
|
||||
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
}
|
||||
|
||||
static void
|
||||
printrr(const struct dns_parse *p, struct dns_rr *rr) {
|
||||
const unsigned char *pkt = p->dnsp_pkt;
|
||||
const unsigned char *end = p->dnsp_end;
|
||||
const unsigned char *dptr = rr->dnsrr_dptr;
|
||||
const unsigned char *dend = rr->dnsrr_dend;
|
||||
unsigned char *dn = rr->dnsrr_dn;
|
||||
const unsigned char *c;
|
||||
unsigned n;
|
||||
|
||||
if (verbose > 0) {
|
||||
if (verbose > 1) {
|
||||
if (!p->dnsp_rrl && !rr->dnsrr_dn[0] && rr->dnsrr_typ == DNS_T_OPT) {
|
||||
printf(";EDNS0 OPT record (UDPsize: %d): %d bytes\n",
|
||||
rr->dnsrr_cls, rr->dnsrr_dsz);
|
||||
return;
|
||||
}
|
||||
n = printf("%s.", dns_dntosp(rr->dnsrr_dn));
|
||||
printf("%s%u\t%s\t%s\t",
|
||||
n > 15 ? "\t" : n > 7 ? "\t\t" : "\t\t\t",
|
||||
rr->dnsrr_ttl,
|
||||
dns_classname(rr->dnsrr_cls),
|
||||
dns_typename(rr->dnsrr_typ));
|
||||
}
|
||||
else
|
||||
printf("%s. %s ", dns_dntosp(rr->dnsrr_dn), dns_typename(rr->dnsrr_typ));
|
||||
}
|
||||
|
||||
switch(rr->dnsrr_typ) {
|
||||
|
||||
case DNS_T_CNAME:
|
||||
case DNS_T_PTR:
|
||||
case DNS_T_NS:
|
||||
case DNS_T_MB:
|
||||
case DNS_T_MD:
|
||||
case DNS_T_MF:
|
||||
case DNS_T_MG:
|
||||
case DNS_T_MR:
|
||||
if (dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN) <= 0) goto xperr;
|
||||
printf("%s.", dns_dntosp(dn));
|
||||
break;
|
||||
|
||||
case DNS_T_A:
|
||||
if (rr->dnsrr_dsz != 4) goto xperr;
|
||||
printf("%d.%d.%d.%d", dptr[0], dptr[1], dptr[2], dptr[3]);
|
||||
break;
|
||||
|
||||
case DNS_T_AAAA:
|
||||
if (rr->dnsrr_dsz != 16) goto xperr;
|
||||
printf("%s", inet_ntop(AF_INET6, dptr, (char*)dn, DNS_MAXDN));
|
||||
break;
|
||||
|
||||
case DNS_T_MX:
|
||||
c = dptr + 2;
|
||||
if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr;
|
||||
printf("%d %s.", dns_get16(dptr), dns_dntosp(dn));
|
||||
break;
|
||||
|
||||
case DNS_T_TXT:
|
||||
/* first verify it */
|
||||
for(c = dptr; c < dend; c += n) {
|
||||
n = *c++;
|
||||
if (c + n > dend) goto xperr;
|
||||
}
|
||||
c = dptr; n = 0;
|
||||
while (c < dend) {
|
||||
if (verbose > 0) printf(n++ ? "\" \"":"\"");
|
||||
c = printtxt(c);
|
||||
}
|
||||
if (verbose > 0) putchar('"');
|
||||
break;
|
||||
|
||||
case DNS_T_HINFO: /* CPU, OS */
|
||||
c = dptr;
|
||||
n = *c++; if ((c += n) >= dend) goto xperr;
|
||||
n = *c++; if ((c += n) != dend) goto xperr;
|
||||
c = dptr;
|
||||
if (verbose > 0) putchar('"');
|
||||
c = printtxt(c);
|
||||
if (verbose > 0) printf("\" \""); else putchar(' ');
|
||||
printtxt(c);
|
||||
if (verbose > 0) putchar('"');
|
||||
break;
|
||||
|
||||
case DNS_T_WKS:
|
||||
c = dptr;
|
||||
if (dptr + 4 + 2 >= end) goto xperr;
|
||||
printf("%s %d", inet_ntoa(*((struct in_addr*)dptr)), dptr[4]);
|
||||
c = dptr + 5;
|
||||
for (n = 0; c < dend; ++c, n += 8) {
|
||||
if (*c) {
|
||||
unsigned b;
|
||||
for (b = 0; b < 8; ++b)
|
||||
if (*c & (1 << (7-b))) printf(" %d", n + b);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DNS_T_SRV: /* prio weight port targetDN */
|
||||
c = dptr;
|
||||
c += 2 + 2 + 2;
|
||||
if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr;
|
||||
c = dptr;
|
||||
printf("%d %d %d %s.",
|
||||
dns_get16(c+0), dns_get16(c+2), dns_get16(c+4),
|
||||
dns_dntosp(dn));
|
||||
break;
|
||||
|
||||
case DNS_T_NAPTR: /* order pref flags serv regexp repl */
|
||||
c = dptr;
|
||||
c += 4; /* order, pref */
|
||||
for (n = 0; n < 3; ++n)
|
||||
if (c >= dend) goto xperr;
|
||||
else c += *c + 1;
|
||||
if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) goto xperr;
|
||||
c = dptr;
|
||||
printf("%u %u", dns_get16(c+0), dns_get16(c+2));
|
||||
c += 4;
|
||||
for(n = 0; n < 3; ++n) {
|
||||
putchar(' ');
|
||||
if (verbose > 0) putchar('"');
|
||||
c = printtxt(c);
|
||||
if (verbose > 0) putchar('"');
|
||||
}
|
||||
printf(" %s.", dns_dntosp(dn));
|
||||
break;
|
||||
|
||||
case DNS_T_KEY: /* flags(2) proto(1) algo(1) pubkey */
|
||||
c = dptr;
|
||||
if (c + 2 + 1 + 1 > dend) goto xperr;
|
||||
printf("%d %d %d", dns_get16(c), c[2], c[3]);
|
||||
c += 2 + 1 + 1;
|
||||
if (c < dend) {
|
||||
putchar(' ');
|
||||
printb64(c, dend);
|
||||
}
|
||||
break;
|
||||
|
||||
case DNS_T_SIG:
|
||||
/* type(2) algo(1) labels(1) ottl(4) sexp(4) sinc(4) tag(2) sdn sig */
|
||||
c = dptr;
|
||||
c += 2 + 1 + 1 + 4 + 4 + 4 + 2;
|
||||
if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0) goto xperr;
|
||||
printf("%d %u %u %u ",
|
||||
dns_get16(dptr), dptr[2], dptr[3], dns_get32(dptr+4));
|
||||
printdate(dns_get32(dptr+8));
|
||||
putchar(' ');
|
||||
printdate(dns_get32(dptr+12));
|
||||
printf(" %d %s. ", dns_get16(dptr+10), dns_dntosp(dn));
|
||||
printb64(c, dend);
|
||||
break;
|
||||
|
||||
#if 0 /* unused RR types? */
|
||||
case DNS_T_DS:
|
||||
c = dptr;
|
||||
if (c + 2 + 2 >= dend) goto xperr;
|
||||
printf("%u %u %u ", dns_get16(c), c[2], c[3]);
|
||||
printhex(c + 4, dend);
|
||||
break;
|
||||
|
||||
case DNS_T_NSEC:
|
||||
c = dptr;
|
||||
if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0) goto xperr;
|
||||
printf("%s.", dns_dntosp(dn));
|
||||
unfinished.
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
case DNS_T_SOA:
|
||||
c = dptr;
|
||||
if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 ||
|
||||
dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 ||
|
||||
c + 4*5 != dend)
|
||||
goto xperr;
|
||||
dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN);
|
||||
printf("%s. ", dns_dntosp(dn));
|
||||
dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN);
|
||||
printf("%s. ", dns_dntosp(dn));
|
||||
printf("%u %u %u %u %u",
|
||||
dns_get32(dptr), dns_get32(dptr+4), dns_get32(dptr+8),
|
||||
dns_get32(dptr+12), dns_get32(dptr+16));
|
||||
break;
|
||||
|
||||
case DNS_T_MINFO:
|
||||
c = dptr;
|
||||
if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 ||
|
||||
dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 ||
|
||||
c != dend)
|
||||
goto xperr;
|
||||
dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN);
|
||||
printf("%s. ", dns_dntosp(dn));
|
||||
dns_getdn(pkt, &dptr, end, dn, DNS_MAXDN);
|
||||
printf("%s.", dns_dntosp(dn));
|
||||
break;
|
||||
|
||||
case DNS_T_NULL:
|
||||
default:
|
||||
printhex(dptr, dend);
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
return;
|
||||
|
||||
xperr:
|
||||
printf("<parse error>\n");
|
||||
++errors;
|
||||
}
|
||||
|
||||
static int
|
||||
printsection(struct dns_parse *p, int nrr, const char *sname) {
|
||||
struct dns_rr rr;
|
||||
int r;
|
||||
if (!nrr) return 0;
|
||||
if (verbose > 1) printf("\n;; %s section (%d):\n", sname, nrr);
|
||||
|
||||
p->dnsp_rrl = nrr;
|
||||
while((r = dns_nextrr(p, &rr)) > 0)
|
||||
printrr(p, &rr);
|
||||
if (r < 0) printf("<<ERROR>>\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* dbgcb will only be called if verbose > 1 */
|
||||
static void
|
||||
dbgcb(int code, const struct sockaddr *sa, unsigned slen,
|
||||
const unsigned char *pkt, int r,
|
||||
const struct dns_query *unused_q, void *unused_data) {
|
||||
struct dns_parse p;
|
||||
const unsigned char *cur, *end;
|
||||
int numqd;
|
||||
|
||||
if (code > 0) {
|
||||
printf(";; trying %s.\n", dns_dntosp(dns_payload(pkt)));
|
||||
printf(";; sending %d bytes query to ", r);
|
||||
}
|
||||
else
|
||||
printf(";; received %d bytes response from ", r);
|
||||
if (sa->sa_family == AF_INET && slen >= sizeof(struct sockaddr_in)) {
|
||||
char buf[4*4];
|
||||
printf("%s port %d\n",
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr,
|
||||
buf, sizeof(buf)),
|
||||
htons(((struct sockaddr_in*)sa)->sin_port));
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
else if (sa->sa_family == AF_INET6 && slen >= sizeof(struct sockaddr_in6)) {
|
||||
char buf[6*5+4*4];
|
||||
printf("%s port %d\n",
|
||||
inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr,
|
||||
buf, sizeof(buf)),
|
||||
htons(((struct sockaddr_in6*)sa)->sin6_port));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
printf("<<unknown socket type %d>>\n", sa->sa_family);
|
||||
if (code > 0 && verbose < 3) {
|
||||
putchar('\n');
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == -2) printf(";; reply from unexpected source\n");
|
||||
if (code == -5) printf(";; reply to a query we didn't sent (or old)\n");
|
||||
if (r < DNS_HSIZE) {
|
||||
printf(";; short packet (%d bytes)\n", r);
|
||||
return;
|
||||
}
|
||||
if (dns_opcode(pkt) != 0)
|
||||
printf(";; unexpected opcode %d\n", dns_opcode(pkt));
|
||||
if (dns_tc(pkt) != 0)
|
||||
printf(";; warning: TC bit set, probably incomplete reply\n");
|
||||
|
||||
printf(";; ->>HEADER<<- opcode: ");
|
||||
switch(dns_opcode(pkt)) {
|
||||
case 0: printf("QUERY"); break;
|
||||
case 1: printf("IQUERY"); break;
|
||||
case 2: printf("STATUS"); break;
|
||||
default: printf("UNKNOWN(%u)", dns_opcode(pkt)); break;
|
||||
}
|
||||
printf(", status: %s, id: %d, size: %d\n;; flags:",
|
||||
dns_rcodename(dns_rcode(pkt)), dns_qid(pkt), r);
|
||||
if (dns_qr(pkt)) printf(" qr");
|
||||
if (dns_rd(pkt)) printf(" rd");
|
||||
if (dns_ra(pkt)) printf(" ra");
|
||||
if (dns_aa(pkt)) printf(" aa");
|
||||
if (dns_tc(pkt)) printf(" tc");
|
||||
numqd = dns_numqd(pkt);
|
||||
printf("; QUERY: %d, ANSWER: %d, AUTHORITY: %d, ADDITIONAL: %d\n",
|
||||
numqd, dns_numan(pkt), dns_numns(pkt), dns_numar(pkt));
|
||||
if (numqd != 1)
|
||||
printf(";; unexpected number of entries in QUERY section: %d\n",
|
||||
numqd);
|
||||
printf("\n;; QUERY SECTION (%d):\n", numqd);
|
||||
cur = dns_payload(pkt);
|
||||
end = pkt + r;
|
||||
while(numqd--) {
|
||||
if (dns_getdn(pkt, &cur, end, p.dnsp_dnbuf, DNS_MAXDN) <= 0 ||
|
||||
cur + 4 > end) {
|
||||
printf("; invalid query section\n");
|
||||
return;
|
||||
}
|
||||
r = printf(";%s.", dns_dntosp(p.dnsp_dnbuf));
|
||||
printf("%s%s\t%s\n",
|
||||
r > 23 ? "\t" : r > 15 ? "\t\t" : r > 7 ? "\t\t\t" : "\t\t\t\t",
|
||||
dns_classname(dns_get16(cur+2)), dns_typename(dns_get16(cur)));
|
||||
cur += 4;
|
||||
}
|
||||
|
||||
p.dnsp_pkt = pkt;
|
||||
p.dnsp_cur = p.dnsp_ans = cur;
|
||||
p.dnsp_end = end;
|
||||
p.dnsp_qdn = NULL;
|
||||
p.dnsp_qcls = p.dnsp_qtyp = 0;
|
||||
p.dnsp_ttl = 0xffffffffu;
|
||||
p.dnsp_nrr = 0;
|
||||
|
||||
r = printsection(&p, dns_numan(pkt), "ANSWER");
|
||||
if (r == 0)
|
||||
r = printsection(&p, dns_numns(pkt), "AUTHORITY");
|
||||
if (r == 0)
|
||||
r = printsection(&p, dns_numar(pkt), "ADDITIONAL");
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void dnscb(struct dns_ctx *ctx, void *result, void *data) {
|
||||
int r = dns_status(ctx);
|
||||
struct query *q = data;
|
||||
struct dns_parse p;
|
||||
struct dns_rr rr;
|
||||
unsigned nrr;
|
||||
unsigned char dn[DNS_MAXDN];
|
||||
const unsigned char *pkt, *cur, *end;
|
||||
if (!result) {
|
||||
dnserror(q, r);
|
||||
return;
|
||||
}
|
||||
pkt = result; end = pkt + r; cur = dns_payload(pkt);
|
||||
dns_getdn(pkt, &cur, end, dn, sizeof(dn));
|
||||
dns_initparse(&p, NULL, pkt, cur, end);
|
||||
p.dnsp_qcls = p.dnsp_qtyp = 0;
|
||||
nrr = 0;
|
||||
while((r = dns_nextrr(&p, &rr)) > 0) {
|
||||
if (!dns_dnequal(dn, rr.dnsrr_dn)) continue;
|
||||
if ((qcls == DNS_C_ANY || qcls == rr.dnsrr_cls) &&
|
||||
(q->qtyp == DNS_T_ANY || q->qtyp == rr.dnsrr_typ))
|
||||
++nrr;
|
||||
else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
|
||||
if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
|
||||
p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
|
||||
rr.dnsrr_dptr != rr.dnsrr_dend) {
|
||||
r = DNS_E_PROTOCOL;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (verbose == 1) {
|
||||
printf("%s.", dns_dntosp(dn));
|
||||
printf(" CNAME %s.\n", dns_dntosp(p.dnsp_dnbuf));
|
||||
}
|
||||
dns_dntodn(p.dnsp_dnbuf, dn, sizeof(dn));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!r && !nrr)
|
||||
r = DNS_E_NODATA;
|
||||
if (r < 0) {
|
||||
dnserror(q, r);
|
||||
free(result);
|
||||
return;
|
||||
}
|
||||
if (verbose < 2) { /* else it is already printed by dbgfn */
|
||||
dns_rewind(&p, NULL);
|
||||
p.dnsp_qtyp = q->qtyp;
|
||||
p.dnsp_qcls = qcls;
|
||||
while(dns_nextrr(&p, &rr))
|
||||
printrr(&p, &rr);
|
||||
}
|
||||
free(result);
|
||||
query_free(q);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
int fd;
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
time_t now;
|
||||
char *ns[DNS_MAXSERV];
|
||||
int nns = 0;
|
||||
struct query *q;
|
||||
enum dns_type qtyp = 0;
|
||||
struct dns_ctx *nctx = NULL;
|
||||
|
||||
if (!(progname = strrchr(argv[0], '/'))) progname = argv[0];
|
||||
else argv[0] = ++progname;
|
||||
|
||||
if (argc <= 1)
|
||||
die(0, "try `%s -h' for help", progname);
|
||||
|
||||
if (dns_init(0) < 0 || !(nctx = dns_new(NULL)))
|
||||
die(errno, "unable to initialize dns library");
|
||||
/* we keep two dns contexts: one may be needed to resolve
|
||||
* nameservers if given as names, using default options.
|
||||
*/
|
||||
|
||||
while((i = getopt(argc, argv, "vqt:c:an:o:h")) != EOF) switch(i) {
|
||||
case 'v': ++verbose; break;
|
||||
case 'q': --verbose; break;
|
||||
case 't':
|
||||
if (optarg[0] == '*' && !optarg[1])
|
||||
i = DNS_T_ANY;
|
||||
else if ((i = dns_findtypename(optarg)) <= 0)
|
||||
die(0, "unrecognized query type `%s'", optarg);
|
||||
qtyp = i;
|
||||
break;
|
||||
case 'c':
|
||||
if (optarg[0] == '*' && !optarg[1])
|
||||
i = DNS_C_ANY;
|
||||
else if ((i = dns_findclassname(optarg)) < 0)
|
||||
die(0, "unrecognized query class `%s'", optarg);
|
||||
qcls = i;
|
||||
break;
|
||||
case 'a':
|
||||
qtyp = DNS_T_ANY;
|
||||
++verbose;
|
||||
break;
|
||||
case 'n':
|
||||
if (nns >= DNS_MAXSERV)
|
||||
die(0, "too many nameservers, %d max", DNS_MAXSERV);
|
||||
ns[nns++] = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
if (dns_set_opts(NULL, optarg) != 0)
|
||||
die(0, "invalid option string: `%s'", optarg);
|
||||
break;
|
||||
case 'h':
|
||||
printf(
|
||||
"%s: simple DNS query tool (using udns version %s)\n"
|
||||
"Usage: %s [options] domain-name...\n"
|
||||
"where options are:\n"
|
||||
" -h - print this help and exit\n"
|
||||
" -v - be more verbose\n"
|
||||
" -q - be less verbose\n"
|
||||
" -t type - set query type (A, AA, PTR etc)\n"
|
||||
" -c class - set query class (IN (default), CH, HS, *)\n"
|
||||
" -a - equivalent to -t ANY -v\n"
|
||||
" -n ns - use given nameserver(s) instead of default\n"
|
||||
" (may be specified multiple times)\n"
|
||||
" -o option:value - set resovler option (the same as setting $RES_OPTIONS):\n"
|
||||
" timeout:sec - initial query timeout\n"
|
||||
" attempts:num - number of attempt to resovle a query\n"
|
||||
" ndots:num - if name has more than num dots, lookup it before search\n"
|
||||
" port:num - port number for queries instead of default 53\n"
|
||||
" udpbuf:num - size of UDP buffer (use EDNS0 if >512)\n"
|
||||
" (may be specified more than once)\n"
|
||||
, progname, dns_version(), progname);
|
||||
return 0;
|
||||
default:
|
||||
die(0, "try `%s -h' for help", progname);
|
||||
}
|
||||
|
||||
argc -= optind; argv += optind;
|
||||
if (!argc)
|
||||
die(0, "no name(s) to query specified");
|
||||
|
||||
if (nns) {
|
||||
/* if nameservers given as names, resolve them.
|
||||
* We only allow IPv4 nameservers as names for now.
|
||||
* Ok, it is easy enouth to try both AAAA and A,
|
||||
* but the question is what to do by default.
|
||||
*/
|
||||
struct sockaddr_in sin;
|
||||
int j, r = 0, opened = 0;
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(dns_set_opt(NULL, DNS_OPT_PORT, -1));
|
||||
dns_add_serv(NULL, NULL);
|
||||
for(i = 0; i < nns; ++i) {
|
||||
if (!inet_aton(ns[i], &sin.sin_addr)) {
|
||||
struct dns_rr_a4 *rr;
|
||||
if (!opened) {
|
||||
if (dns_open(nctx) < 0)
|
||||
die(errno, "unable to initialize dns context");
|
||||
opened = 1;
|
||||
}
|
||||
rr = dns_resolve_a4(nctx, ns[i], 0);
|
||||
if (!rr)
|
||||
die(0, "unable to resolve nameserver %s: %s",
|
||||
ns[i], dns_strerror(dns_status(nctx)));
|
||||
for(j = 0; j < rr->dnsa4_nrr; ++j) {
|
||||
sin.sin_addr = rr->dnsa4_addr[j];
|
||||
if ((r = dns_add_serv_s(NULL, (struct sockaddr *)&sin)) < 0)
|
||||
break;
|
||||
}
|
||||
free(rr);
|
||||
}
|
||||
else
|
||||
r = dns_add_serv_s(NULL, (struct sockaddr *)&sin);
|
||||
if (r < 0)
|
||||
die(errno, "unable to add nameserver %s", inet_ntoa(sin.sin_addr));
|
||||
}
|
||||
}
|
||||
dns_free(nctx);
|
||||
|
||||
fd = dns_open(NULL);
|
||||
if (fd < 0)
|
||||
die(errno, "unable to initialize dns context");
|
||||
|
||||
if (verbose > 1)
|
||||
dns_set_dbgfn(NULL, dbgcb);
|
||||
|
||||
for (i = 0; i < argc; ++i) {
|
||||
char *name = argv[i];
|
||||
union {
|
||||
struct in_addr addr;
|
||||
struct in6_addr addr6;
|
||||
} a;
|
||||
unsigned char dn[DNS_MAXDN];
|
||||
enum dns_type l_qtyp = 0;
|
||||
int abs;
|
||||
if (inet_pton(AF_INET, name, &a.addr) > 0) {
|
||||
dns_a4todn(&a.addr, 0, dn, sizeof(dn));
|
||||
l_qtyp = DNS_T_PTR;
|
||||
abs = 1;
|
||||
}
|
||||
else if (inet_pton(AF_INET6, name, &a.addr6) > 0) {
|
||||
dns_a6todn(&a.addr6, 0, dn, sizeof(dn));
|
||||
l_qtyp = DNS_T_PTR;
|
||||
abs = 1;
|
||||
}
|
||||
else if (!dns_ptodn(name, strlen(name), dn, sizeof(dn), &abs))
|
||||
die(0, "invalid name `%s'\n", name);
|
||||
else
|
||||
l_qtyp = DNS_T_A;
|
||||
if (qtyp) l_qtyp = qtyp;
|
||||
q = query_new(name, dn, l_qtyp);
|
||||
if (abs) abs = DNS_NOSRCH;
|
||||
if (!dns_submit_dn(NULL, dn, qcls, l_qtyp, abs, 0, dnscb, q))
|
||||
dnserror(q, dns_status(NULL));
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
now = 0;
|
||||
while((i = dns_timeouts(NULL, -1, now)) > 0) {
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = i;
|
||||
tv.tv_usec = 0;
|
||||
i = select(fd+1, &fds, 0, 0, &tv);
|
||||
now = time(NULL);
|
||||
if (i > 0) dns_ioevent(NULL, now);
|
||||
}
|
||||
|
||||
return errors ? 1 : notfound ? 100 : 0;
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/* $Id: ex-rdns.c,v 1.6 2005/05/07 12:21:42 mjt Exp $
|
||||
parallel rDNS resolver example - read IP addresses from stdin,
|
||||
write domain names to stdout
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/poll.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "udns.h"
|
||||
|
||||
static int curq;
|
||||
|
||||
static const char *n2ip(const unsigned char *c) {
|
||||
static char b[sizeof("255.255.255.255")];
|
||||
sprintf(b, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]);
|
||||
return b;
|
||||
}
|
||||
static void dnscb(struct dns_ctx *ctx, struct dns_rr_ptr *rr, void *data) {
|
||||
const char *ip = n2ip((unsigned char *)&data);
|
||||
int i;
|
||||
--curq;
|
||||
if (rr) {
|
||||
printf("%s", ip);
|
||||
for(i = 0; i < rr->dnsptr_nrr; ++i)
|
||||
printf(" %s", rr->dnsptr_ptr[i]);
|
||||
putchar('\n');
|
||||
free(rr);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s: %s\n", ip, dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int c, t;
|
||||
time_t now;
|
||||
int maxq = 10;
|
||||
struct pollfd pfd;
|
||||
char linebuf[1024];
|
||||
char *eol;
|
||||
int eof;
|
||||
|
||||
if (dns_init(1) < 0) return 1;
|
||||
while((c = getopt(argc, argv, "m:r")) != EOF) switch(c) {
|
||||
case 'm': maxq = atoi(optarg); break;
|
||||
case 'r':
|
||||
dns_set_opt(0, DNS_OPT_FLAGS,
|
||||
dns_set_opt(0, DNS_OPT_FLAGS, -1) | DNS_NORD);
|
||||
break;
|
||||
default: return 1;
|
||||
}
|
||||
if (argc != optind) return 1;
|
||||
|
||||
pfd.fd = dns_sock(0);
|
||||
pfd.events = POLLIN;
|
||||
now = time(NULL);
|
||||
c = optind;
|
||||
eof = 0;
|
||||
while(curq || !eof) {
|
||||
if (!eof && curq < maxq) {
|
||||
union { struct in_addr a; void *p; } pa;
|
||||
if (!fgets(linebuf, sizeof(linebuf), stdin)) {
|
||||
eof = 1;
|
||||
continue;
|
||||
}
|
||||
eol = strchr(linebuf, '\n');
|
||||
if (eol) *eol = '\0';
|
||||
if (!linebuf[0]) continue;
|
||||
if (!inet_aton(linebuf, &pa.a))
|
||||
fprintf(stderr, "%s: invalid address\n", linebuf);
|
||||
else if (dns_submit_a4ptr(0, &pa.a, dnscb, pa.p) == 0)
|
||||
fprintf(stderr, "%s: unable to submit query: %s\n",
|
||||
linebuf, dns_strerror(dns_status(0)));
|
||||
else
|
||||
++curq;
|
||||
continue;
|
||||
}
|
||||
if (curq) {
|
||||
t = dns_timeouts(0, -1, now);
|
||||
t = poll(&pfd, 1, c * 1000);
|
||||
now = time(NULL);
|
||||
if (t) dns_ioevent(0, now);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
/* This is from the BIND 4.9.4 release, modified to compile by itself */
|
||||
|
||||
/* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_INET_PTON
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "inet_pton.h"
|
||||
|
||||
#define IN6ADDRSZ 16
|
||||
#define INADDRSZ 4
|
||||
#define INT16SZ 2
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* WARNING: Don't even consider trying to compile this on a system where
|
||||
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||
*/
|
||||
|
||||
static int inet_pton4(const char *src, unsigned char *dst);
|
||||
#ifdef ENABLE_IPV6
|
||||
static int inet_pton6(const char *src, unsigned char *dst);
|
||||
#endif
|
||||
|
||||
/* int
|
||||
* inet_pton(af, src, dst)
|
||||
* convert from presentation format (which usually means ASCII printable)
|
||||
* to network format (which is usually some kind of binary format).
|
||||
* return:
|
||||
* 1 if the address was valid for the specified address family
|
||||
* 0 if the address wasn't valid (`dst' is untouched in this case)
|
||||
* -1 if some other error occurred (`dst' is untouched in this case, too)
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
int
|
||||
udns_inet_pton(int af, const char *src, void *dst)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_pton4(src, (unsigned char *)dst));
|
||||
#ifdef ENABLE_IPV6
|
||||
#ifndef AF_INET6
|
||||
#define AF_INET6 (AF_MAX+1) /* just to let this compile */
|
||||
#endif
|
||||
case AF_INET6:
|
||||
return (inet_pton6(src, (unsigned char *)dst));
|
||||
#endif
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (-1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton4(src, dst)
|
||||
* like inet_aton() but without all the hexadecimal and shorthand.
|
||||
* return:
|
||||
* 1 if `src' is a valid dotted quad, else 0.
|
||||
* notice:
|
||||
* does not touch `dst' unless it's returning 1.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton4(const char *src, unsigned char *dst)
|
||||
{
|
||||
static const char digits[] = "0123456789";
|
||||
int saw_digit, octets, ch;
|
||||
unsigned char tmp[INADDRSZ], *tp;
|
||||
|
||||
saw_digit = 0;
|
||||
octets = 0;
|
||||
tp = tmp;
|
||||
*tp = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr(digits, ch)) != NULL) {
|
||||
unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
|
||||
|
||||
if (val > 255)
|
||||
return (0);
|
||||
*tp = val;
|
||||
if (! saw_digit) {
|
||||
if (++octets > 4)
|
||||
return (0);
|
||||
saw_digit = 1;
|
||||
}
|
||||
} else if (ch == '.' && saw_digit) {
|
||||
if (octets == 4)
|
||||
return (0);
|
||||
*++tp = 0;
|
||||
saw_digit = 0;
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
if (octets < 4)
|
||||
return (0);
|
||||
/* bcopy(tmp, dst, INADDRSZ); */
|
||||
memcpy(dst, tmp, INADDRSZ);
|
||||
return (1);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
/* int
|
||||
* inet_pton6(src, dst)
|
||||
* convert presentation level address to network order binary form.
|
||||
* return:
|
||||
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
|
||||
* notice:
|
||||
* (1) does not touch `dst' unless it's returning 1.
|
||||
* (2) :: in a full address is silently ignored.
|
||||
* credit:
|
||||
* inspired by Mark Andrews.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton6(const char *src, unsigned char *dst)
|
||||
{
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
|
||||
const char *xdigits, *curtok;
|
||||
int ch, saw_xdigit;
|
||||
unsigned int val;
|
||||
|
||||
memset((tp = tmp), 0, IN6ADDRSZ);
|
||||
endp = tp + IN6ADDRSZ;
|
||||
colonp = NULL;
|
||||
/* Leading :: requires some special handling. */
|
||||
if (*src == ':')
|
||||
if (*++src != ':')
|
||||
return (0);
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
|
||||
pch = strchr((xdigits = xdigits_u), ch);
|
||||
if (pch != NULL) {
|
||||
val <<= 4;
|
||||
val |= (pch - xdigits);
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
if (ch == ':') {
|
||||
curtok = src;
|
||||
if (!saw_xdigit) {
|
||||
if (colonp)
|
||||
return (0);
|
||||
colonp = tp;
|
||||
continue;
|
||||
}
|
||||
if (tp + INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (unsigned char) (val >> 8) & 0xff;
|
||||
*tp++ = (unsigned char) val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
|
||||
inet_pton4(curtok, tp) > 0) {
|
||||
tp += INADDRSZ;
|
||||
saw_xdigit = 0;
|
||||
break; /* '\0' was seen by inet_pton4(). */
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
if (saw_xdigit) {
|
||||
if (tp + INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (unsigned char) (val >> 8) & 0xff;
|
||||
*tp++ = (unsigned char) val & 0xff;
|
||||
}
|
||||
if (colonp != NULL) {
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
const int n = tp - colonp;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
endp[- i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
if (tp != endp)
|
||||
return (0);
|
||||
/* bcopy(tmp, dst, IN6ADDRSZ); */
|
||||
memcpy(dst, tmp, IN6ADDRSZ);
|
||||
return (1);
|
||||
}
|
||||
#endif /* ENABLE_IPV6 */
|
||||
|
||||
#endif /* HAVE_INET_PTON */
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef __INET_PTON_H
|
||||
#define __INET_PTON_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id: inet_pton.h,v 1.7 2005/11/28 20:21:36 bagder Exp $
|
||||
***************************************************************************/
|
||||
|
||||
int udns_inet_pton(int, const char *, void *);
|
||||
|
||||
#endif /* __INET_PTON_H */
|
||||
@@ -1,151 +0,0 @@
|
||||
.\" $Id: rblcheck.1,v 1.1 2005/04/24 23:14:23 mjt Exp $
|
||||
.\" rblckeck manpage
|
||||
.\"
|
||||
.\" Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
.\" This file is part of UDNS library, an async DNS stub resolver.
|
||||
.\"
|
||||
.\" This library is free software; you can redistribute it and/or
|
||||
.\" modify it under the terms of the GNU Lesser General Public
|
||||
.\" License as published by the Free Software Foundation; either
|
||||
.\" version 2.1 of the License, or (at your option) any later version.
|
||||
.\"
|
||||
.\" This library is distributed in the hope that it will be useful,
|
||||
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
.\" Lesser General Public License for more details.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU Lesser General Public
|
||||
.\" License along with this library, in file named COPYING.LGPL; if not,
|
||||
.\" write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
.\" Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
.TH rblckeck 1 "Apr 2005" "User Utilities"
|
||||
|
||||
.SH NAME
|
||||
rblckeck \- DNSBL lookup utility
|
||||
|
||||
.SH SYNOPSYS
|
||||
.B rblcheck
|
||||
.RB [\| \-s
|
||||
.IR zone \|]
|
||||
.RB [\| \-S
|
||||
.IR zone\-file \|]
|
||||
.RB [\| \-c \|]
|
||||
.RB [\| \-tmvq \|]
|
||||
.RB [\| \-n
|
||||
.IR nsaddr \|]
|
||||
.IR address \|.\|.\|.
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B rblcheck
|
||||
is a simple command-line to perform DNSBL (DNS-based blocklists) lookups.
|
||||
For every IP address (or a name, in which case it will be resolved to an
|
||||
address first), the utility verifies whenever it is listed in a (list of)
|
||||
DNS blocklists specified with
|
||||
.B \-s
|
||||
or
|
||||
.B \-S
|
||||
options, optionally obtains text assotiated with the listing (usually it
|
||||
is either some description about the reason of the listing or an URL
|
||||
referring to such a description), and displays results on standard output.
|
||||
.PP
|
||||
The program is implemented on top of
|
||||
.BR udns (3)
|
||||
library.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
The following options are recognized by
|
||||
.BR rblcheck :
|
||||
|
||||
.TP
|
||||
.B \-s \fIzone\fR
|
||||
add the given \fIzone\fR DNSBL name to the list of active zones.
|
||||
.TP
|
||||
.B \-S \fIzone-file\fR
|
||||
add list of zones from the named \fIzone-file\fR to the list of
|
||||
active zones (the file specifies one zone as the first word on a
|
||||
line, empty lines and lines starting with `#' character are ignored).
|
||||
.TP
|
||||
.B \-c
|
||||
reset active zone list.
|
||||
.TP
|
||||
.B \-v
|
||||
be more verbose, produce more detailed output.
|
||||
.TP
|
||||
.B \-q
|
||||
the opposite for \fB\-v\fR -- produce less detailed output.
|
||||
.TP
|
||||
.B \-t
|
||||
obtain text for listed addresses.
|
||||
.TP
|
||||
.B \-n \fInsaddr\fR
|
||||
Use the given nameserver (given as IPv4 or IPv6 address) instead of the
|
||||
default. The same effect may be achieved by setting $NSCACHEIP environment
|
||||
variable.
|
||||
.TP
|
||||
.B \-m
|
||||
stop after first hit, ie after the first address which is found to be
|
||||
listed.
|
||||
|
||||
.TP
|
||||
.B \-h
|
||||
print short help and exit.
|
||||
|
||||
.PP
|
||||
If no
|
||||
.BR \-s ,
|
||||
.BR \-S
|
||||
and
|
||||
.B \-c
|
||||
options are given,
|
||||
.B rblcheck
|
||||
will try to obtain list of zones using $RBLCHECK_ZONES environment variable,
|
||||
or ~/.rblcheckrc, or /etc/rblckechrc files, in that order. If no zones are
|
||||
found, it will exit unsuccessefully.
|
||||
|
||||
.SH "RETURN VALUE"
|
||||
When no addresses given are listed and no errors occured,
|
||||
.B rblcheck
|
||||
exits with code 0. If at least one address is listed,
|
||||
.B rblcheck
|
||||
returns 100. In case of DNS errors,
|
||||
.B rblcheck
|
||||
returns 2.
|
||||
|
||||
.SH ENVIRONMENT
|
||||
|
||||
.TP
|
||||
.B $RBLCHECK_ZONES
|
||||
if no
|
||||
.BR \-s ,
|
||||
.B \-S
|
||||
or
|
||||
.B \-c
|
||||
option is given,
|
||||
.B rblcheck
|
||||
tries this variable to obtain list of DNSBL zones to check against.
|
||||
|
||||
.SH FILES
|
||||
|
||||
.TP
|
||||
$HOME/.rblcheckrc and /etc/rblcheckrc
|
||||
if no
|
||||
.BR \-s ,
|
||||
.B \-S
|
||||
or
|
||||
.B \-c
|
||||
option is given, and no $RBLCHECK_ZONES environment variable is set,
|
||||
.B rblcheck
|
||||
will try the two files (the first one that exists) to obtain list of
|
||||
DNSBL zones to check against.
|
||||
Each line specifies one zone (only first word in each line is used).
|
||||
Empty lines and lines starting with `#' character are ignored.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR dnsget (1)
|
||||
.BR resolv.conf (5)
|
||||
.BR udns (3).
|
||||
|
||||
.SH AUTHOR
|
||||
This program and manual pages are written by Michael Tokarev.
|
||||
@@ -1,364 +0,0 @@
|
||||
/* $Id: rblcheck.c,v 1.9 2005/04/24 22:49:10 mjt Exp $
|
||||
dnsbl (rbl) checker application
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include "udns.h"
|
||||
|
||||
static const char *version = "udns-rblcheck 0.1";
|
||||
static char *progname;
|
||||
|
||||
struct rblookup {
|
||||
struct ipcheck *parent;
|
||||
struct in_addr key;
|
||||
const char *zone;
|
||||
struct dns_rr_a4 *addr;
|
||||
struct dns_rr_txt *txt;
|
||||
};
|
||||
|
||||
struct ipcheck {
|
||||
const char *name;
|
||||
int naddr;
|
||||
int listed;
|
||||
struct rblookup *lookup;
|
||||
};
|
||||
|
||||
#define notlisted ((void*)1)
|
||||
|
||||
static int nzones, nzalloc;
|
||||
static const char **zones;
|
||||
|
||||
static int do_txt;
|
||||
static int stopfirst;
|
||||
static int verbose = 1;
|
||||
/* verbosity level:
|
||||
* <0 - only bare As/TXTs
|
||||
* 0 - what RBL result
|
||||
* 1(default) - what is listed by RBL: result
|
||||
* 2 - what is[not ]listed by RBL: result, name lookups
|
||||
*/
|
||||
|
||||
static int listed;
|
||||
static int failures;
|
||||
|
||||
static void *ecalloc(int size, int cnt) {
|
||||
void *t = calloc(size, cnt);
|
||||
if (!t) {
|
||||
fprintf(stderr, "%s: out of memory\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
static void addzone(const char *zone) {
|
||||
if (nzones >= nzalloc) {
|
||||
const char **zs = (const char**)ecalloc(sizeof(char*), (nzalloc += 16));
|
||||
if (zones) {
|
||||
memcpy(zs, zones, nzones * sizeof(char*));
|
||||
free(zones);
|
||||
}
|
||||
zones = zs;
|
||||
}
|
||||
zones[nzones++] = zone;
|
||||
}
|
||||
|
||||
static int addzonefile(const char *fname) {
|
||||
FILE *f = fopen(fname, "r");
|
||||
char linebuf[2048];
|
||||
if (!f)
|
||||
return 0;
|
||||
while(fgets(linebuf, sizeof(linebuf), f)) {
|
||||
char *p = linebuf, *e;
|
||||
while(*p == ' ' || *p == '\t') ++p;
|
||||
if (*p == '#' || *p == '\n') continue;
|
||||
e = p;
|
||||
while(*e && *e != ' ' && *e != '\t' && *e != '\n')
|
||||
++e;
|
||||
*e = '\0';
|
||||
addzone(p);
|
||||
}
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dnserror(struct rblookup *ipl, const char *what) {
|
||||
fprintf(stderr, "%s: unable to %s for %s (%s): %s\n",
|
||||
progname, what, inet_ntoa(ipl->key), ipl->zone,
|
||||
dns_strerror(dns_status(0)));
|
||||
++failures;
|
||||
}
|
||||
|
||||
static void display_result(struct ipcheck *ipc) {
|
||||
int j;
|
||||
struct rblookup *l, *le;
|
||||
if (!ipc->naddr) return;
|
||||
for (l = ipc->lookup, le = l + nzones * ipc->naddr; l < le; ++l) {
|
||||
if (!l->addr) continue;
|
||||
if (verbose < 2 && l->addr == notlisted) continue;
|
||||
if (verbose >= 0) {
|
||||
if (ipc->name) printf("%s[%s]", ipc->name, inet_ntoa(l->key));
|
||||
else printf("%s", inet_ntoa(l->key));
|
||||
}
|
||||
if (l->addr == notlisted) {
|
||||
printf(" is NOT listed by %s\n", l->zone);
|
||||
continue;
|
||||
}
|
||||
else if (verbose >= 1)
|
||||
printf(" is listed by %s: ", l->zone);
|
||||
else if (verbose >= 0)
|
||||
printf(" %s ", l->zone);
|
||||
if (verbose >= 1 || !do_txt)
|
||||
for (j = 0; j < l->addr->dnsa4_nrr; ++j)
|
||||
printf("%s%s", j ? " " : "", inet_ntoa(l->addr->dnsa4_addr[j]));
|
||||
if (!do_txt) ;
|
||||
else if (l->txt) {
|
||||
for(j = 0; j < l->txt->dnstxt_nrr; ++j) {
|
||||
unsigned char *t = l->txt->dnstxt_txt[j].txt;
|
||||
unsigned char *e = t + l->txt->dnstxt_txt[j].len;
|
||||
printf("%s\"", verbose > 0 ? "\n\t" : j ? " " : "");
|
||||
while(t < e) {
|
||||
if (*t < ' ' || *t >= 127) printf("\\x%02x", *t);
|
||||
else if (*t == '\\' || *t == '"') printf("\\%c", *t);
|
||||
else putchar(*t);
|
||||
++t;
|
||||
}
|
||||
putchar('"');
|
||||
}
|
||||
free(l->txt);
|
||||
}
|
||||
else
|
||||
printf("%s<no text available>", verbose > 0 ? "\n\t" : "");
|
||||
free(l->addr);
|
||||
putchar('\n');
|
||||
}
|
||||
free(ipc->lookup);
|
||||
}
|
||||
|
||||
static void txtcb(struct dns_ctx *ctx, struct dns_rr_txt *r, void *data) {
|
||||
struct rblookup *ipl = data;
|
||||
if (r) {
|
||||
ipl->txt = r;
|
||||
++ipl->parent->listed;
|
||||
}
|
||||
else if (dns_status(ctx) != DNS_E_NXDOMAIN)
|
||||
dnserror(ipl, "lookup DNSBL TXT record");
|
||||
}
|
||||
|
||||
static void a4cb(struct dns_ctx *ctx, struct dns_rr_a4 *r, void *data) {
|
||||
struct rblookup *ipl = data;
|
||||
if (r) {
|
||||
ipl->addr = r;
|
||||
++listed;
|
||||
if (do_txt) {
|
||||
if (dns_submit_a4dnsbl_txt(0, &ipl->key, ipl->zone, txtcb, ipl))
|
||||
return;
|
||||
dnserror(ipl, "submit DNSBL TXT record");
|
||||
}
|
||||
++ipl->parent->listed;
|
||||
}
|
||||
else if (dns_status(ctx) != DNS_E_NXDOMAIN)
|
||||
dnserror(ipl, "lookup DNSBL A record");
|
||||
else
|
||||
ipl->addr = notlisted;
|
||||
}
|
||||
|
||||
static int
|
||||
submit_a_queries(struct ipcheck *ipc,
|
||||
int naddr, const struct in_addr *addr) {
|
||||
int z, a;
|
||||
struct rblookup *rl = ecalloc(sizeof(*rl), nzones * naddr);
|
||||
ipc->lookup = rl;
|
||||
ipc->naddr = naddr;
|
||||
for(a = 0; a < naddr; ++a) {
|
||||
for(z = 0; z < nzones; ++z) {
|
||||
rl->key = addr[a];
|
||||
rl->zone = zones[z];
|
||||
rl->parent = ipc;
|
||||
if (!dns_submit_a4dnsbl(0, &rl->key, rl->zone, a4cb, rl))
|
||||
dnserror(rl, "submit DNSBL A query");
|
||||
++rl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void namecb(struct dns_ctx *ctx, struct dns_rr_a4 *rr, void *data) {
|
||||
struct ipcheck *ipc = data;
|
||||
if (rr) {
|
||||
submit_a_queries(ipc, rr->dnsa4_nrr, rr->dnsa4_addr);
|
||||
free(rr);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s: unable to lookup %s: %s\n",
|
||||
progname, ipc->name, dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
|
||||
static int submit(struct ipcheck *ipc) {
|
||||
struct in_addr addr;
|
||||
if (inet_aton(ipc->name, &addr)) {
|
||||
submit_a_queries(ipc, 1, &addr);
|
||||
ipc->name = NULL;
|
||||
}
|
||||
else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc))
|
||||
fprintf(stderr, "%s: unable to submit name query for %s: %s\n",
|
||||
progname, ipc->name, dns_strerror(dns_status(0)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void waitdns(struct ipcheck *ipc) {
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
int c;
|
||||
int fd = dns_sock(NULL);
|
||||
time_t now = 0;
|
||||
FD_ZERO(&fds);
|
||||
while((c = dns_timeouts(NULL, -1, now)) > 0) {
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = c;
|
||||
tv.tv_usec = 0;
|
||||
c = select(fd+1, &fds, NULL, NULL, &tv);
|
||||
now = time(NULL);
|
||||
if (c > 0)
|
||||
dns_ioevent(NULL, now);
|
||||
if (stopfirst && ipc->listed)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int c;
|
||||
struct ipcheck ipc;
|
||||
char *nameserver = NULL;
|
||||
int zgiven = 0;
|
||||
|
||||
if (!(progname = strrchr(argv[0], '/'))) progname = argv[0];
|
||||
else argv[0] = ++progname;
|
||||
|
||||
while((c = getopt(argc, argv, "hqtvms:S:cn:")) != EOF) switch(c) {
|
||||
case 's': ++zgiven; addzone(optarg); break;
|
||||
case 'S':
|
||||
++zgiven;
|
||||
if (addzonefile(optarg)) break;
|
||||
fprintf(stderr, "%s: unable to read %s\n", progname, optarg);
|
||||
return 1;
|
||||
case 'c': ++zgiven; nzones = 0; break;
|
||||
case 'q': --verbose; break;
|
||||
case 'v': ++verbose; break;
|
||||
case 't': do_txt = 1; break;
|
||||
case 'n': nameserver = optarg; break;
|
||||
case 'm': ++stopfirst; break;
|
||||
case 'h':
|
||||
printf("%s: %s.\n", progname, version);
|
||||
printf("Usage is: %s [options] address..\n", progname);
|
||||
printf(
|
||||
"Where options are:\n"
|
||||
" -h - print this help and exit\n"
|
||||
" -s service - add the service (DNSBL zone) to the serice list\n"
|
||||
" -S service-file - add the DNSBL zone(s) read from the given file\n"
|
||||
" -c - clear service list\n"
|
||||
" -v - increase verbosity level (more -vs => more verbose)\n"
|
||||
" -q - decrease verbosity level (opposite of -v)\n"
|
||||
" -t - obtain and print TXT records if any\n"
|
||||
" -m - stop checking after first address match in any list\n"
|
||||
" -n ipaddr - use the given nameserver instead of the default\n"
|
||||
"(if no -s or -S option is given, use $RBLCHECK_ZONES, ~/.rblcheckrc\n"
|
||||
"or /etc/rblcheckrc in that order)\n"
|
||||
);
|
||||
return 0;
|
||||
default:
|
||||
fprintf(stderr, "%s: use `%s -h' for help\n", progname, progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!zgiven) {
|
||||
char *s = getenv("RBLCHECK_ZONES");
|
||||
if (s) {
|
||||
char *k;
|
||||
s = strdup(s);
|
||||
k = strtok(s, " \t");
|
||||
while(k) {
|
||||
addzone(k);
|
||||
k = strtok(NULL, " \t");
|
||||
}
|
||||
free(s);
|
||||
}
|
||||
else {
|
||||
char *path;
|
||||
char *home = getenv("HOME");
|
||||
if (!home) home = ".";
|
||||
path = malloc(strlen(home) + 1 + sizeof(".rblcheckrc"));
|
||||
sprintf(path, "%s/.rblcheckrc", home);
|
||||
if (!addzonefile(path))
|
||||
addzonefile("/etc/rblcheckrc");
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
if (!nzones) {
|
||||
fprintf(stderr, "%s: no service (zone) list specified (-s or -S option)\n",
|
||||
progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
if (!argc)
|
||||
return 0;
|
||||
|
||||
if (dns_init(0) < 0) {
|
||||
fprintf(stderr, "%s: unable to initialize DNS library: %s\n",
|
||||
progname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (nameserver) {
|
||||
dns_add_serv(NULL, NULL);
|
||||
if (dns_add_serv(NULL, nameserver) < 0)
|
||||
fprintf(stderr, "%s: unable to use nameserver %s: %s\n",
|
||||
progname, nameserver, strerror(errno));
|
||||
}
|
||||
if (dns_open(NULL) < 0) {
|
||||
fprintf(stderr, "%s: unable to initialize DNS library: %s\n",
|
||||
progname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (c = 0; c < argc; ++c) {
|
||||
if (c && (verbose > 1 || (verbose == 1 && do_txt))) putchar('\n');
|
||||
ipc.name = argv[c];
|
||||
submit(&ipc);
|
||||
waitdns(&ipc);
|
||||
display_result(&ipc);
|
||||
if (stopfirst > 1 && listed) break;
|
||||
}
|
||||
|
||||
return listed ? 100 : failures ? 2 : 0;
|
||||
}
|
||||
-1284
File diff suppressed because it is too large.
Load diff
@@ -1,747 +0,0 @@
|
||||
/* $Id: udns.h,v 1.41 2006/11/29 01:20:30 mjt Exp $
|
||||
header file for the UDNS library.
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef UDNS_VERSION /* include guard */
|
||||
|
||||
#define UDNS_VERSION "0.0.9pre"
|
||||
|
||||
#ifdef WIN32
|
||||
# ifdef UDNS_DYNAMIC_LIBRARY
|
||||
# ifdef DNS_LIBRARY_BUILD
|
||||
# define UDNS_API __declspec(dllexport)
|
||||
# define UDNS_DATA_API __declspec(dllexport)
|
||||
# else
|
||||
# define UDNS_API __declspec(dllimport)
|
||||
# define UDNS_DATA_API __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#ifdef _MSC_VER
|
||||
#undef inline
|
||||
#define inline __inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UDNS_API
|
||||
# define UDNS_API
|
||||
#endif
|
||||
#ifndef UDNS_DATA_API
|
||||
# define UDNS_DATA_API
|
||||
#endif
|
||||
|
||||
#include <sys/types.h> /* for time_t */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* forward declarations if sockets stuff isn't #include'd */
|
||||
struct in_addr;
|
||||
struct in6_addr;
|
||||
struct sockaddr;
|
||||
|
||||
/**************************************************************************/
|
||||
/**************** Common definitions **************************************/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "winsock2.h"
|
||||
typedef SOCKET dns_socket;
|
||||
#else
|
||||
typedef int dns_socket;
|
||||
#endif
|
||||
|
||||
UDNS_API const char *
|
||||
dns_version(void);
|
||||
|
||||
struct dns_ctx;
|
||||
struct dns_query;
|
||||
|
||||
/* shorthand for [const] unsigned char */
|
||||
typedef unsigned char dnsc_t;
|
||||
typedef const unsigned char dnscc_t;
|
||||
|
||||
#define DNS_MAXDN 255 /* max DN length */
|
||||
#define DNS_MAXLABEL 63 /* max DN label length */
|
||||
#define DNS_MAXNAME 1024 /* max asciiz domain name length */
|
||||
#define DNS_HSIZE 12 /* DNS packet header size */
|
||||
#define DNS_PORT 53 /* default domain port */
|
||||
#define DNS_MAXSERV 6 /* max servers to consult */
|
||||
#define DNS_MAXSRCH 5 /* max searchlist entries */
|
||||
#define DNS_MAXPACKET 512 /* max traditional-DNS UDP packet size */
|
||||
#define DNS_EDNS0PACKET 4096 /* EDNS0 packet size to use */
|
||||
|
||||
enum dns_class { /* DNS RR Classes */
|
||||
DNS_C_INVALID = 0, /* invalid class */
|
||||
DNS_C_IN = 1, /* Internet */
|
||||
DNS_C_CH = 3, /* CHAOS */
|
||||
DNS_C_HS = 4, /* HESIOD */
|
||||
DNS_C_ANY = 255 /* wildcard */
|
||||
};
|
||||
|
||||
enum dns_type { /* DNS RR Types */
|
||||
DNS_T_INVALID = 0, /* Cookie. */
|
||||
DNS_T_A = 1, /* Host address. */
|
||||
DNS_T_NS = 2, /* Authoritative server. */
|
||||
DNS_T_MD = 3, /* Mail destination. */
|
||||
DNS_T_MF = 4, /* Mail forwarder. */
|
||||
DNS_T_CNAME = 5, /* Canonical name. */
|
||||
DNS_T_SOA = 6, /* Start of authority zone. */
|
||||
DNS_T_MB = 7, /* Mailbox domain name. */
|
||||
DNS_T_MG = 8, /* Mail group member. */
|
||||
DNS_T_MR = 9, /* Mail rename name. */
|
||||
DNS_T_NULL = 10, /* Null resource record. */
|
||||
DNS_T_WKS = 11, /* Well known service. */
|
||||
DNS_T_PTR = 12, /* Domain name pointer. */
|
||||
DNS_T_HINFO = 13, /* Host information. */
|
||||
DNS_T_MINFO = 14, /* Mailbox information. */
|
||||
DNS_T_MX = 15, /* Mail routing information. */
|
||||
DNS_T_TXT = 16, /* Text strings. */
|
||||
DNS_T_RP = 17, /* Responsible person. */
|
||||
DNS_T_AFSDB = 18, /* AFS cell database. */
|
||||
DNS_T_X25 = 19, /* X_25 calling address. */
|
||||
DNS_T_ISDN = 20, /* ISDN calling address. */
|
||||
DNS_T_RT = 21, /* Router. */
|
||||
DNS_T_NSAP = 22, /* NSAP address. */
|
||||
DNS_T_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */
|
||||
DNS_T_SIG = 24, /* Security signature. */
|
||||
DNS_T_KEY = 25, /* Security key. */
|
||||
DNS_T_PX = 26, /* X.400 mail mapping. */
|
||||
DNS_T_GPOS = 27, /* Geographical position (withdrawn). */
|
||||
DNS_T_AAAA = 28, /* Ip6 Address. */
|
||||
DNS_T_LOC = 29, /* Location Information. */
|
||||
DNS_T_NXT = 30, /* Next domain (security). */
|
||||
DNS_T_EID = 31, /* Endpoint identifier. */
|
||||
DNS_T_NIMLOC = 32, /* Nimrod Locator. */
|
||||
DNS_T_SRV = 33, /* Server Selection. */
|
||||
DNS_T_ATMA = 34, /* ATM Address */
|
||||
DNS_T_NAPTR = 35, /* Naming Authority PoinTeR */
|
||||
DNS_T_KX = 36, /* Key Exchange */
|
||||
DNS_T_CERT = 37, /* Certification record */
|
||||
DNS_T_A6 = 38, /* IPv6 address (deprecates AAAA) */
|
||||
DNS_T_DNAME = 39, /* Non-terminal DNAME (for IPv6) */
|
||||
DNS_T_SINK = 40, /* Kitchen sink (experimentatl) */
|
||||
DNS_T_OPT = 41, /* EDNS0 option (meta-RR) */
|
||||
DNS_T_DS = 43, /* DNSSEC */
|
||||
DNS_T_NSEC = 47, /* DNSSEC */
|
||||
DNS_T_TSIG = 250, /* Transaction signature. */
|
||||
DNS_T_IXFR = 251, /* Incremental zone transfer. */
|
||||
DNS_T_AXFR = 252, /* Transfer zone of authority. */
|
||||
DNS_T_MAILB = 253, /* Transfer mailbox records. */
|
||||
DNS_T_MAILA = 254, /* Transfer mail agent records. */
|
||||
DNS_T_ANY = 255, /* Wildcard match. */
|
||||
DNS_T_ZXFR = 256, /* BIND-specific, nonstandard. */
|
||||
DNS_T_MAX = 65536
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
/**************** Domain Names (DNs) **************************************/
|
||||
|
||||
/* return length of the DN */
|
||||
UDNS_API unsigned
|
||||
dns_dnlen(dnscc_t *dn);
|
||||
|
||||
/* return #of labels in a DN */
|
||||
UDNS_API unsigned
|
||||
dns_dnlabels(dnscc_t *dn);
|
||||
|
||||
/* lower- and uppercase single DN char */
|
||||
#define DNS_DNLC(c) ((c) >= 'A' && (c) <= 'Z' ? (c) - 'A' + 'a' : (c))
|
||||
#define DNS_DNUC(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
|
||||
|
||||
/* compare the DNs, return dnlen of equal or 0 if not */
|
||||
UDNS_API unsigned
|
||||
dns_dnequal(dnscc_t *dn1, dnscc_t *dn2);
|
||||
|
||||
/* copy one DN to another, size checking */
|
||||
UDNS_API unsigned
|
||||
dns_dntodn(dnscc_t *sdn, dnsc_t *ddn, unsigned ddnsiz);
|
||||
|
||||
/* convert asciiz string of length namelen (0 to use strlen) to DN */
|
||||
UDNS_API int
|
||||
dns_ptodn(const char *name, unsigned namelen,
|
||||
dnsc_t *dn, unsigned dnsiz, int *isabs);
|
||||
|
||||
/* simpler form of dns_ptodn() */
|
||||
#define dns_sptodn(name,dn,dnsiz) dns_ptodn((name),0,(dn),(dnsiz),0)
|
||||
|
||||
UDNS_DATA_API extern dnscc_t dns_inaddr_arpa_dn[14];
|
||||
#define DNS_A4RSIZE 30
|
||||
UDNS_API int
|
||||
dns_a4todn(const struct in_addr *addr, dnscc_t *tdn,
|
||||
dnsc_t *dn, unsigned dnsiz);
|
||||
UDNS_API int
|
||||
dns_a4ptodn(const struct in_addr *addr, const char *tname,
|
||||
dnsc_t *dn, unsigned dnsiz);
|
||||
UDNS_API dnsc_t *
|
||||
dns_a4todn_(const struct in_addr *addr, dnsc_t *dn, dnsc_t *dne);
|
||||
|
||||
UDNS_DATA_API extern dnscc_t dns_ip6_arpa_dn[10];
|
||||
#define DNS_A6RSIZE 74
|
||||
UDNS_API int
|
||||
dns_a6todn(const struct in6_addr *addr, dnscc_t *tdn,
|
||||
dnsc_t *dn, unsigned dnsiz);
|
||||
UDNS_API int
|
||||
dns_a6ptodn(const struct in6_addr *addr, const char *tname,
|
||||
dnsc_t *dn, unsigned dnsiz);
|
||||
UDNS_API dnsc_t *
|
||||
dns_a6todn_(const struct in6_addr *addr, dnsc_t *dn, dnsc_t *dne);
|
||||
|
||||
/* convert DN into asciiz string */
|
||||
UDNS_API int
|
||||
dns_dntop(dnscc_t *dn, char *name, unsigned namesiz);
|
||||
|
||||
/* convert DN into asciiz string, using static buffer (NOT thread-safe!) */
|
||||
UDNS_API const char *
|
||||
dns_dntosp(dnscc_t *dn);
|
||||
|
||||
/* return buffer size (incl. null byte) required for asciiz form of a DN */
|
||||
UDNS_API unsigned
|
||||
dns_dntop_size(dnscc_t *dn);
|
||||
|
||||
/**************************************************************************/
|
||||
/**************** DNS raw packet layout ***********************************/
|
||||
|
||||
enum dns_rcode { /* reply codes */
|
||||
DNS_R_NOERROR = 0, /* ok, no error */
|
||||
DNS_R_FORMERR = 1, /* format error */
|
||||
DNS_R_SERVFAIL = 2, /* server failed */
|
||||
DNS_R_NXDOMAIN = 3, /* domain does not exists */
|
||||
DNS_R_NOTIMPL = 4, /* not implemented */
|
||||
DNS_R_REFUSED = 5, /* query refused */
|
||||
/* these are for BIND_UPDATE */
|
||||
DNS_R_YXDOMAIN = 6, /* Name exists */
|
||||
DNS_R_YXRRSET = 7, /* RRset exists */
|
||||
DNS_R_NXRRSET = 8, /* RRset does not exist */
|
||||
DNS_R_NOTAUTH = 9, /* Not authoritative for zone */
|
||||
DNS_R_NOTZONE = 10, /* Zone of record different from zone section */
|
||||
/*ns_r_max = 11,*/
|
||||
/* The following are TSIG extended errors */
|
||||
DNS_R_BADSIG = 16,
|
||||
DNS_R_BADKEY = 17,
|
||||
DNS_R_BADTIME = 18
|
||||
};
|
||||
|
||||
static inline unsigned dns_get16(dnscc_t *s) {
|
||||
return ((unsigned)s[0]<<8) | s[1];
|
||||
}
|
||||
static inline unsigned dns_get32(dnscc_t *s) {
|
||||
return ((unsigned)s[0]<<24) | ((unsigned)s[1]<<16)
|
||||
| ((unsigned)s[2]<<8) | s[3];
|
||||
}
|
||||
static inline dnsc_t *dns_put16(dnsc_t *d, unsigned n) {
|
||||
*d++ = (dnsc_t)((n >> 8) & 255); *d++ = (dnsc_t)(n & 255); return d;
|
||||
}
|
||||
static inline dnsc_t *dns_put32(dnsc_t *d, unsigned n) {
|
||||
*d++ = (dnsc_t)((n >> 24) & 255); *d++ = (dnsc_t)((n >> 16) & 255);
|
||||
*d++ = (dnsc_t)((n >> 8) & 255); *d++ = (dnsc_t)(n & 255);
|
||||
return d;
|
||||
}
|
||||
|
||||
/* DNS Header layout */
|
||||
enum {
|
||||
/* bytes 0:1 - query ID */
|
||||
DNS_H_QID1 = 0,
|
||||
DNS_H_QID2 = 1,
|
||||
DNS_H_QID = DNS_H_QID1,
|
||||
#define dns_qid(pkt) dns_get16((pkt)+DNS_H_QID)
|
||||
/* byte 2: flags1 */
|
||||
DNS_H_F1 = 2,
|
||||
DNS_HF1_QR = 0x80, /* query response flag */
|
||||
#define dns_qr(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_QR)
|
||||
DNS_HF1_OPCODE = 0x78, /* opcode, 0 = query */
|
||||
#define dns_opcode(pkt) (((pkt)[DNS_H_F1]&DNS_HF1_OPCODE)>>3)
|
||||
DNS_HF1_AA = 0x04, /* auth answer */
|
||||
#define dns_aa(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_AA)
|
||||
DNS_HF1_TC = 0x02, /* truncation flag */
|
||||
#define dns_tc(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_TC)
|
||||
DNS_HF1_RD = 0x01, /* recursion desired (may be set in query) */
|
||||
#define dns_rd(pkt) ((pkt)[DNS_H_F1]&DNS_HF1_RD)
|
||||
/* byte 3: flags2 */
|
||||
DNS_H_F2 = 3,
|
||||
DNS_HF2_RA = 0x80, /* recursion available */
|
||||
#define dns_ra(pkt) ((pkt)[DNS_H_F2]&DNS_HF2_RA)
|
||||
DNS_HF2_Z = 0x70, /* reserved */
|
||||
DNS_HF2_RCODE = 0x0f, /* response code, DNS_R_XXX above */
|
||||
#define dns_rcode(pkt) ((pkt)[DNS_H_F2]&DNS_HF2_RCODE)
|
||||
/* bytes 4:5: qdcount, numqueries */
|
||||
DNS_H_QDCNT1 = 4,
|
||||
DNS_H_QDCNT2 = 5,
|
||||
DNS_H_QDCNT = DNS_H_QDCNT1,
|
||||
#define dns_numqd(pkt) dns_get16((pkt)+4)
|
||||
/* bytes 6:7: ancount, numanswers */
|
||||
DNS_H_ANCNT1 = 6,
|
||||
DNS_H_ANCNT2 = 7,
|
||||
DNS_H_ANCNT = DNS_H_ANCNT1,
|
||||
#define dns_numan(pkt) dns_get16((pkt)+6)
|
||||
/* bytes 8:9: nscount, numauthority */
|
||||
DNS_H_NSCNT1 = 8,
|
||||
DNS_H_NSCNT2 = 9,
|
||||
DNS_H_NSCNT = DNS_H_NSCNT1,
|
||||
#define dns_numns(pkt) dns_get16((pkt)+8)
|
||||
/* bytes 10:11: arcount, numadditional */
|
||||
DNS_H_ARCNT1 = 10,
|
||||
DNS_H_ARCNT2 = 11,
|
||||
DNS_H_ARCNT = DNS_H_ARCNT1,
|
||||
#define dns_numar(pkt) dns_get16((pkt)+10)
|
||||
#define dns_payload(pkt) ((pkt)+DNS_HSIZE)
|
||||
};
|
||||
|
||||
/* packet buffer: start at pkt, end before pkte, current pos *curp.
|
||||
* extract a DN and set *curp to the next byte after DN in packet.
|
||||
* return -1 on error, 0 if dnsiz is too small, or dnlen on ok.
|
||||
*/
|
||||
UDNS_API int
|
||||
dns_getdn(dnscc_t *pkt, dnscc_t **curp, dnscc_t *end,
|
||||
dnsc_t *dn, unsigned dnsiz);
|
||||
|
||||
/* skip the DN at position cur in packet ending before pkte,
|
||||
* return pointer to the next byte after the DN or NULL on error */
|
||||
UDNS_API dnscc_t *
|
||||
dns_skipdn(dnscc_t *end, dnscc_t *cur);
|
||||
|
||||
struct dns_rr { /* DNS Resource Record */
|
||||
dnsc_t dnsrr_dn[DNS_MAXDN]; /* the DN of the RR */
|
||||
enum dns_class dnsrr_cls; /* Class */
|
||||
enum dns_type dnsrr_typ; /* Type */
|
||||
unsigned dnsrr_ttl; /* Time-To-Live (TTL) */
|
||||
unsigned dnsrr_dsz; /* data size */
|
||||
dnscc_t *dnsrr_dptr; /* pointer to start of data */
|
||||
dnscc_t *dnsrr_dend; /* past end of data */
|
||||
};
|
||||
|
||||
struct dns_parse { /* RR/packet parsing state */
|
||||
dnscc_t *dnsp_pkt; /* start of the packet */
|
||||
dnscc_t *dnsp_end; /* end of the packet */
|
||||
dnscc_t *dnsp_cur; /* current packet position */
|
||||
dnscc_t *dnsp_ans; /* start of answer section */
|
||||
int dnsp_rrl; /* number of RRs left to go */
|
||||
int dnsp_nrr; /* RR count so far */
|
||||
unsigned dnsp_ttl; /* TTL value so far */
|
||||
dnscc_t *dnsp_qdn; /* the RR DN we're looking for */
|
||||
enum dns_class dnsp_qcls; /* RR class we're looking for or 0 */
|
||||
enum dns_type dnsp_qtyp; /* RR type we're looking for or 0 */
|
||||
dnsc_t dnsp_dnbuf[DNS_MAXDN]; /* domain buffer */
|
||||
};
|
||||
|
||||
/* initialize the parse structure */
|
||||
UDNS_API void
|
||||
dns_initparse(struct dns_parse *p, dnscc_t *qdn,
|
||||
dnscc_t *pkt, dnscc_t *cur, dnscc_t *end);
|
||||
|
||||
/* search next RR, <0=error, 0=no more RRs, >0 = found. */
|
||||
UDNS_API int
|
||||
dns_nextrr(struct dns_parse *p, struct dns_rr *rr);
|
||||
|
||||
UDNS_API void
|
||||
dns_rewind(struct dns_parse *p, dnscc_t *qdn);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************** Resolver Context ****************************************/
|
||||
|
||||
/* default resolver context */
|
||||
UDNS_DATA_API extern struct dns_ctx dns_defctx;
|
||||
|
||||
/* initialize default resolver context and open it if do_open is true.
|
||||
* <0 on failure. */
|
||||
UDNS_API dns_socket
|
||||
dns_init(int do_open);
|
||||
|
||||
/* return new resolver context with the same settings as copy */
|
||||
UDNS_API struct dns_ctx *
|
||||
dns_new(const struct dns_ctx *copy);
|
||||
|
||||
/* free resolver context; all queries are dropped */
|
||||
UDNS_API void
|
||||
dns_free(struct dns_ctx *ctx);
|
||||
|
||||
/* add nameserver for a resolver context (or reset nslist if serv==NULL) */
|
||||
UDNS_API int
|
||||
dns_add_serv(struct dns_ctx *ctx, const char *serv);
|
||||
|
||||
/* add nameserver using struct sockaddr array (with ports etc) */
|
||||
UDNS_API int
|
||||
dns_add_serv_s(struct dns_ctx *ctx, const struct sockaddr *sa);
|
||||
|
||||
/* add search list element for a resolver context (or reset it if srch==NULL) */
|
||||
UDNS_API int
|
||||
dns_add_srch(struct dns_ctx *ctx, const char *srch);
|
||||
|
||||
/* set options for a resolver context */
|
||||
UDNS_API int
|
||||
dns_set_opts(struct dns_ctx *ctx, const char *opts);
|
||||
|
||||
enum dns_opt { /* options */
|
||||
DNS_OPT_FLAGS, /* flags, DNS_F_XXX */
|
||||
DNS_OPT_TIMEOUT, /* timeout in secounds */
|
||||
DNS_OPT_NTRIES, /* number of retries */
|
||||
DNS_OPT_NDOTS, /* ndots */
|
||||
DNS_OPT_UDPSIZE, /* EDNS0 UDP size */
|
||||
DNS_OPT_PORT, /* port to use */
|
||||
};
|
||||
|
||||
/* set or get (if val<0) an option */
|
||||
UDNS_API int
|
||||
dns_set_opt(struct dns_ctx *ctx, enum dns_opt opt, int val);
|
||||
|
||||
enum dns_flags {
|
||||
DNS_NOSRCH = 0x00010000, /* do not perform search */
|
||||
DNS_NORD = 0x00020000, /* request no recursion */
|
||||
DNS_AAONLY = 0x00040000, /* set AA flag in queries */
|
||||
DNS_PASSALL = 0x00080000, /* pass all replies to application */
|
||||
};
|
||||
|
||||
/* set the debug function pointer */
|
||||
typedef void
|
||||
(dns_dbgfn)(int code, const struct sockaddr *sa, unsigned salen,
|
||||
dnscc_t *pkt, int plen,
|
||||
const struct dns_query *q, void *data);
|
||||
UDNS_API void
|
||||
dns_set_dbgfn(struct dns_ctx *ctx, dns_dbgfn *dbgfn);
|
||||
|
||||
/* open and return UDP socket */
|
||||
UDNS_API dns_socket
|
||||
dns_open(struct dns_ctx *ctx);
|
||||
|
||||
/* return UDP socket or -1 if not open */
|
||||
UDNS_API dns_socket
|
||||
dns_sock(const struct dns_ctx *ctx);
|
||||
|
||||
/* close the UDP socket */
|
||||
UDNS_API void
|
||||
dns_close(struct dns_ctx *ctx);
|
||||
|
||||
/* return number of requests queued */
|
||||
UDNS_API int
|
||||
dns_active(const struct dns_ctx *ctx);
|
||||
|
||||
/* return status of the last operation */
|
||||
UDNS_API int
|
||||
dns_status(const struct dns_ctx *ctx);
|
||||
UDNS_API void
|
||||
dns_setstatus(struct dns_ctx *ctx, int status);
|
||||
|
||||
/* handle I/O event on UDP socket */
|
||||
UDNS_API void
|
||||
dns_ioevent(struct dns_ctx *ctx, time_t now);
|
||||
|
||||
/* process any timeouts, return time in secounds to the
|
||||
* next timeout (or -1 if none) but not greather than maxwait */
|
||||
UDNS_API int
|
||||
dns_timeouts(struct dns_ctx *ctx, int maxwait, time_t now);
|
||||
|
||||
/* define timer requesting routine to use */
|
||||
typedef void dns_utm_fn(struct dns_ctx *ctx, int timeout, void *data);
|
||||
UDNS_API void
|
||||
dns_set_tmcbck(struct dns_ctx *ctx, dns_utm_fn *fn, void *data);
|
||||
|
||||
/**************************************************************************/
|
||||
/**************** Making Queries ******************************************/
|
||||
|
||||
/* query callback routine */
|
||||
typedef void dns_query_fn(struct dns_ctx *ctx, void *result, void *data);
|
||||
|
||||
/* query parse routine: raw DNS => application structure */
|
||||
typedef int
|
||||
dns_parse_fn(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
|
||||
void **res);
|
||||
|
||||
enum dns_status {
|
||||
DNS_E_NOERROR = 0, /* ok, not an error */
|
||||
DNS_E_TEMPFAIL = -1, /* timeout, SERVFAIL or similar */
|
||||
DNS_E_PROTOCOL = -2, /* got garbled reply */
|
||||
DNS_E_NXDOMAIN = -3, /* domain does not exists */
|
||||
DNS_E_NODATA = -4, /* domain exists but no data of reqd type */
|
||||
DNS_E_NOMEM = -5, /* out of memory while processing */
|
||||
DNS_E_BADQUERY = -6 /* the query is malformed */
|
||||
};
|
||||
|
||||
/* submit generic DN query */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_dn(struct dns_ctx *ctx,
|
||||
dnscc_t *dn, int qcls, int qtyp, int flags,
|
||||
dns_parse_fn *parse, dns_query_fn *cbck, void *data);
|
||||
/* submit generic name query */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_p(struct dns_ctx *ctx,
|
||||
const char *name, int qcls, int qtyp, int flags,
|
||||
dns_parse_fn *parse, dns_query_fn *cbck, void *data);
|
||||
|
||||
/* cancel the given async query in progress */
|
||||
UDNS_API int
|
||||
dns_cancel(struct dns_ctx *ctx, struct dns_query *q);
|
||||
|
||||
/* resolve a generic query, return the answer */
|
||||
UDNS_API void *
|
||||
dns_resolve_dn(struct dns_ctx *ctx,
|
||||
dnscc_t *qdn, int qcls, int qtyp, int flags,
|
||||
dns_parse_fn *parse);
|
||||
UDNS_API void *
|
||||
dns_resolve_p(struct dns_ctx *ctx,
|
||||
const char *qname, int qcls, int qtyp, int flags,
|
||||
dns_parse_fn *parse);
|
||||
UDNS_API void *
|
||||
dns_resolve(struct dns_ctx *ctx, struct dns_query *q);
|
||||
|
||||
|
||||
/* Specific RR handlers */
|
||||
|
||||
#define dns_rr_common(prefix) \
|
||||
char *prefix##_cname; /* canonical name */ \
|
||||
char *prefix##_qname; /* original query name */ \
|
||||
unsigned prefix##_ttl; /* TTL value */ \
|
||||
int prefix##_nrr /* number of records */
|
||||
|
||||
struct dns_rr_null { /* NULL RRset, aka RRset template */
|
||||
dns_rr_common(dnsn);
|
||||
};
|
||||
|
||||
UDNS_API int
|
||||
dns_stdrr_size(const struct dns_parse *p);
|
||||
UDNS_API void *
|
||||
dns_stdrr_finish(struct dns_rr_null *ret, char *cp, const struct dns_parse *p);
|
||||
|
||||
struct dns_rr_a4 { /* the A RRset */
|
||||
dns_rr_common(dnsa4);
|
||||
struct in_addr *dnsa4_addr; /* array of addresses, naddr elements */
|
||||
};
|
||||
|
||||
UDNS_API dns_parse_fn dns_parse_a4; /* A RR parsing routine */
|
||||
typedef void /* A query callback routine */
|
||||
dns_query_a4_fn(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data);
|
||||
|
||||
/* submit A IN query */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_a4(struct dns_ctx *ctx, const char *name, int flags,
|
||||
dns_query_a4_fn *cbck, void *data);
|
||||
|
||||
/* resolve A IN query */
|
||||
UDNS_API struct dns_rr_a4 *
|
||||
dns_resolve_a4(struct dns_ctx *ctx, const char *name, int flags);
|
||||
|
||||
|
||||
struct dns_rr_a6 { /* the AAAA RRset */
|
||||
dns_rr_common(dnsa6);
|
||||
struct in6_addr *dnsa6_addr; /* array of addresses, naddr elements */
|
||||
};
|
||||
|
||||
UDNS_API dns_parse_fn dns_parse_a6; /* A RR parsing routine */
|
||||
typedef void /* A query callback routine */
|
||||
dns_query_a6_fn(struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data);
|
||||
|
||||
/* submit AAAA IN query */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_a6(struct dns_ctx *ctx, const char *name, int flags,
|
||||
dns_query_a6_fn *cbck, void *data);
|
||||
|
||||
/* resolve AAAA IN query */
|
||||
UDNS_API struct dns_rr_a6 *
|
||||
dns_resolve_a6(struct dns_ctx *ctx, const char *name, int flags);
|
||||
|
||||
|
||||
struct dns_rr_ptr { /* the PTR RRset */
|
||||
dns_rr_common(dnsptr);
|
||||
char **dnsptr_ptr; /* array of PTRs */
|
||||
};
|
||||
|
||||
UDNS_API dns_parse_fn dns_parse_ptr; /* PTR RR parsing routine */
|
||||
typedef void /* PTR query callback */
|
||||
dns_query_ptr_fn(struct dns_ctx *ctx, struct dns_rr_ptr *result, void *data);
|
||||
/* submit PTR IN in-addr.arpa query */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr,
|
||||
dns_query_ptr_fn *cbck, void *data);
|
||||
/* resolve PTR IN in-addr.arpa query */
|
||||
UDNS_API struct dns_rr_ptr *
|
||||
dns_resolve_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr);
|
||||
|
||||
/* the same as above, but for ip6.arpa */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr,
|
||||
dns_query_ptr_fn *cbck, void *data);
|
||||
UDNS_API struct dns_rr_ptr *
|
||||
dns_resolve_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr);
|
||||
|
||||
|
||||
struct dns_mx { /* single MX RR */
|
||||
int priority; /* MX priority */
|
||||
char *name; /* MX name */
|
||||
};
|
||||
struct dns_rr_mx { /* the MX RRset */
|
||||
dns_rr_common(dnsmx);
|
||||
struct dns_mx *dnsmx_mx; /* array of MXes */
|
||||
};
|
||||
UDNS_API dns_parse_fn dns_parse_mx; /* MX RR parsing routine */
|
||||
typedef void /* MX RR callback */
|
||||
dns_query_mx_fn(struct dns_ctx *ctx, struct dns_rr_mx *result, void *data);
|
||||
/* submit MX IN query */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_mx(struct dns_ctx *ctx, const char *name, int flags,
|
||||
dns_query_mx_fn *cbck, void *data);
|
||||
/* resolve MX IN query */
|
||||
UDNS_API struct dns_rr_mx *
|
||||
dns_resolve_mx(struct dns_ctx *ctx, const char *name, int flags);
|
||||
|
||||
|
||||
struct dns_txt { /* single TXT record */
|
||||
int len; /* length of the text */
|
||||
dnsc_t *txt; /* pointer to text buffer. May contain nulls. */
|
||||
};
|
||||
struct dns_rr_txt { /* the TXT RRset */
|
||||
dns_rr_common(dnstxt);
|
||||
struct dns_txt *dnstxt_txt; /* array of TXT records */
|
||||
};
|
||||
UDNS_API dns_parse_fn dns_parse_txt; /* TXT RR parsing routine */
|
||||
typedef void /* TXT RR callback */
|
||||
dns_query_txt_fn(struct dns_ctx *ctx, struct dns_rr_txt *result, void *data);
|
||||
/* submit TXT query */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags,
|
||||
dns_query_txt_fn *cbck, void *data);
|
||||
/* resolve TXT query */
|
||||
UDNS_API struct dns_rr_txt *
|
||||
dns_resolve_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags);
|
||||
|
||||
|
||||
struct dns_srv { /* single SRV RR */
|
||||
int priority; /* SRV priority */
|
||||
int weight; /* SRV weight */
|
||||
int port; /* SRV port */
|
||||
char *name; /* SRV name */
|
||||
};
|
||||
struct dns_rr_srv { /* the SRV RRset */
|
||||
dns_rr_common(dnssrv);
|
||||
struct dns_srv *dnssrv_srv; /* array of SRVes */
|
||||
};
|
||||
UDNS_API dns_parse_fn dns_parse_srv; /* SRV RR parsing routine */
|
||||
typedef void /* SRV RR callback */
|
||||
dns_query_srv_fn(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data);
|
||||
/* submit SRV IN query */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_srv(struct dns_ctx *ctx,
|
||||
const char *name, const char *srv, const char *proto,
|
||||
int flags, dns_query_srv_fn *cbck, void *data);
|
||||
/* resolve SRV IN query */
|
||||
UDNS_API struct dns_rr_srv *
|
||||
dns_resolve_srv(struct dns_ctx *ctx,
|
||||
const char *name, const char *srv, const char *proto,
|
||||
int flags);
|
||||
|
||||
/* NAPTR (RFC3403) RR type */
|
||||
struct dns_naptr { /* single NAPTR RR */
|
||||
int order; /* NAPTR order */
|
||||
int preference; /* NAPTR preference */
|
||||
char *flags; /* NAPTR flags */
|
||||
char *service; /* NAPTR service */
|
||||
char *regexp; /* NAPTR regexp */
|
||||
char *replacement; /* NAPTR replacement */
|
||||
};
|
||||
|
||||
struct dns_rr_naptr { /* the NAPTR RRset */
|
||||
dns_rr_common(dnsnaptr);
|
||||
struct dns_naptr *dnsnaptr_naptr; /* array of NAPTRes */
|
||||
};
|
||||
UDNS_API dns_parse_fn dns_parse_naptr; /* NAPTR RR parsing routine */
|
||||
typedef void /* NAPTR RR callback */
|
||||
dns_query_naptr_fn(struct dns_ctx *ctx,
|
||||
struct dns_rr_naptr *result, void *data);
|
||||
/* submit NAPTR IN query */
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_naptr(struct dns_ctx *ctx, const char *name, int flags,
|
||||
dns_query_naptr_fn *cbck, void *data);
|
||||
/* resolve NAPTR IN query */
|
||||
UDNS_API struct dns_rr_naptr *
|
||||
dns_resolve_naptr(struct dns_ctx *ctx, const char *name, int flags);
|
||||
|
||||
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_a4dnsbl(struct dns_ctx *ctx,
|
||||
const struct in_addr *addr, const char *dnsbl,
|
||||
dns_query_a4_fn *cbck, void *data);
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_a4dnsbl_txt(struct dns_ctx *ctx,
|
||||
const struct in_addr *addr, const char *dnsbl,
|
||||
dns_query_txt_fn *cbck, void *data);
|
||||
UDNS_API struct dns_rr_a4 *
|
||||
dns_resolve_a4dnsbl(struct dns_ctx *ctx,
|
||||
const struct in_addr *addr, const char *dnsbl);
|
||||
UDNS_API struct dns_rr_txt *
|
||||
dns_resolve_a4dnsbl_txt(struct dns_ctx *ctx,
|
||||
const struct in_addr *addr, const char *dnsbl);
|
||||
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_a6dnsbl(struct dns_ctx *ctx,
|
||||
const struct in6_addr *addr, const char *dnsbl,
|
||||
dns_query_a4_fn *cbck, void *data);
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_a6dnsbl_txt(struct dns_ctx *ctx,
|
||||
const struct in6_addr *addr, const char *dnsbl,
|
||||
dns_query_txt_fn *cbck, void *data);
|
||||
UDNS_API struct dns_rr_a4 *
|
||||
dns_resolve_a6dnsbl(struct dns_ctx *ctx,
|
||||
const struct in6_addr *addr, const char *dnsbl);
|
||||
UDNS_API struct dns_rr_txt *
|
||||
dns_resolve_a6dnsbl_txt(struct dns_ctx *ctx,
|
||||
const struct in6_addr *addr, const char *dnsbl);
|
||||
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_rhsbl(struct dns_ctx *ctx,
|
||||
const char *name, const char *rhsbl,
|
||||
dns_query_a4_fn *cbck, void *data);
|
||||
UDNS_API struct dns_query *
|
||||
dns_submit_rhsbl_txt(struct dns_ctx *ctx,
|
||||
const char *name, const char *rhsbl,
|
||||
dns_query_txt_fn *cbck, void *data);
|
||||
UDNS_API struct dns_rr_a4 *
|
||||
dns_resolve_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl);
|
||||
UDNS_API struct dns_rr_txt *
|
||||
dns_resolve_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl);
|
||||
|
||||
/**************************************************************************/
|
||||
/**************** Names, Names ********************************************/
|
||||
|
||||
struct dns_nameval {
|
||||
int val;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
UDNS_DATA_API extern const struct dns_nameval dns_classtab[];
|
||||
UDNS_DATA_API extern const struct dns_nameval dns_typetab[];
|
||||
UDNS_DATA_API extern const struct dns_nameval dns_rcodetab[];
|
||||
UDNS_API int
|
||||
dns_findname(const struct dns_nameval *nv, const char *name);
|
||||
#define dns_findclassname(cls) dns_findname(dns_classtab, (cls))
|
||||
#define dns_findtypename(type) dns_findname(dns_typetab, (type))
|
||||
#define dns_findrcodename(rcode) dns_findname(dns_rcodetab, (rcode))
|
||||
|
||||
UDNS_API const char *dns_classname(enum dns_class cls);
|
||||
UDNS_API const char *dns_typename(enum dns_type type);
|
||||
UDNS_API const char *dns_rcodename(enum dns_rcode rcode);
|
||||
const char *_dns_format_code(char *buf, const char *prefix, int code);
|
||||
|
||||
UDNS_API const char *dns_strerror(int errnum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* include guard */
|
||||
@@ -1,160 +0,0 @@
|
||||
/* $Id: udns_bl.c,v 1.10 2005/09/12 10:55:21 mjt Exp $
|
||||
DNSBL stuff
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "udns.h"
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_a4dnsbl(struct dns_ctx *ctx,
|
||||
const struct in_addr *addr, const char *dnsbl,
|
||||
dns_query_a4_fn *cbck, void *data) {
|
||||
dnsc_t dn[DNS_MAXDN];
|
||||
if (dns_a4ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) {
|
||||
dns_setstatus(ctx, DNS_E_BADQUERY);
|
||||
return NULL;
|
||||
}
|
||||
return
|
||||
dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_A, DNS_NOSRCH,
|
||||
dns_parse_a4, (dns_query_fn*)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_a4dnsbl_txt(struct dns_ctx *ctx,
|
||||
const struct in_addr *addr, const char *dnsbl,
|
||||
dns_query_txt_fn *cbck, void *data) {
|
||||
dnsc_t dn[DNS_MAXDN];
|
||||
if (dns_a4ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) {
|
||||
dns_setstatus(ctx, DNS_E_BADQUERY);
|
||||
return NULL;
|
||||
}
|
||||
return
|
||||
dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_TXT, DNS_NOSRCH,
|
||||
dns_parse_txt, (dns_query_fn*)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_a4 *
|
||||
dns_resolve_a4dnsbl(struct dns_ctx *ctx,
|
||||
const struct in_addr *addr, const char *dnsbl) {
|
||||
return (struct dns_rr_a4 *)
|
||||
dns_resolve(ctx, dns_submit_a4dnsbl(ctx, addr, dnsbl, 0, 0));
|
||||
}
|
||||
|
||||
struct dns_rr_txt *
|
||||
dns_resolve_a4dnsbl_txt(struct dns_ctx *ctx,
|
||||
const struct in_addr *addr, const char *dnsbl) {
|
||||
return (struct dns_rr_txt *)
|
||||
dns_resolve(ctx, dns_submit_a4dnsbl_txt(ctx, addr, dnsbl, 0, 0));
|
||||
}
|
||||
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_a6dnsbl(struct dns_ctx *ctx,
|
||||
const struct in6_addr *addr, const char *dnsbl,
|
||||
dns_query_a4_fn *cbck, void *data) {
|
||||
dnsc_t dn[DNS_MAXDN];
|
||||
if (dns_a6ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) {
|
||||
dns_setstatus(ctx, DNS_E_BADQUERY);
|
||||
return NULL;
|
||||
}
|
||||
return
|
||||
dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_A, DNS_NOSRCH,
|
||||
dns_parse_a4, (dns_query_fn*)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_a6dnsbl_txt(struct dns_ctx *ctx,
|
||||
const struct in6_addr *addr, const char *dnsbl,
|
||||
dns_query_txt_fn *cbck, void *data) {
|
||||
dnsc_t dn[DNS_MAXDN];
|
||||
if (dns_a6ptodn(addr, dnsbl, dn, sizeof(dn)) <= 0) {
|
||||
dns_setstatus(ctx, DNS_E_BADQUERY);
|
||||
return NULL;
|
||||
}
|
||||
return
|
||||
dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_TXT, DNS_NOSRCH,
|
||||
dns_parse_txt, (dns_query_fn*)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_a4 *
|
||||
dns_resolve_a6dnsbl(struct dns_ctx *ctx,
|
||||
const struct in6_addr *addr, const char *dnsbl) {
|
||||
return (struct dns_rr_a4 *)
|
||||
dns_resolve(ctx, dns_submit_a6dnsbl(ctx, addr, dnsbl, 0, 0));
|
||||
}
|
||||
|
||||
struct dns_rr_txt *
|
||||
dns_resolve_a6dnsbl_txt(struct dns_ctx *ctx,
|
||||
const struct in6_addr *addr, const char *dnsbl) {
|
||||
return (struct dns_rr_txt *)
|
||||
dns_resolve(ctx, dns_submit_a6dnsbl_txt(ctx, addr, dnsbl, 0, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
dns_rhsbltodn(const char *name, const char *rhsbl, dnsc_t dn[DNS_MAXDN])
|
||||
{
|
||||
int l = dns_sptodn(name, dn, DNS_MAXDN);
|
||||
if (l <= 0) return 0;
|
||||
l = dns_sptodn(rhsbl, dn+l-1, DNS_MAXDN-l+1);
|
||||
if (l <= 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl,
|
||||
dns_query_a4_fn *cbck, void *data) {
|
||||
dnsc_t dn[DNS_MAXDN];
|
||||
if (!dns_rhsbltodn(name, rhsbl, dn)) {
|
||||
dns_setstatus(ctx, DNS_E_BADQUERY);
|
||||
return NULL;
|
||||
}
|
||||
return
|
||||
dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_A, DNS_NOSRCH,
|
||||
dns_parse_a4, (dns_query_fn*)cbck, data);
|
||||
}
|
||||
struct dns_query *
|
||||
dns_submit_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl,
|
||||
dns_query_txt_fn *cbck, void *data) {
|
||||
dnsc_t dn[DNS_MAXDN];
|
||||
if (!dns_rhsbltodn(name, rhsbl, dn)) {
|
||||
dns_setstatus(ctx, DNS_E_BADQUERY);
|
||||
return NULL;
|
||||
}
|
||||
return
|
||||
dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_TXT, DNS_NOSRCH,
|
||||
dns_parse_txt, (dns_query_fn*)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_a4 *
|
||||
dns_resolve_rhsbl(struct dns_ctx *ctx, const char *name, const char *rhsbl) {
|
||||
return (struct dns_rr_a4*)
|
||||
dns_resolve(ctx, dns_submit_rhsbl(ctx, name, rhsbl, 0, 0));
|
||||
}
|
||||
|
||||
struct dns_rr_txt *
|
||||
dns_resolve_rhsbl_txt(struct dns_ctx *ctx, const char *name, const char *rhsbl)
|
||||
{
|
||||
return (struct dns_rr_txt*)
|
||||
dns_resolve(ctx, dns_submit_rhsbl_txt(ctx, name, rhsbl, 0, 0));
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
/* Automatically generated. */
|
||||
#include "udns.h"
|
||||
|
||||
const struct dns_nameval dns_typetab[] = {
|
||||
{DNS_T_INVALID,"INVALID"},
|
||||
{DNS_T_A,"A"},
|
||||
{DNS_T_NS,"NS"},
|
||||
{DNS_T_MD,"MD"},
|
||||
{DNS_T_MF,"MF"},
|
||||
{DNS_T_CNAME,"CNAME"},
|
||||
{DNS_T_SOA,"SOA"},
|
||||
{DNS_T_MB,"MB"},
|
||||
{DNS_T_MG,"MG"},
|
||||
{DNS_T_MR,"MR"},
|
||||
{DNS_T_NULL,"NULL"},
|
||||
{DNS_T_WKS,"WKS"},
|
||||
{DNS_T_PTR,"PTR"},
|
||||
{DNS_T_HINFO,"HINFO"},
|
||||
{DNS_T_MINFO,"MINFO"},
|
||||
{DNS_T_MX,"MX"},
|
||||
{DNS_T_TXT,"TXT"},
|
||||
{DNS_T_RP,"RP"},
|
||||
{DNS_T_AFSDB,"AFSDB"},
|
||||
{DNS_T_X25,"X25"},
|
||||
{DNS_T_ISDN,"ISDN"},
|
||||
{DNS_T_RT,"RT"},
|
||||
{DNS_T_NSAP,"NSAP"},
|
||||
{DNS_T_NSAP_PTR,"NSAP_PTR"},
|
||||
{DNS_T_SIG,"SIG"},
|
||||
{DNS_T_KEY,"KEY"},
|
||||
{DNS_T_PX,"PX"},
|
||||
{DNS_T_GPOS,"GPOS"},
|
||||
{DNS_T_AAAA,"AAAA"},
|
||||
{DNS_T_LOC,"LOC"},
|
||||
{DNS_T_NXT,"NXT"},
|
||||
{DNS_T_EID,"EID"},
|
||||
{DNS_T_NIMLOC,"NIMLOC"},
|
||||
{DNS_T_SRV,"SRV"},
|
||||
{DNS_T_ATMA,"ATMA"},
|
||||
{DNS_T_NAPTR,"NAPTR"},
|
||||
{DNS_T_KX,"KX"},
|
||||
{DNS_T_CERT,"CERT"},
|
||||
{DNS_T_A6,"A6"},
|
||||
{DNS_T_DNAME,"DNAME"},
|
||||
{DNS_T_SINK,"SINK"},
|
||||
{DNS_T_OPT,"OPT"},
|
||||
{DNS_T_DS,"DS"},
|
||||
{DNS_T_NSEC,"NSEC"},
|
||||
{DNS_T_TSIG,"TSIG"},
|
||||
{DNS_T_IXFR,"IXFR"},
|
||||
{DNS_T_AXFR,"AXFR"},
|
||||
{DNS_T_MAILB,"MAILB"},
|
||||
{DNS_T_MAILA,"MAILA"},
|
||||
{DNS_T_ANY,"ANY"},
|
||||
{DNS_T_ZXFR,"ZXFR"},
|
||||
{DNS_T_MAX,"MAX"},
|
||||
{0,0}};
|
||||
const char *dns_typename(enum dns_type code) {
|
||||
static char nm[20];
|
||||
switch(code) {
|
||||
case DNS_T_INVALID: return dns_typetab[0].name;
|
||||
case DNS_T_A: return dns_typetab[1].name;
|
||||
case DNS_T_NS: return dns_typetab[2].name;
|
||||
case DNS_T_MD: return dns_typetab[3].name;
|
||||
case DNS_T_MF: return dns_typetab[4].name;
|
||||
case DNS_T_CNAME: return dns_typetab[5].name;
|
||||
case DNS_T_SOA: return dns_typetab[6].name;
|
||||
case DNS_T_MB: return dns_typetab[7].name;
|
||||
case DNS_T_MG: return dns_typetab[8].name;
|
||||
case DNS_T_MR: return dns_typetab[9].name;
|
||||
case DNS_T_NULL: return dns_typetab[10].name;
|
||||
case DNS_T_WKS: return dns_typetab[11].name;
|
||||
case DNS_T_PTR: return dns_typetab[12].name;
|
||||
case DNS_T_HINFO: return dns_typetab[13].name;
|
||||
case DNS_T_MINFO: return dns_typetab[14].name;
|
||||
case DNS_T_MX: return dns_typetab[15].name;
|
||||
case DNS_T_TXT: return dns_typetab[16].name;
|
||||
case DNS_T_RP: return dns_typetab[17].name;
|
||||
case DNS_T_AFSDB: return dns_typetab[18].name;
|
||||
case DNS_T_X25: return dns_typetab[19].name;
|
||||
case DNS_T_ISDN: return dns_typetab[20].name;
|
||||
case DNS_T_RT: return dns_typetab[21].name;
|
||||
case DNS_T_NSAP: return dns_typetab[22].name;
|
||||
case DNS_T_NSAP_PTR: return dns_typetab[23].name;
|
||||
case DNS_T_SIG: return dns_typetab[24].name;
|
||||
case DNS_T_KEY: return dns_typetab[25].name;
|
||||
case DNS_T_PX: return dns_typetab[26].name;
|
||||
case DNS_T_GPOS: return dns_typetab[27].name;
|
||||
case DNS_T_AAAA: return dns_typetab[28].name;
|
||||
case DNS_T_LOC: return dns_typetab[29].name;
|
||||
case DNS_T_NXT: return dns_typetab[30].name;
|
||||
case DNS_T_EID: return dns_typetab[31].name;
|
||||
case DNS_T_NIMLOC: return dns_typetab[32].name;
|
||||
case DNS_T_SRV: return dns_typetab[33].name;
|
||||
case DNS_T_ATMA: return dns_typetab[34].name;
|
||||
case DNS_T_NAPTR: return dns_typetab[35].name;
|
||||
case DNS_T_KX: return dns_typetab[36].name;
|
||||
case DNS_T_CERT: return dns_typetab[37].name;
|
||||
case DNS_T_A6: return dns_typetab[38].name;
|
||||
case DNS_T_DNAME: return dns_typetab[39].name;
|
||||
case DNS_T_SINK: return dns_typetab[40].name;
|
||||
case DNS_T_OPT: return dns_typetab[41].name;
|
||||
case DNS_T_DS: return dns_typetab[42].name;
|
||||
case DNS_T_NSEC: return dns_typetab[43].name;
|
||||
case DNS_T_TSIG: return dns_typetab[44].name;
|
||||
case DNS_T_IXFR: return dns_typetab[45].name;
|
||||
case DNS_T_AXFR: return dns_typetab[46].name;
|
||||
case DNS_T_MAILB: return dns_typetab[47].name;
|
||||
case DNS_T_MAILA: return dns_typetab[48].name;
|
||||
case DNS_T_ANY: return dns_typetab[49].name;
|
||||
case DNS_T_ZXFR: return dns_typetab[50].name;
|
||||
case DNS_T_MAX: return dns_typetab[51].name;
|
||||
}
|
||||
return _dns_format_code(nm,"type",code);
|
||||
}
|
||||
|
||||
const struct dns_nameval dns_classtab[] = {
|
||||
{DNS_C_INVALID,"INVALID"},
|
||||
{DNS_C_IN,"IN"},
|
||||
{DNS_C_CH,"CH"},
|
||||
{DNS_C_HS,"HS"},
|
||||
{DNS_C_ANY,"ANY"},
|
||||
{0,0}};
|
||||
const char *dns_classname(enum dns_class code) {
|
||||
static char nm[20];
|
||||
switch(code) {
|
||||
case DNS_C_INVALID: return dns_classtab[0].name;
|
||||
case DNS_C_IN: return dns_classtab[1].name;
|
||||
case DNS_C_CH: return dns_classtab[2].name;
|
||||
case DNS_C_HS: return dns_classtab[3].name;
|
||||
case DNS_C_ANY: return dns_classtab[4].name;
|
||||
}
|
||||
return _dns_format_code(nm,"class",code);
|
||||
}
|
||||
|
||||
const struct dns_nameval dns_rcodetab[] = {
|
||||
{DNS_R_NOERROR,"NOERROR"},
|
||||
{DNS_R_FORMERR,"FORMERR"},
|
||||
{DNS_R_SERVFAIL,"SERVFAIL"},
|
||||
{DNS_R_NXDOMAIN,"NXDOMAIN"},
|
||||
{DNS_R_NOTIMPL,"NOTIMPL"},
|
||||
{DNS_R_REFUSED,"REFUSED"},
|
||||
{DNS_R_YXDOMAIN,"YXDOMAIN"},
|
||||
{DNS_R_YXRRSET,"YXRRSET"},
|
||||
{DNS_R_NXRRSET,"NXRRSET"},
|
||||
{DNS_R_NOTAUTH,"NOTAUTH"},
|
||||
{DNS_R_NOTZONE,"NOTZONE"},
|
||||
{DNS_R_BADSIG,"BADSIG"},
|
||||
{DNS_R_BADKEY,"BADKEY"},
|
||||
{DNS_R_BADTIME,"BADTIME"},
|
||||
{0,0}};
|
||||
const char *dns_rcodename(enum dns_rcode code) {
|
||||
static char nm[20];
|
||||
switch(code) {
|
||||
case DNS_R_NOERROR: return dns_rcodetab[0].name;
|
||||
case DNS_R_FORMERR: return dns_rcodetab[1].name;
|
||||
case DNS_R_SERVFAIL: return dns_rcodetab[2].name;
|
||||
case DNS_R_NXDOMAIN: return dns_rcodetab[3].name;
|
||||
case DNS_R_NOTIMPL: return dns_rcodetab[4].name;
|
||||
case DNS_R_REFUSED: return dns_rcodetab[5].name;
|
||||
case DNS_R_YXDOMAIN: return dns_rcodetab[6].name;
|
||||
case DNS_R_YXRRSET: return dns_rcodetab[7].name;
|
||||
case DNS_R_NXRRSET: return dns_rcodetab[8].name;
|
||||
case DNS_R_NOTAUTH: return dns_rcodetab[9].name;
|
||||
case DNS_R_NOTZONE: return dns_rcodetab[10].name;
|
||||
case DNS_R_BADSIG: return dns_rcodetab[11].name;
|
||||
case DNS_R_BADKEY: return dns_rcodetab[12].name;
|
||||
case DNS_R_BADTIME: return dns_rcodetab[13].name;
|
||||
}
|
||||
return _dns_format_code(nm,"rcode",code);
|
||||
}
|
||||
@@ -1,382 +0,0 @@
|
||||
/* $Id: udns_dn.c,v 1.7 2006/11/28 22:45:20 mjt Exp $
|
||||
domain names manipulation routines
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "udns.h"
|
||||
|
||||
unsigned dns_dnlen(dnscc_t *dn) {
|
||||
register dnscc_t *d = dn;
|
||||
while(*d)
|
||||
d += 1 + *d;
|
||||
return (unsigned)(d - dn) + 1;
|
||||
}
|
||||
|
||||
unsigned dns_dnlabels(register dnscc_t *dn) {
|
||||
register unsigned l = 0;
|
||||
while(*dn)
|
||||
++l, dn += 1 + *dn;
|
||||
return l;
|
||||
}
|
||||
|
||||
unsigned dns_dnequal(register dnscc_t *dn1, register dnscc_t *dn2) {
|
||||
register unsigned c;
|
||||
dnscc_t *dn = dn1;
|
||||
for(;;) {
|
||||
if ((c = *dn1++) != *dn2++)
|
||||
return 0;
|
||||
if (!c)
|
||||
return (unsigned)(dn1 - dn);
|
||||
while(c--) {
|
||||
if (DNS_DNLC(*dn1) != DNS_DNLC(*dn2))
|
||||
return 0;
|
||||
++dn1; ++dn2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
dns_dntodn(dnscc_t *sdn, dnsc_t *ddn, unsigned ddnsiz) {
|
||||
unsigned sdnlen = dns_dnlen(sdn);
|
||||
if (ddnsiz < sdnlen)
|
||||
return 0;
|
||||
memcpy(ddn, sdn, sdnlen);
|
||||
return sdnlen;
|
||||
}
|
||||
|
||||
int
|
||||
dns_ptodn(const char *name, unsigned namelen,
|
||||
dnsc_t *dn, unsigned dnsiz, int *isabs)
|
||||
{
|
||||
dnsc_t *dp; /* current position in dn (len byte first) */
|
||||
dnsc_t *const de /* end of dn: last byte that can be filled up */
|
||||
= dn + (dnsiz >= DNS_MAXDN ? DNS_MAXDN : dnsiz) - 1;
|
||||
dnscc_t *np = (dnscc_t *)name;
|
||||
dnscc_t *ne = np + (namelen ? namelen : strlen((char*)np));
|
||||
dnsc_t *llab; /* start of last label (llab[-1] will be length) */
|
||||
unsigned c; /* next input character, or length of last label */
|
||||
|
||||
if (!dnsiz)
|
||||
return 0;
|
||||
dp = llab = dn + 1;
|
||||
|
||||
while(np < ne) {
|
||||
|
||||
if (*np == '.') { /* label delimiter */
|
||||
c = (unsigned)(dp - llab); /* length of the label */
|
||||
if (!c) { /* empty label */
|
||||
if (np == (dnscc_t *)name && np + 1 == ne) {
|
||||
/* special case for root dn, aka `.' */
|
||||
++np;
|
||||
break;
|
||||
}
|
||||
return -1; /* zero label */
|
||||
}
|
||||
if (c > DNS_MAXLABEL)
|
||||
return -1; /* label too long */
|
||||
llab[-1] = (dnsc_t)c; /* update len of last label */
|
||||
llab = ++dp; /* start new label, llab[-1] will be len of it */
|
||||
++np;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check whenever we may put out one more byte */
|
||||
if (dp >= de) /* too long? */
|
||||
return dnsiz >= DNS_MAXDN ? -1 : 0;
|
||||
if (*np != '\\') { /* non-escape, simple case */
|
||||
*dp++ = *np++;
|
||||
continue;
|
||||
}
|
||||
/* handle \-style escape */
|
||||
/* note that traditionally, domain names (gethostbyname etc)
|
||||
* used decimal \dd notation, not octal \ooo (RFC1035), so
|
||||
* we're following this tradition here.
|
||||
*/
|
||||
if (++np == ne)
|
||||
return -1; /* bad escape */
|
||||
else if (*np >= '0' && *np <= '9') { /* decimal number */
|
||||
/* we allow not only exactly 3 digits as per RFC1035,
|
||||
* but also 2 or 1, for better usability. */
|
||||
c = *np++ - '0';
|
||||
if (np < ne && *np >= '0' && *np <= '9') { /* 2digits */
|
||||
c = c * 10 + *np++ - '0';
|
||||
if (np < ne && *np >= '0' && *np <= '9') {
|
||||
c = c * 10 + *np++ - '0';
|
||||
if (c > 255)
|
||||
return -1; /* bad escape */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
c = *np++;
|
||||
*dp++ = (dnsc_t)c; /* place next out byte */
|
||||
}
|
||||
|
||||
if ((c = (unsigned)(dp - llab)) > DNS_MAXLABEL)
|
||||
return -1; /* label too long */
|
||||
if ((llab[-1] = (dnsc_t)c) != 0) {
|
||||
*dp++ = 0;
|
||||
if (isabs)
|
||||
*isabs = 0;
|
||||
}
|
||||
else if (isabs)
|
||||
*isabs = 1;
|
||||
|
||||
return (int)(dp - dn);
|
||||
}
|
||||
|
||||
dnscc_t dns_inaddr_arpa_dn[14] = "\07in-addr\04arpa";
|
||||
|
||||
dnsc_t *
|
||||
dns_a4todn_(const struct in_addr *addr, dnsc_t *dn, dnsc_t *dne) {
|
||||
dnsc_t *p;
|
||||
unsigned n;
|
||||
dnscc_t *s = ((dnscc_t *)addr) + 4;
|
||||
while(--s >= (dnscc_t *)addr) {
|
||||
n = *s;
|
||||
p = dn + 1;
|
||||
if (n > 99) {
|
||||
if (p + 2 > dne) return 0;
|
||||
*p++ = n / 100 + '0';
|
||||
*p++ = (n % 100 / 10) + '0';
|
||||
*p = n % 10 + '0';
|
||||
}
|
||||
else if (n > 9) {
|
||||
if (p + 1 > dne) return 0;
|
||||
*p++ = n / 10 + '0';
|
||||
*p = n % 10 + '0';
|
||||
}
|
||||
else {
|
||||
if (p > dne) return 0;
|
||||
*p = n + '0';
|
||||
}
|
||||
*dn = (dnsc_t)(p - dn);
|
||||
dn = p + 1;
|
||||
}
|
||||
return dn;
|
||||
}
|
||||
|
||||
int dns_a4todn(const struct in_addr *addr, dnscc_t *tdn,
|
||||
dnsc_t *dn, unsigned dnsiz) {
|
||||
dnsc_t *dne = dn + (dnsiz > DNS_MAXDN ? DNS_MAXDN : dnsiz);
|
||||
dnsc_t *p;
|
||||
unsigned l;
|
||||
p = dns_a4todn_(addr, dn, dne);
|
||||
if (!p) return 0;
|
||||
if (!tdn)
|
||||
tdn = dns_inaddr_arpa_dn;
|
||||
l = dns_dnlen(tdn);
|
||||
if (p + l > dne) return dnsiz >= DNS_MAXDN ? -1 : 0;
|
||||
memcpy(p, tdn, l);
|
||||
return (int)((p + l) - dn);
|
||||
}
|
||||
|
||||
int dns_a4ptodn(const struct in_addr *addr, const char *tname,
|
||||
dnsc_t *dn, unsigned dnsiz) {
|
||||
dnsc_t *p;
|
||||
int r;
|
||||
if (!tname)
|
||||
return dns_a4todn(addr, NULL, dn, dnsiz);
|
||||
p = dns_a4todn_(addr, dn, dn + dnsiz);
|
||||
if (!p) return 0;
|
||||
r = dns_sptodn(tname, p, dnsiz - (p - dn));
|
||||
return r != 0 ? r : dnsiz >= DNS_MAXDN ? -1 : 0;
|
||||
}
|
||||
|
||||
dnscc_t dns_ip6_arpa_dn[10] = "\03ip6\04arpa";
|
||||
|
||||
dnsc_t *
|
||||
dns_a6todn_(const struct in6_addr *addr, dnsc_t *dn, dnsc_t *dne) {
|
||||
unsigned n;
|
||||
dnscc_t *s = ((dnscc_t *)addr) + 16;
|
||||
if (dn + 64 > dne) return 0;
|
||||
while(--s >= (dnscc_t *)addr) {
|
||||
*dn++ = 1;
|
||||
n = *s & 0x0f;
|
||||
*dn++ = n > 9 ? n + 'a' - 10 : n + '0';
|
||||
*dn++ = 1;
|
||||
n = *s >> 4;
|
||||
*dn++ = n > 9 ? n + 'a' - 10 : n + '0';
|
||||
}
|
||||
return dn;
|
||||
}
|
||||
|
||||
int dns_a6todn(const struct in6_addr *addr, dnscc_t *tdn,
|
||||
dnsc_t *dn, unsigned dnsiz) {
|
||||
dnsc_t *dne = dn + (dnsiz > DNS_MAXDN ? DNS_MAXDN : dnsiz);
|
||||
dnsc_t *p;
|
||||
unsigned l;
|
||||
p = dns_a6todn_(addr, dn, dne);
|
||||
if (!p) return 0;
|
||||
if (!tdn)
|
||||
tdn = dns_ip6_arpa_dn;
|
||||
l = dns_dnlen(tdn);
|
||||
if (p + l > dne) return dnsiz >= DNS_MAXDN ? -1 : 0;
|
||||
memcpy(p, tdn, l);
|
||||
return (int)((p + l) - dn);
|
||||
}
|
||||
|
||||
int dns_a6ptodn(const struct in6_addr *addr, const char *tname,
|
||||
dnsc_t *dn, unsigned dnsiz) {
|
||||
dnsc_t *p;
|
||||
int r;
|
||||
if (!tname)
|
||||
return dns_a6todn(addr, NULL, dn, dnsiz);
|
||||
p = dns_a6todn_(addr, dn, dn + dnsiz);
|
||||
if (!p) return 0;
|
||||
r = dns_sptodn(tname, p, dnsiz - (p - dn));
|
||||
return r != 0 ? r : dnsiz >= DNS_MAXDN ? -1 : 0;
|
||||
}
|
||||
|
||||
/* return size of buffer required to convert the dn into asciiz string.
|
||||
* Keep in sync with dns_dntop() below.
|
||||
*/
|
||||
unsigned dns_dntop_size(dnscc_t *dn) {
|
||||
unsigned size = 0; /* the size reqd */
|
||||
dnscc_t *le; /* label end */
|
||||
|
||||
while(*dn) {
|
||||
/* *dn is the length of the next label, non-zero */
|
||||
if (size)
|
||||
++size; /* for the dot */
|
||||
le = dn + *dn + 1;
|
||||
++dn;
|
||||
do {
|
||||
switch(*dn) {
|
||||
case '.':
|
||||
case '\\':
|
||||
/* Special modifiers in zone files. */
|
||||
case '"':
|
||||
case ';':
|
||||
case '@':
|
||||
case '$':
|
||||
size += 2;
|
||||
break;
|
||||
default:
|
||||
if (*dn <= 0x20 || *dn >= 0x7f)
|
||||
/* \ddd decimal notation */
|
||||
size += 4;
|
||||
else
|
||||
size += 1;
|
||||
}
|
||||
} while(++dn < le);
|
||||
}
|
||||
size += 1; /* zero byte at the end - string terminator */
|
||||
return size > DNS_MAXNAME ? 0 : size;
|
||||
}
|
||||
|
||||
/* Convert the dn into asciiz string.
|
||||
* Keep in sync with dns_dntop_size() above.
|
||||
*/
|
||||
int dns_dntop(dnscc_t *dn, char *name, unsigned namesiz) {
|
||||
char *np = name; /* current name ptr */
|
||||
char *const ne = name + namesiz; /* end of name */
|
||||
dnscc_t *le; /* label end */
|
||||
|
||||
while(*dn) {
|
||||
/* *dn is the length of the next label, non-zero */
|
||||
if (np != name) {
|
||||
if (np >= ne) goto toolong;
|
||||
*np++ = '.';
|
||||
}
|
||||
le = dn + *dn + 1;
|
||||
++dn;
|
||||
do {
|
||||
switch(*dn) {
|
||||
case '.':
|
||||
case '\\':
|
||||
/* Special modifiers in zone files. */
|
||||
case '"':
|
||||
case ';':
|
||||
case '@':
|
||||
case '$':
|
||||
if (np + 2 > ne) goto toolong;
|
||||
*np++ = '\\';
|
||||
*np++ = *dn;
|
||||
break;
|
||||
default:
|
||||
if (*dn <= 0x20 || *dn >= 0x7f) {
|
||||
/* \ddd decimal notation */
|
||||
if (np + 4 >= ne) goto toolong;
|
||||
*np++ = '\\';
|
||||
*np++ = '0' + (*dn / 100);
|
||||
*np++ = '0' + ((*dn % 100) / 10);
|
||||
*np++ = '0' + (*dn % 10);
|
||||
}
|
||||
else {
|
||||
if (np >= ne) goto toolong;
|
||||
*np++ = *dn;
|
||||
}
|
||||
}
|
||||
} while(++dn < le);
|
||||
}
|
||||
if (np >= ne) goto toolong;
|
||||
*np++ = '\0';
|
||||
return (int)(np - name);
|
||||
toolong:
|
||||
return namesiz >= DNS_MAXNAME ? -1 : 0;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
int sz;
|
||||
dnsc_t dn[DNS_MAXDN+10];
|
||||
dnsc_t *dl, *dp;
|
||||
int isabs;
|
||||
|
||||
sz = (argc > 1) ? atoi(argv[1]) : 0;
|
||||
|
||||
for(i = 2; i < argc; ++i) {
|
||||
int r = dns_ptodn(argv[i], 0, dn, sz, &isabs);
|
||||
printf("%s: ", argv[i]);
|
||||
if (r < 0) printf("error\n");
|
||||
else if (!r) printf("buffer too small\n");
|
||||
else {
|
||||
printf("len=%d dnlen=%d size=%d name:",
|
||||
r, dns_dnlen(dn), dns_dntop_size(dn));
|
||||
dl = dn;
|
||||
while(*dl) {
|
||||
printf(" %d=", *dl);
|
||||
dp = dl + 1;
|
||||
dl = dp + *dl;
|
||||
while(dp < dl) {
|
||||
if (*dp <= ' ' || *dp >= 0x7f)
|
||||
printf("\\%03d", *dp);
|
||||
else if (*dp == '.' || *dp == '\\')
|
||||
printf("\\%c", *dp);
|
||||
else
|
||||
putchar(*dp);
|
||||
++dp;
|
||||
}
|
||||
}
|
||||
if (isabs) putchar('.');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
||||
@@ -1,30 +0,0 @@
|
||||
/* $Id: udns_dntosp.c,v 1.5 2005/04/19 21:48:09 mjt Exp $
|
||||
dns_dntosp() = convert DN to asciiz string using static buffer
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "udns.h"
|
||||
|
||||
static char name[DNS_MAXNAME];
|
||||
|
||||
const char *dns_dntosp(dnscc_t *dn) {
|
||||
return dns_dntop(dn, name, sizeof(name)) > 0 ? name : 0;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/* $Id: udns_misc.c,v 1.8 2005/04/05 22:51:32 mjt Exp $
|
||||
miscellaneous routines
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "udns.h"
|
||||
|
||||
int dns_findname(const struct dns_nameval *nv, const char *name) {
|
||||
register const char *a, *b;
|
||||
for(; nv->name; ++nv)
|
||||
for(a = name, b = nv->name; ; ++a, ++b)
|
||||
if (DNS_DNUC(*a) != *b) break;
|
||||
else if (!*a) return nv->val;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *_dns_format_code(char *buf, const char *prefix, int code) {
|
||||
char *bp = buf;
|
||||
unsigned c, n;
|
||||
do *bp++ = DNS_DNUC(*prefix);
|
||||
while(*++prefix);
|
||||
*bp++ = '#';
|
||||
if (code < 0) code = -code, *bp++ = '-';
|
||||
n = 0; c = code;
|
||||
do ++n;
|
||||
while((c /= 10));
|
||||
c = code;
|
||||
bp[n--] = '\0';
|
||||
do bp[n--] = c % 10 + '0';
|
||||
while((c /= 10));
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *dns_strerror(int err) {
|
||||
if (err >= 0) return "successeful completion";
|
||||
switch(err) {
|
||||
case DNS_E_TEMPFAIL: return "temporary failure in name resolution";
|
||||
case DNS_E_PROTOCOL: return "protocol error";
|
||||
case DNS_E_NXDOMAIN: return "domain name does not exist";
|
||||
case DNS_E_NODATA: return "valid domain but no data of requested type";
|
||||
case DNS_E_NOMEM: return "out of memory";
|
||||
case DNS_E_BADQUERY: return "malformed query";
|
||||
default: return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
const char *dns_version(void) {
|
||||
return UDNS_VERSION;
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/* $Id: udns_parse.c,v 1.14 2005/09/12 10:55:21 mjt Exp $
|
||||
raw DNS packet parsing routines
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "udns.h"
|
||||
|
||||
dnscc_t *dns_skipdn(dnscc_t *cur, dnscc_t *end) {
|
||||
unsigned c;
|
||||
for(;;) {
|
||||
if (cur >= end)
|
||||
return NULL;
|
||||
c = *cur++;
|
||||
if (!c)
|
||||
return cur;
|
||||
if (c & 192) /* jump */
|
||||
return cur + 1 >= end ? NULL : cur + 1;
|
||||
cur += c;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dns_getdn(dnscc_t *pkt, dnscc_t **cur, dnscc_t *end,
|
||||
register dnsc_t *dn, unsigned dnsiz) {
|
||||
unsigned c;
|
||||
dnscc_t *pp = *cur; /* current packet pointer */
|
||||
dnsc_t *dp = dn; /* current dn pointer */
|
||||
dnsc_t *const de /* end of the DN dest */
|
||||
= dn + (dnsiz < DNS_MAXDN ? dnsiz : DNS_MAXDN);
|
||||
dnscc_t *jump = NULL; /* ptr after first jump if any */
|
||||
unsigned loop = 100; /* jump loop counter */
|
||||
|
||||
for(;;) { /* loop by labels */
|
||||
if (pp >= end) /* reached end of packet? */
|
||||
return -1;
|
||||
c = *pp++; /* length of the label */
|
||||
if (!c) { /* empty label: terminate */
|
||||
if (dn >= de) /* can't fit terminator */
|
||||
goto noroom;
|
||||
*dp++ = 0;
|
||||
/* return next pos: either after the first jump or current */
|
||||
*cur = jump ? jump : pp;
|
||||
return (int)(dp - dn);
|
||||
}
|
||||
if (c & 192) { /* jump */
|
||||
if (pp >= end) /* eop instead of jump pos */
|
||||
return -1;
|
||||
if (!jump) jump = pp + 1; /* remember first jump */
|
||||
else if (!--loop) return -1; /* too many jumps */
|
||||
c = ((c & ~192) << 8) | *pp; /* new pos */
|
||||
if (c < DNS_HSIZE) /* don't allow jump into the header */
|
||||
return -1;
|
||||
pp = pkt + c;
|
||||
continue;
|
||||
}
|
||||
if (c > DNS_MAXLABEL) /* too long label? */
|
||||
return -1;
|
||||
if (pp + c > end) /* label does not fit in packet? */
|
||||
return -1;
|
||||
if (dp + c + 1 > de) /* if enouth room for the label */
|
||||
goto noroom;
|
||||
*dp++ = c; /* label length */
|
||||
memcpy(dp, pp, c); /* and the label itself */
|
||||
dp += c;
|
||||
pp += c; /* advance to the next label */
|
||||
}
|
||||
noroom:
|
||||
return dnsiz < DNS_MAXDN ? 0 : -1;
|
||||
}
|
||||
|
||||
void dns_rewind(struct dns_parse *p, dnscc_t *qdn) {
|
||||
p->dnsp_qdn = qdn;
|
||||
p->dnsp_cur = p->dnsp_ans;
|
||||
p->dnsp_rrl = dns_numan(p->dnsp_pkt);
|
||||
p->dnsp_ttl = 0xffffffffu;
|
||||
p->dnsp_nrr = 0;
|
||||
}
|
||||
|
||||
void
|
||||
dns_initparse(struct dns_parse *p, dnscc_t *qdn,
|
||||
dnscc_t *pkt, dnscc_t *cur, dnscc_t *end) {
|
||||
p->dnsp_pkt = pkt;
|
||||
p->dnsp_end = end;
|
||||
p->dnsp_rrl = dns_numan(pkt);
|
||||
p->dnsp_qdn = qdn;
|
||||
assert(cur + 4 <= end);
|
||||
if ((p->dnsp_qtyp = dns_get16(cur+0)) == DNS_T_ANY) p->dnsp_qtyp = 0;
|
||||
if ((p->dnsp_qcls = dns_get16(cur+2)) == DNS_C_ANY) p->dnsp_qcls = 0;
|
||||
p->dnsp_cur = p->dnsp_ans = cur + 4;
|
||||
p->dnsp_ttl = 0xffffffffu;
|
||||
p->dnsp_nrr = 0;
|
||||
}
|
||||
|
||||
int dns_nextrr(struct dns_parse *p, struct dns_rr *rr) {
|
||||
dnscc_t *cur = p->dnsp_cur;
|
||||
while(p->dnsp_rrl > 0) {
|
||||
--p->dnsp_rrl;
|
||||
if (dns_getdn(p->dnsp_pkt, &cur, p->dnsp_end,
|
||||
rr->dnsrr_dn, sizeof(rr->dnsrr_dn)) <= 0)
|
||||
return -1;
|
||||
if (cur + 10 > p->dnsp_end)
|
||||
return -1;
|
||||
rr->dnsrr_typ = dns_get16(cur);
|
||||
rr->dnsrr_cls = dns_get16(cur+2);
|
||||
rr->dnsrr_ttl = dns_get32(cur+4);
|
||||
rr->dnsrr_dsz = dns_get16(cur+8);
|
||||
rr->dnsrr_dptr = cur = cur + 10;
|
||||
rr->dnsrr_dend = cur = cur + rr->dnsrr_dsz;
|
||||
if (cur > p->dnsp_end)
|
||||
return -1;
|
||||
if (p->dnsp_qdn && !dns_dnequal(p->dnsp_qdn, rr->dnsrr_dn))
|
||||
continue;
|
||||
if ((!p->dnsp_qcls || p->dnsp_qcls == rr->dnsrr_cls) &&
|
||||
(!p->dnsp_qtyp || p->dnsp_qtyp == rr->dnsrr_typ)) {
|
||||
p->dnsp_cur = cur;
|
||||
++p->dnsp_nrr;
|
||||
if (p->dnsp_ttl > rr->dnsrr_ttl) p->dnsp_ttl = rr->dnsrr_ttl;
|
||||
return 1;
|
||||
}
|
||||
if (p->dnsp_qdn && rr->dnsrr_typ == DNS_T_CNAME && !p->dnsp_nrr) {
|
||||
if (dns_getdn(p->dnsp_pkt, &rr->dnsrr_dptr, p->dnsp_end,
|
||||
p->dnsp_dnbuf, sizeof(p->dnsp_dnbuf)) <= 0 ||
|
||||
rr->dnsrr_dptr != rr->dnsrr_dend)
|
||||
return -1;
|
||||
p->dnsp_qdn = p->dnsp_dnbuf;
|
||||
if (p->dnsp_ttl > rr->dnsrr_ttl) p->dnsp_ttl = rr->dnsrr_ttl;
|
||||
}
|
||||
}
|
||||
p->dnsp_cur = cur;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_stdrr_size(const struct dns_parse *p) {
|
||||
return
|
||||
dns_dntop_size(p->dnsp_qdn) +
|
||||
(p->dnsp_qdn == dns_payload(p->dnsp_pkt) ? 0 :
|
||||
dns_dntop_size(dns_payload(p->dnsp_pkt)));
|
||||
}
|
||||
|
||||
void *dns_stdrr_finish(struct dns_rr_null *ret, char *cp,
|
||||
const struct dns_parse *p) {
|
||||
cp += dns_dntop(p->dnsp_qdn, (ret->dnsn_cname = cp), DNS_MAXNAME);
|
||||
if (p->dnsp_qdn == dns_payload(p->dnsp_pkt))
|
||||
ret->dnsn_qname = ret->dnsn_cname;
|
||||
else
|
||||
dns_dntop(dns_payload(p->dnsp_pkt), (ret->dnsn_qname = cp), DNS_MAXNAME);
|
||||
ret->dnsn_ttl = p->dnsp_ttl;
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,126 +0,0 @@
|
||||
/* $Id: udns_rr_a.c,v 1.14 2005/04/20 06:44:34 mjt Exp $
|
||||
parse/query A/AAAA IN records
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#ifdef WIN32
|
||||
# include <winsock2.h> /* includes <windows.h> */
|
||||
# include <ws2tcpip.h> /* needed for struct in6_addr */
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
#include "udns.h"
|
||||
|
||||
/* here, we use common routine to parse both IPv4 and IPv6 addresses.
|
||||
*/
|
||||
|
||||
/* this structure should match dns_rr_a[46] */
|
||||
struct dns_rr_a {
|
||||
dns_rr_common(dnsa);
|
||||
unsigned char *dnsa_addr;
|
||||
};
|
||||
|
||||
static int
|
||||
dns_parse_a(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
|
||||
void **result, unsigned dsize) {
|
||||
struct dns_rr_a *ret;
|
||||
struct dns_parse p;
|
||||
struct dns_rr rr;
|
||||
int r;
|
||||
|
||||
/* first, validate and count number of addresses */
|
||||
dns_initparse(&p, qdn, pkt, cur, end);
|
||||
while((r = dns_nextrr(&p, &rr)) > 0)
|
||||
if (rr.dnsrr_dsz != dsize)
|
||||
return DNS_E_PROTOCOL;
|
||||
if (r < 0)
|
||||
return DNS_E_PROTOCOL;
|
||||
else if (!p.dnsp_nrr)
|
||||
return DNS_E_NODATA;
|
||||
|
||||
ret = malloc(sizeof(*ret) + dsize * p.dnsp_nrr + dns_stdrr_size(&p));
|
||||
if (!ret)
|
||||
return DNS_E_NOMEM;
|
||||
|
||||
ret->dnsa_nrr = p.dnsp_nrr;
|
||||
ret->dnsa_addr = (unsigned char*)(ret+1);
|
||||
|
||||
/* copy the RRs */
|
||||
for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r)
|
||||
memcpy(ret->dnsa_addr + dsize * r, rr.dnsrr_dptr, dsize);
|
||||
|
||||
dns_stdrr_finish((struct dns_rr_null *)ret,
|
||||
(char *)(ret->dnsa_addr + dsize * p.dnsp_nrr), &p);
|
||||
*result = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dns_parse_a4(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
|
||||
void **result) {
|
||||
#ifndef __OpenBSD__ /* Openbsd likes to patch compilers to bitch about stupid things */
|
||||
assert(sizeof(struct in_addr) == 4);
|
||||
#endif
|
||||
assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_A);
|
||||
return dns_parse_a(qdn, pkt, cur, end, result, 4);
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_a4(struct dns_ctx *ctx, const char *name, int flags,
|
||||
dns_query_a4_fn *cbck, void *data) {
|
||||
return
|
||||
dns_submit_p(ctx, name, DNS_C_IN, DNS_T_A, flags,
|
||||
dns_parse_a4, (dns_query_fn*)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_a4 *
|
||||
dns_resolve_a4(struct dns_ctx *ctx, const char *name, int flags) {
|
||||
return (struct dns_rr_a4 *)
|
||||
dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_A, flags, dns_parse_a4);
|
||||
}
|
||||
|
||||
int
|
||||
dns_parse_a6(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
|
||||
void **result) {
|
||||
#ifdef AF_INET6
|
||||
assert(sizeof(struct in6_addr) == 16);
|
||||
#endif
|
||||
assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_AAAA);
|
||||
return dns_parse_a(qdn, pkt, cur, end, result, 16);
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_a6(struct dns_ctx *ctx, const char *name, int flags,
|
||||
dns_query_a6_fn *cbck, void *data) {
|
||||
return
|
||||
dns_submit_p(ctx, name, DNS_C_IN, DNS_T_AAAA, flags,
|
||||
dns_parse_a6, (dns_query_fn*)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_a6 *
|
||||
dns_resolve_a6(struct dns_ctx *ctx, const char *name, int flags) {
|
||||
return (struct dns_rr_a6 *)
|
||||
dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_AAAA, flags, dns_parse_a6);
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/* $Id: udns_rr_mx.c,v 1.13 2005/04/20 06:44:34 mjt Exp $
|
||||
parse/query MX IN records
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "udns.h"
|
||||
|
||||
int
|
||||
dns_parse_mx(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
|
||||
void **result) {
|
||||
struct dns_rr_mx *ret;
|
||||
struct dns_parse p;
|
||||
struct dns_rr rr;
|
||||
int r, l;
|
||||
char *sp;
|
||||
dnsc_t mx[DNS_MAXDN];
|
||||
|
||||
assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_MX);
|
||||
|
||||
/* first, validate the answer and count size of the result */
|
||||
l = 0;
|
||||
dns_initparse(&p, qdn, pkt, cur, end);
|
||||
while((r = dns_nextrr(&p, &rr)) > 0) {
|
||||
cur = rr.dnsrr_dptr + 2;
|
||||
r = dns_getdn(pkt, &cur, end, mx, sizeof(mx));
|
||||
if (r <= 0 || cur != rr.dnsrr_dend)
|
||||
return DNS_E_PROTOCOL;
|
||||
l += dns_dntop_size(mx);
|
||||
}
|
||||
if (r < 0)
|
||||
return DNS_E_PROTOCOL;
|
||||
if (!p.dnsp_nrr)
|
||||
return DNS_E_NODATA;
|
||||
|
||||
/* next, allocate and set up result */
|
||||
l += dns_stdrr_size(&p);
|
||||
ret = malloc(sizeof(*ret) + sizeof(struct dns_mx) * p.dnsp_nrr + l);
|
||||
if (!ret)
|
||||
return DNS_E_NOMEM;
|
||||
ret->dnsmx_nrr = p.dnsp_nrr;
|
||||
ret->dnsmx_mx = (struct dns_mx *)(ret+1);
|
||||
|
||||
/* and 3rd, fill in result, finally */
|
||||
sp = (char*)(ret->dnsmx_mx + p.dnsp_nrr);
|
||||
for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) {
|
||||
ret->dnsmx_mx[r].name = sp;
|
||||
cur = rr.dnsrr_dptr;
|
||||
ret->dnsmx_mx[r].priority = dns_get16(cur);
|
||||
cur += 2;
|
||||
dns_getdn(pkt, &cur, end, mx, sizeof(mx));
|
||||
sp += dns_dntop(mx, sp, DNS_MAXNAME);
|
||||
}
|
||||
dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
|
||||
*result = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_mx(struct dns_ctx *ctx, const char *name, int flags,
|
||||
dns_query_mx_fn *cbck, void *data) {
|
||||
return
|
||||
dns_submit_p(ctx, name, DNS_C_IN, DNS_T_MX, flags,
|
||||
dns_parse_mx, (dns_query_fn *)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_mx *
|
||||
dns_resolve_mx(struct dns_ctx *ctx, const char *name, int flags) {
|
||||
return (struct dns_rr_mx *)
|
||||
dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_MX, flags, dns_parse_mx);
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/* $Id: udns_rr_naptr.c,v 1.1 2006/11/28 22:58:04 mjt Exp $
|
||||
parse/query NAPTR IN records
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
Copyright (C) 2006 Mikael Magnusson <mikma@users.sourceforge.net>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "udns.h"
|
||||
|
||||
/* Get a single string for NAPTR record, pretty much like a DN label.
|
||||
* String length is in first byte in *cur, so it can't be >255.
|
||||
*/
|
||||
static int dns_getstr(dnscc_t **cur, dnscc_t *ep, char *buf)
|
||||
{
|
||||
unsigned l;
|
||||
dnscc_t *cp = *cur;
|
||||
|
||||
l = *cp++;
|
||||
if (cp + l > ep)
|
||||
return DNS_E_PROTOCOL;
|
||||
if (buf) {
|
||||
memcpy(buf, cp, l);
|
||||
buf[l] = '\0';
|
||||
}
|
||||
cp += l;
|
||||
|
||||
*cur = cp;
|
||||
return l + 1;
|
||||
}
|
||||
|
||||
int
|
||||
dns_parse_naptr(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
|
||||
void **result) {
|
||||
struct dns_rr_naptr *ret;
|
||||
struct dns_parse p;
|
||||
struct dns_rr rr;
|
||||
int r, l;
|
||||
char *sp;
|
||||
dnsc_t dn[DNS_MAXDN];
|
||||
|
||||
assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_NAPTR);
|
||||
|
||||
/* first, validate the answer and count size of the result */
|
||||
l = 0;
|
||||
dns_initparse(&p, qdn, pkt, cur, end);
|
||||
while((r = dns_nextrr(&p, &rr)) > 0) {
|
||||
int i;
|
||||
dnscc_t *ep = rr.dnsrr_dend;
|
||||
|
||||
/* first 4 bytes: order & preference */
|
||||
cur = rr.dnsrr_dptr + 4;
|
||||
|
||||
/* flags, services and regexp */
|
||||
for (i = 0; i < 3; i++) {
|
||||
r = dns_getstr(&cur, ep, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
l += r;
|
||||
}
|
||||
/* replacement */
|
||||
r = dns_getdn(pkt, &cur, end, dn, sizeof(dn));
|
||||
if (r <= 0 || cur != rr.dnsrr_dend)
|
||||
return DNS_E_PROTOCOL;
|
||||
l += dns_dntop_size(dn);
|
||||
}
|
||||
if (r < 0)
|
||||
return DNS_E_PROTOCOL;
|
||||
if (!p.dnsp_nrr)
|
||||
return DNS_E_NODATA;
|
||||
|
||||
/* next, allocate and set up result */
|
||||
l += dns_stdrr_size(&p);
|
||||
ret = malloc(sizeof(*ret) + sizeof(struct dns_naptr) * p.dnsp_nrr + l);
|
||||
if (!ret)
|
||||
return DNS_E_NOMEM;
|
||||
ret->dnsnaptr_nrr = p.dnsp_nrr;
|
||||
ret->dnsnaptr_naptr = (struct dns_naptr *)(ret+1);
|
||||
|
||||
/* and 3rd, fill in result, finally */
|
||||
sp = (char*)(&ret->dnsnaptr_naptr[p.dnsp_nrr]);
|
||||
for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) {
|
||||
cur = rr.dnsrr_dptr;
|
||||
ret->dnsnaptr_naptr[r].order = dns_get16(cur); cur += 2;
|
||||
ret->dnsnaptr_naptr[r].preference = dns_get16(cur); cur += 2;
|
||||
sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].flags = sp));
|
||||
sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].service = sp));
|
||||
sp += dns_getstr(&cur, end, (ret->dnsnaptr_naptr[r].regexp = sp));
|
||||
dns_getdn(pkt, &cur, end, dn, sizeof(dn));
|
||||
sp += dns_dntop(dn, (ret->dnsnaptr_naptr[r].replacement = sp), DNS_MAXNAME);
|
||||
}
|
||||
dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
|
||||
*result = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_naptr(struct dns_ctx *ctx, const char *name, int flags,
|
||||
dns_query_naptr_fn *cbck, void *data) {
|
||||
return
|
||||
dns_submit_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags,
|
||||
dns_parse_naptr, (dns_query_fn *)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_naptr *
|
||||
dns_resolve_naptr(struct dns_ctx *ctx, const char *name, int flags) {
|
||||
return (struct dns_rr_naptr *)
|
||||
dns_resolve_p(ctx, name, DNS_C_IN, DNS_T_NAPTR, flags, dns_parse_naptr);
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/* $Id: udns_rr_ptr.c,v 1.15 2005/09/12 11:21:06 mjt Exp $
|
||||
parse/query PTR records
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "udns.h"
|
||||
|
||||
int
|
||||
dns_parse_ptr(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
|
||||
void **result) {
|
||||
struct dns_rr_ptr *ret;
|
||||
struct dns_parse p;
|
||||
struct dns_rr rr;
|
||||
int r, l, c;
|
||||
char *sp;
|
||||
dnsc_t ptr[DNS_MAXDN];
|
||||
|
||||
assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_PTR);
|
||||
|
||||
/* first, validate the answer and count size of the result */
|
||||
l = c = 0;
|
||||
dns_initparse(&p, qdn, pkt, cur, end);
|
||||
while((r = dns_nextrr(&p, &rr)) > 0) {
|
||||
cur = rr.dnsrr_dptr;
|
||||
r = dns_getdn(pkt, &cur, end, ptr, sizeof(ptr));
|
||||
if (r <= 0 || cur != rr.dnsrr_dend)
|
||||
return DNS_E_PROTOCOL;
|
||||
l += dns_dntop_size(ptr);
|
||||
++c;
|
||||
}
|
||||
if (r < 0)
|
||||
return DNS_E_PROTOCOL;
|
||||
if (!c)
|
||||
return DNS_E_NODATA;
|
||||
|
||||
/* next, allocate and set up result */
|
||||
ret = malloc(sizeof(*ret) + sizeof(char **) * c + l + dns_stdrr_size(&p));
|
||||
if (!ret)
|
||||
return DNS_E_NOMEM;
|
||||
ret->dnsptr_nrr = c;
|
||||
ret->dnsptr_ptr = (char **)(ret+1);
|
||||
|
||||
/* and 3rd, fill in result, finally */
|
||||
sp = (char*)(ret->dnsptr_ptr + c);
|
||||
c = 0;
|
||||
dns_rewind(&p, qdn);
|
||||
while((r = dns_nextrr(&p, &rr)) > 0) {
|
||||
ret->dnsptr_ptr[c] = sp;
|
||||
cur = rr.dnsrr_dptr;
|
||||
dns_getdn(pkt, &cur, end, ptr, sizeof(ptr));
|
||||
sp += dns_dntop(ptr, sp, DNS_MAXNAME);
|
||||
++c;
|
||||
}
|
||||
dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
|
||||
*result = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr,
|
||||
dns_query_ptr_fn *cbck, void *data) {
|
||||
dnsc_t dn[DNS_A4RSIZE];
|
||||
dns_a4todn(addr, 0, dn, sizeof(dn));
|
||||
return
|
||||
dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_PTR, DNS_NOSRCH,
|
||||
dns_parse_ptr, (dns_query_fn *)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_ptr *
|
||||
dns_resolve_a4ptr(struct dns_ctx *ctx, const struct in_addr *addr) {
|
||||
return (struct dns_rr_ptr *)
|
||||
dns_resolve(ctx, dns_submit_a4ptr(ctx, addr, NULL, NULL));
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr,
|
||||
dns_query_ptr_fn *cbck, void *data) {
|
||||
dnsc_t dn[DNS_A6RSIZE];
|
||||
dns_a6todn(addr, 0, dn, sizeof(dn));
|
||||
return
|
||||
dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_PTR, DNS_NOSRCH,
|
||||
dns_parse_ptr, (dns_query_fn *)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_ptr *
|
||||
dns_resolve_a6ptr(struct dns_ctx *ctx, const struct in6_addr *addr) {
|
||||
return (struct dns_rr_ptr *)
|
||||
dns_resolve(ctx, dns_submit_a6ptr(ctx, addr, NULL, NULL));
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/* $Id: udns_rr_srv.c,v 1.2 2005/09/12 12:26:22 mjt Exp $
|
||||
parse/query SRV IN (rfc2782) records
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Copyright 2005 Thadeu Lima de Souza Cascardo <cascardo@minaslivre.org>
|
||||
|
||||
2005-09-11:
|
||||
Changed MX parser file into a SRV parser file
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "udns.h"
|
||||
|
||||
int
|
||||
dns_parse_srv(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
|
||||
void **result) {
|
||||
struct dns_rr_srv *ret;
|
||||
struct dns_parse p;
|
||||
struct dns_rr rr;
|
||||
int r, l;
|
||||
char *sp;
|
||||
dnsc_t srv[DNS_MAXDN];
|
||||
|
||||
assert(dns_get16(cur+2) == DNS_C_IN && dns_get16(cur+0) == DNS_T_SRV);
|
||||
|
||||
/* first, validate the answer and count size of the result */
|
||||
l = 0;
|
||||
dns_initparse(&p, qdn, pkt, cur, end);
|
||||
while((r = dns_nextrr(&p, &rr)) > 0) {
|
||||
cur = rr.dnsrr_dptr + 6;
|
||||
r = dns_getdn(pkt, &cur, end, srv, sizeof(srv));
|
||||
if (r <= 0 || cur != rr.dnsrr_dend)
|
||||
return DNS_E_PROTOCOL;
|
||||
l += dns_dntop_size(srv);
|
||||
}
|
||||
if (r < 0)
|
||||
return DNS_E_PROTOCOL;
|
||||
if (!p.dnsp_nrr)
|
||||
return DNS_E_NODATA;
|
||||
|
||||
/* next, allocate and set up result */
|
||||
l += dns_stdrr_size(&p);
|
||||
ret = malloc(sizeof(*ret) + sizeof(struct dns_srv) * p.dnsp_nrr + l);
|
||||
if (!ret)
|
||||
return DNS_E_NOMEM;
|
||||
ret->dnssrv_nrr = p.dnsp_nrr;
|
||||
ret->dnssrv_srv = (struct dns_srv *)(ret+1);
|
||||
|
||||
/* and 3rd, fill in result, finally */
|
||||
sp = (char*)(ret->dnssrv_srv + p.dnsp_nrr);
|
||||
for (dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr); ++r) {
|
||||
ret->dnssrv_srv[r].name = sp;
|
||||
cur = rr.dnsrr_dptr;
|
||||
ret->dnssrv_srv[r].priority = dns_get16(cur);
|
||||
ret->dnssrv_srv[r].weight = dns_get16(cur+2);
|
||||
ret->dnssrv_srv[r].port = dns_get16(cur+4);
|
||||
cur += 6;
|
||||
dns_getdn(pkt, &cur, end, srv, sizeof(srv));
|
||||
sp += dns_dntop(srv, sp, DNS_MAXNAME);
|
||||
}
|
||||
dns_stdrr_finish((struct dns_rr_null *)ret, sp, &p);
|
||||
*result = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add a single service or proto name prepending an undescore (_),
|
||||
* according to rfc2782 rules.
|
||||
* Return 0 or the label length.
|
||||
* Routing assumes dn holds enouth space for a single DN label. */
|
||||
static unsigned add_sname(dnsc_t *dn, const char *sn) {
|
||||
unsigned l;
|
||||
l = dns_ptodn(sn, 0, dn + 1, DNS_MAXLABEL-1, NULL);
|
||||
if (l <= 1 || l - 2 != dn[1])
|
||||
/* Should we really check if sn is exactly one label? Do we care? */
|
||||
return 0;
|
||||
dn[0] = l - 1;
|
||||
dn[1] = '_';
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Construct a domain name for SRV query from the given name, service and
|
||||
* protocol (service may be NULL in which case protocol isn't used).
|
||||
* Return negative value on error (malformed query),
|
||||
* or addition query flag(s) to use.
|
||||
*/
|
||||
static int
|
||||
build_srv_dn(dnsc_t *dn, const char *name, const char *srv, const char *proto)
|
||||
{
|
||||
unsigned p = 0, l;
|
||||
int isabs;
|
||||
if (srv) {
|
||||
l = add_sname(dn + p, srv);
|
||||
if (!l)
|
||||
return -1;
|
||||
p += l;
|
||||
l = add_sname(dn + p, proto);
|
||||
if (!l)
|
||||
return -1;
|
||||
p += l;
|
||||
}
|
||||
l = dns_ptodn(name, 0, dn + p, DNS_MAXDN - p, &isabs);
|
||||
if (!l)
|
||||
return -1;
|
||||
return isabs ? DNS_NOSRCH : 0;
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_srv(struct dns_ctx *ctx,
|
||||
const char *name, const char *srv, const char *proto,
|
||||
int flags, dns_query_srv_fn *cbck, void *data) {
|
||||
dnsc_t dn[DNS_MAXDN];
|
||||
int r = build_srv_dn(dn, name, srv, proto);
|
||||
if (r < 0) {
|
||||
dns_setstatus (ctx, DNS_E_BADQUERY);
|
||||
return NULL;
|
||||
}
|
||||
return
|
||||
dns_submit_dn(ctx, dn, DNS_C_IN, DNS_T_SRV, flags | r,
|
||||
dns_parse_srv, (dns_query_fn *)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_srv *
|
||||
dns_resolve_srv(struct dns_ctx *ctx,
|
||||
const char *name, const char *srv, const char *proto, int flags)
|
||||
{
|
||||
dnsc_t dn[DNS_MAXDN];
|
||||
int r = build_srv_dn(dn, name, srv, proto);
|
||||
if (r < 0) {
|
||||
dns_setstatus(ctx, DNS_E_BADQUERY);
|
||||
return NULL;
|
||||
}
|
||||
return (struct dns_rr_srv *)
|
||||
dns_resolve_dn(ctx, dn, DNS_C_IN, DNS_T_SRV, flags | r, dns_parse_srv);
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/* $Id: udns_rr_txt.c,v 1.15 2006/11/28 22:45:20 mjt Exp $
|
||||
parse/query TXT records
|
||||
|
||||
Copyright (C) 2005 Michael Tokarev <mjt@corpit.ru>
|
||||
This file is part of UDNS library, an async DNS stub resolver.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library, in file named COPYING.LGPL; if not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place,
|
||||
Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "udns.h"
|
||||
|
||||
int
|
||||
dns_parse_txt(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end,
|
||||
void **result) {
|
||||
struct dns_rr_txt *ret;
|
||||
struct dns_parse p;
|
||||
struct dns_rr rr;
|
||||
int r, l;
|
||||
dnsc_t *sp;
|
||||
dnscc_t *cp, *ep;
|
||||
|
||||
assert(dns_get16(cur+0) == DNS_T_TXT);
|
||||
|
||||
/* first, validate the answer and count size of the result */
|
||||
l = 0;
|
||||
dns_initparse(&p, qdn, pkt, cur, end);
|
||||
while((r = dns_nextrr(&p, &rr)) > 0) {
|
||||
cp = rr.dnsrr_dptr; ep = rr.dnsrr_dend;
|
||||
while(cp < ep) {
|
||||
r = *cp++;
|
||||
if (cp + r > ep)
|
||||
return DNS_E_PROTOCOL;
|
||||
l += r;
|
||||
cp += r;
|
||||
}
|
||||
}
|
||||
if (r < 0)
|
||||
return DNS_E_PROTOCOL;
|
||||
if (!p.dnsp_nrr)
|
||||
return DNS_E_NODATA;
|
||||
|
||||
/* next, allocate and set up result */
|
||||
l += (sizeof(struct dns_txt) + 1) * p.dnsp_nrr + dns_stdrr_size(&p);
|
||||
ret = malloc(sizeof(*ret) + l);
|
||||
if (!ret)
|
||||
return DNS_E_NOMEM;
|
||||
ret->dnstxt_nrr = p.dnsp_nrr;
|
||||
ret->dnstxt_txt = (struct dns_txt *)(ret+1);
|
||||
|
||||
/* and 3rd, fill in result, finally */
|
||||
sp = (dnsc_t*)(ret->dnstxt_txt + p.dnsp_nrr);
|
||||
for(dns_rewind(&p, qdn), r = 0; dns_nextrr(&p, &rr) > 0; ++r) {
|
||||
ret->dnstxt_txt[r].txt = sp;
|
||||
cp = rr.dnsrr_dptr; ep = rr.dnsrr_dend;
|
||||
while(cp < ep) {
|
||||
l = *cp++;
|
||||
memcpy(sp, cp, l);
|
||||
sp += l;
|
||||
cp += l;
|
||||
}
|
||||
ret->dnstxt_txt[r].len = (int)(sp - ret->dnstxt_txt[r].txt);
|
||||
*sp++ = '\0';
|
||||
}
|
||||
dns_stdrr_finish((struct dns_rr_null *)ret, (char*)sp, &p);
|
||||
*result = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dns_query *
|
||||
dns_submit_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags,
|
||||
dns_query_txt_fn *cbck, void *data) {
|
||||
return
|
||||
dns_submit_p(ctx, name, qcls, DNS_T_TXT, flags,
|
||||
dns_parse_txt, (dns_query_fn *)cbck, data);
|
||||
}
|
||||
|
||||
struct dns_rr_txt *
|
||||
dns_resolve_txt(struct dns_ctx *ctx, const char *name, int qcls, int flags) {
|
||||
return (struct dns_rr_txt *)
|
||||
dns_resolve_p(ctx, name, qcls, DNS_T_TXT, flags, dns_parse_txt);
|
||||
}
|
||||
Reference in new issue
Block a user