Merge branch 'master' into smgmaster

This commit is contained in:
Moises Silva 2011-03-24 19:08:24 -04:00
commit bf23a0a38b
127 changed files with 3185 additions and 8895 deletions

23
.gitignore vendored
View File

@ -42,6 +42,12 @@ configure.lineno
config.log
config.status
core.*
*.2010.log
*.Build.CppClean.log
*.tlog
*.unsuccessfulbuild
*.cache
*.lastbuildstate
/w32/Library/lastversion
/w32/Library/tmpVersion.Bat
@ -83,6 +89,7 @@ core.*
/build/config/missing
/build/freeswitch.pc
/build/getlib.sh
/build/getg729.sh
/build/getsounds.sh
/build/Makefile
/build/Makefile.in
@ -104,6 +111,7 @@ core.*
/libs/freetdm/testtones
/libs/fsg729-*-installer
/libs/g729/
/libs/libcodec2/compile
/libs/libcodec2/config.guess
/libs/libcodec2/config.sub
/libs/libcodec2/configure
@ -118,6 +126,7 @@ core.*
/libs/libcodec2/src/Makefile.in
/libs/libcodec2/unittest/Makefile
/libs/libcodec2/unittest/Makefile.in
/libs/mpg123-1.13.2/
/scripts/fsxs
/scripts/gentls_cert
@ -147,3 +156,17 @@ core.*
/src/mod/say/mod_say_th/Makefile
/src/mod/say/mod_say_zh/Makefile
BuildLog.htm
/w32/Console/Debug/
/w32/Console/Release/
/w32/Library/Debug/
/w32/Library/Release/
Freeswitch.2010.sdf
/Win32/
/x64/
src/mod/codecs/mod_celt/*/*/mod_celt.log
src/mod/endpoints/mod_skinny/*/*/mod_skinny_2010.log
src/mod/formats/mod_shout/*/*/mod_shout.log

View File

@ -1608,24 +1608,16 @@ Global
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|x64.ActiveCfg = Release|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|x64.Build.0 = Release|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|Win32.ActiveCfg = Debug|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|Win32.Build.0 = Debug|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x64.ActiveCfg = Debug|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x64.Build.0 = Debug|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|Win32.ActiveCfg = Release|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|Win32.Build.0 = Release|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x64.ActiveCfg = Release|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x64.Build.0 = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|Win32.ActiveCfg = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|x64.ActiveCfg = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|x64.Build.0 = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|Win32.ActiveCfg = Debug|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|Win32.Build.0 = Debug|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x64.ActiveCfg = Debug|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x64.Build.0 = Debug|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|Win32.ActiveCfg = Release|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|Win32.Build.0 = Release|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x64.ActiveCfg = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x64.Build.0 = Release|x64
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|Win32.ActiveCfg = Release|x64
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|x64.ActiveCfg = Release|x64
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|x64.Build.0 = Release|x64

View File

@ -1480,15 +1480,11 @@ Global
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|x64 Setup.Build.0 = Release|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|x86 Setup.ActiveCfg = Release|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|Win32.ActiveCfg = Debug|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|Win32.Build.0 = Debug|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x64.ActiveCfg = Debug|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x64.Build.0 = Debug|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x64 Setup.ActiveCfg = Debug|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|Win32.ActiveCfg = Release|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|Win32.Build.0 = Release|Win32
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x64.ActiveCfg = Release|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x64.Build.0 = Release|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x64 Setup.ActiveCfg = Release|x64
{4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x86 Setup.ActiveCfg = Release|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|Win32.ActiveCfg = Release|x64
@ -1498,15 +1494,11 @@ Global
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|x64 Setup.Build.0 = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|x86 Setup.ActiveCfg = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|Win32.ActiveCfg = Debug|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|Win32.Build.0 = Debug|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x64.ActiveCfg = Debug|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x64.Build.0 = Debug|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x64 Setup.ActiveCfg = Debug|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|Win32.ActiveCfg = Release|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|Win32.Build.0 = Release|Win32
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x64.ActiveCfg = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x64.Build.0 = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x64 Setup.ActiveCfg = Release|x64
{71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x86 Setup.ActiveCfg = Release|Win32
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|Win32.ActiveCfg = Release|x64

View File

@ -36,6 +36,7 @@ applications/mod_valet_parking
#applications/mod_snipe_hunt
#applications/mod_callcenter
#applications/mod_fsk
#applications/mod_ladspa
codecs/mod_g723_1
codecs/mod_amr
#codecs/mod_amrwb
@ -111,6 +112,7 @@ say/mod_say_ru
#say/mod_say_zh
#say/mod_say_hu
#say/mod_say_th
#timers/mod_timerfd
## Experimental Modules (don't cry if they're broken)
#../../contrib/mod/xml_int/mod_xml_odbc

35
conf/README_IMPORTANT.txt Normal file
View File

@ -0,0 +1,35 @@
-= PLEASE READ THIS BEFORE YOU PUT A FreeSWITCH BOX INTO PRODUCTION =-
This configuration, generally known as the "default configuration" for FreeSWITCH, is *NOT* designed to be put into a production environment without some important modifications. Please keep in mind that the default configuration is designed to demonstrate what FreeSWITCH *can* do, not what it *should* do in your specific scenario.
*** SECURING YOUR SERVER ***
By default, FreeSWITCH starts up and does a NATPMP and UPnP request to your router. If your router supports either of these protocols then FreeSWITCH does two things:
#1 - It gets the external IP address, which it uses for SIP communications
#2 - It causes there to be a "pinhole" opened up in the router allowing inbound communications to your FreeSWITCH server
Please re-read #2. Now, please re-read #2 again. If you do not want a pinhole coming through your router then DO NOT USE the "auto-nat" tools. The way to disable the auto-nat (that is, UPnP/NATPMP) checking is to start FreeSWITCH with the "-nonat" flag. Easy enough.
If you are planning on putting a system into production then you had better pay attention to security in other areas as well. If you are behind a firewall then make sure your firewall is actually protecting you. If you have your server on a public-facing Internet connection then we recommend a few things:
#1 - Consider using iptables (Linux/Unix)
#2 - Consider using fail2ban (see http://wiki.freeswitch.org/wiki/Fail2ban)
*** SECURING YOUR USERS ***
By default, the static XML files have 20 "directory users" in conf/directory/10xx.xml, numbered 1000-1019. Also, the default dialplan has routing for calls to those same extension numbers. (NOTE: the directory and the dialplan are 100% separate concepts. Check out chapters 3-5 of the awesome FreeSWITCH book for details.)
The default users all have *very* simple passwords for SIP credentials and voicemail. If you put those into a production system then you are either brave, ignorant, or stupid. Please don't be any of those three things! You have a few choices for handling your users:
#1 - Delete the static XML files and use mod_xml_curl for dynamic users from a back-end database
#2 - Manually edit the static XML user directory files and modify the passwords
#3 - Run the handy randomize-passwords.pl script found in scripts/perl/ subdirectory under the main FreeSWITCH source directory
*** GETTING HELP ***
FreeSWITCH has a thriving on-line community - we welcome you to join us!
IRC: #freeswitch on irc.freenode.net
Mailing List: freeswitch-users on lists.freeswitch.org
You can also get professional FreeSWITCH assistance by visiting http://www.freeswitchsolutions.com or sending an email to consulting@freeswitch.org.
Happy FreeSWITCHing!

View File

@ -64,6 +64,9 @@
<!-- SNOM Module -->
<!--<load module="mod_snom"/>-->
<!-- This one only works on Linux for now -->
<!--<load module="mod_ladspa"/>-->
<!-- Dialplan Interfaces -->
<!-- <load module="mod_dialplan_directory"/> -->
<load module="mod_dialplan_xml"/>
@ -92,6 +95,7 @@
<load module="mod_file_string"/>
<!-- Timers -->
<!-- <load module="mod_timerfd"/> -->
<!-- Languages -->
<load module="mod_spidermonkey"/>

View File

@ -33,7 +33,7 @@
<param name="ff-key" value="6"/>
<param name="rew-key" value="4"/>
<param name="skip-greet-key" value="#"/>
<param name="previous-message-key" value="1"/>-->
<param name="previous-message-key" value="1"/>
<param name="next-message-key" value="3"/>
<param name="skip-info-key" value="*"/>
<param name="repeat-message-key" value="0"/>

View File

@ -0,0 +1,77 @@
<include>
<X-PRE-PROCESS cmd="set" data="AT_EPENT1=0 0 0 -1 -1 0 -1 0 -1 -1 0 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_EPENT2=1 1 1 -1 -1 1 -1 1 -1 -1 1 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_CPENT1=0 -1 -1 0 -1 0 0 0 -1 -1 0 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_CPENT2=1 -1 -1 1 -1 1 1 1 -1 -1 1 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_CMAJ1=0 -1 0 0 -1 0 -1 0 0 -1 0 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_CMAJ2=1 -1 1 1 -1 1 -1 1 1 -1 1 -1"/>
<X-PRE-PROCESS cmd="set" data="AT_BBLUES=1 -1 1 -1 -1 1 -1 1 1 1 -1 -1"/>
<X-PRE-PROCESS cmd="set" data="ATGPENT2=-1 1 -1 1 -1 1 -1 -1 1 -1 1 -1"/>
<extension name="101">
<condition field="destination_number" expression="^101$">
<!-- AUTOTALENT DEFAULTS -->
<!--
<action application="set" data="AT_TUNE=440"/>
<action application="set" data="AT_FIXED=0"/>
<action application="set" data="AT_PULL=0"/>
<action application="set" data="AT_A=0"/>
<action application="set" data="AT_Bb=-1"/>
<action application="set" data="AT_B=0"/>
<action application="set" data="AT_C=0"/>
<action application="set" data="AT_Db=-1"/>
<action application="set" data="AT_D=0"/>
<action application="set" data="AT_Eb=-1"/>
<action application="set" data="AT_E=0"/>
<action application="set" data="AT_F=0"/>
<action application="set" data="AT_Gb=-1"/>
<action application="set" data="AT_G=0"/>
<action application="set" data="AT_Ab=-1"/>
<action application="set" data="AT_AMOUNT=1"/>
<action application="set" data="AT_SMOOTH=0"/>
<action application="set" data="AT_SHIFT=0"/>
<action application="set" data="AT_OUTSCALE=0"/>
<action application="set" data="AT_LFODEPTH=0"/>
<action application="set" data="AT_LFORATE=5"/>
<action application="set" data="AT_LFOSHAPE=0"/>
<action application="set" data="AT_LFOSYMM=0"/>
<action application="set" data="AT_LFOQUANT=0"/>
<action application="set" data="AT_FCORR=0"/>
<action application="set" data="AT_FWARP=0"/>
<action application="set" data="AT_MIX=1"/>
-->
<action application="set" data="AT_TUNE=440"/>
<action application="set" data="AT_FIXED=0"/>
<action application="set" data="AT_PULL=0"/>
<action application="set" data="AT_AMOUNT=1"/>
<action application="set" data="AT_SMOOTH=0"/>
<action application="set" data="AT_SHIFT=1"/>
<action application="set" data="AT_OUTSCALE=0"/>
<action application="set" data="AT_LFODEPTH=0"/>
<action application="set" data="AT_LFORATE=5"/>
<action application="set" data="AT_LFOSHAPE=0"/>
<action application="set" data="AT_LFOSYMM=0"/>
<action application="set" data="AT_LFOQUANT=0"/>
<action application="set" data="AT_FCORR=0"/>
<action application="set" data="AT_FWARP=0"/>
<action application="set" data="AT_MIX=1"/>
<!-- you have to download the ladspa package and the desired plugins from their desired site -->
<action application="set"><![CDATA[ladspa_params=${AT_TUNE} ${AT_FIXED} ${AT_PULL} ${AT_EPENT2} ${AT_AMOUNT} ${AT_SMOOTH} ${AT_SHIFT} ${AT_OUTSCALE} ${AT_LFODEPTH} ${AT_LFORATE} ${AT_LFOSHAPE} ${AT_LFOSYMM} ${AT_LFOQUANT} ${AT_FCORR} ${AT_FWARP} ${AT_MIX}]]></action>
<action application="ladspa_run" data="r|autotalent||${ladspa_params}"/>
<action application="ladspa_run" data="r|tap_chorusflanger||"/>
<action application="ladspa_run" data="r|phasers_1217.so|autoPhaser|"/>
<action application="bridge" data="sofia/internal/888@conference.freeswitch.org"/>
</condition>
</extension>
</include>

View File

@ -343,6 +343,13 @@
<!-- Turn on a jitterbuffer for every call -->
<!-- <param name="auto-jitterbuffer-msec" value="60"/> -->
<!-- By default mod_sofia will ignore the codecs in the sdp for hold/unhold operations
Set this to true if you want to actually parse the sdp and re-negotiate the codec during hold/unhold.
It's probably not what you want so stick with the default unless you really need to change this.
-->
<!--<param name="renegotiate-codec-on-hold" value="true"/>-->
</settings>
</profile>

View File

@ -461,7 +461,7 @@ AC_PROG_GCC_TRADITIONAL
AC_FUNC_MALLOC
AC_TYPE_SIGNAL
AC_FUNC_STRFTIME
AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs])
AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create])
AC_CHECK_FUNCS([sched_setscheduler setpriority setrlimit setgroups initgroups])
AC_CHECK_FUNCS([wcsncmp setgroups asprintf setenv pselect gettimeofday localtime_r gmtime_r strcasecmp stricmp _stricmp])
@ -922,7 +922,6 @@ AC_CONFIG_FILES([Makefile
build/Makefile
src/Makefile
src/mod/Makefile
src/mod/applications/mod_enum/Makefile
src/mod/applications/mod_expr/Makefile
src/mod/applications/mod_fax/Makefile
src/mod/applications/mod_spandsp/Makefile

3
debian/control vendored
View File

@ -6,7 +6,8 @@ Uploaders: Michal Bielicki <michal.bielicki@seventhsignal.pl>, Gabriel Gunderson
Build-Depends: debhelper (>= 7), wget, automake (>=1.9), autoconf, libtool,
unixodbc-dev, libasound2-dev, libcurl3-openssl-dev|libcurl4-openssl-dev,
libssl-dev, ncurses-dev, libogg-dev, libvorbis-dev, libperl-dev, libgdbm-dev,
libdb-dev, libgnutls-dev, libtiff4-dev, python-dev, libx11-dev, uuid-dev
libdb-dev, libgnutls-dev, libtiff4-dev, python-dev, libx11-dev, uuid-dev,
libc6-dev
Homepage: http://freeswitch.org/
Standards-Version: 3.9.1
Vcs-Git: git://git.freeswitch.org/freeswitch.git

View File

@ -1,3 +1,5 @@
opt/freeswitch/conf/autoload_configs/python.conf.xml
opt/freeswitch/mod/mod_python.so*
usr/lib/python2.*/*-packages/freeswitch.py*
usr/lib/python2.*/*-packages/ESL.py*
usr/lib/python2.*/*-packages/_ESL.so*

View File

@ -55,12 +55,12 @@ do_setlimits() {
ulimit -c unlimited
ulimit -d unlimited
ulimit -f unlimited
ulimit -i unlimited
# ulimit -i unlimited
ulimit -n 999999
ulimit -q unlimited
ulimit -u unlimited
# ulimit -q unlimited
# ulimit -u unlimited
ulimit -v unlimited
ulimit -x unlimited
# ulimit -x unlimited
ulimit -s 240
ulimit -l unlimited
return 0

View File

@ -161,6 +161,7 @@ opt/freeswitch/mod/mod_speex.so*
opt/freeswitch/mod/mod_spy.so*
opt/freeswitch/mod/mod_syslog.so*
opt/freeswitch/mod/mod_theora.so*
opt/freeswitch/mod/mod_timerfd.so*
opt/freeswitch/mod/mod_tone_stream.so*
opt/freeswitch/mod/mod_tts_commandline.so*
opt/freeswitch/mod/mod_valet_parking.so*

7
debian/rules vendored
View File

@ -30,7 +30,9 @@ export LANGUAGES_MODULES=languages/mod_spidermonkey languages/mod_perl languages
export LOGGERS_MODULES=loggers/mod_console loggers/mod_logfile loggers/mod_syslog
export SAY_MODULES=say/mod_say_en say/mod_say_it say/mod_say_de say/mod_say_fr say/mod_say_es say/mod_say_nl say/mod_say_ru
export XML_INT_MODULES=xml_int/mod_xml_rpc xml_int/mod_xml_curl xml_int/mod_xml_cdr
export MYMODULES= $(PASSTHRU_CODEC_MODULES) $(APPLICATIONS_MODULES) $(ASR_TTS_MODULES) $(CODECS_MODULES) $(DIALPLANS_MODULES) $(ENDPOINTS_MODULES) $(EVENT_HANDLERS_MODULES) $(FORMATS_MODULES) $(LANGUAGES_MODULES) $(LOGGERS_MODULES) $(SAY_MODULES) $(XML_INT_MODULES)
export TIMER_MODULES=timers/mod_timerfd
export MYMODULES= $(PASSTHRU_CODEC_MODULES) $(APPLICATIONS_MODULES) $(ASR_TTS_MODULES) $(CODECS_MODULES) $(DIALPLANS_MODULES) $(ENDPOINTS_MODULES) $(EVENT_HANDLERS_MODULES) $(FORMATS_MODULES) $(LANGUAGES_MODULES) $(LOGGERS_MODULES) $(SAY_MODULES) $(XML_INT_MODULES) $(TIMER_MODULES)
export MODULES=$(MYMODULES)
@ -187,7 +189,7 @@ build-stamp: config.status
dh_testdir
$(MAKE)
cd libs/esl && $(MAKE) pymod && cd -
touch $@
clean: # .pc/applied-patches
@ -208,6 +210,7 @@ install: build
dh_installdirs -A
VERBOSE=1 $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
cd libs/esl && VERBOSE=1 $(MAKE) DESTDIR=$(CURDIR)/debian/tmp pymod-install && cd -
# Build architecture-independent files here.

View File

@ -21,6 +21,9 @@ freeswitch (1.0.7)
build: fix warnings on windows x64 builds src and mods projects - only libsofia included on the libs side (r:45ecbc2f)
build: Patch debian init.d script to set ulimit values (r:0eb33e57/FS-2844)
build: add plc to core (r:b7c80a84)
build: VS2010 libportaudio project improvements for DirectX builds and switch to build DirectX by default (r:e9e33f51/FS-3033)
build: add make targets for mod_com_g729 mod_com_g729-activate mod_com_g729-install mod_com_g729-clean mod_com_g729-uninstall (r:17d52112)
build: add support for bz2 to getlibs (r:b61fc396)
codec2: working prototype, still for testing only (r:04ca0751)
config: move limit.conf to db.conf
config: Update VM phrase macros to voice option then action on main, config menus
@ -36,6 +39,8 @@ freeswitch (1.0.7)
config: fix single domain assumption in default config to be more portable *cough* bkw *cough* (r:f987903e)
config: Bump Doxygen.conf version to 1.0.6... belatedly (r:cfeae1ba)
config: docs for acl (r:57b410eb)
config: add default to conf to demonstrate min-idle-cpu (r:b8b7266a)
config: change min/max enforcements to >= instead of > (r:0d5fcf65)
core: Add RTCP support (FSRTP-14)
core: handle some errors on missing db handle conditions
core: add ... and shutdown as a fail-safe when no modules are loaded
@ -183,8 +188,28 @@ freeswitch (1.0.7)
core: add record_restart_time_limit_on_dtmf var (r:7a1dcb69)
core: fix unreachable condition with a null args to make any key stop playback/record etc without dequing and remove hard-coded flush digits in play_and_get_digits be sure to flush it yourself before using (r:976859bb)
core: Fix a lock on reloadxml when stderr write is blocked. Also remove an error parsing print since reason generated were wrong and duplicate. (r:2d6161e8)
core: fix || where it should be or in sql stmt that may cause stray records in the calls table
core: Add CS_NONE and correct variable name (r:3fd7b8f2)
core: Fix SQL issue (r:04bb74fc/FS-3050,FS-3051)
core: fix race with media bug exiting from write frame while read frame is trying to use it (r:1341a75a)
core: fix regression in rtp stack trying to avoid broken clients who send the wrong payload type, we were eating the stun packets in jingle calls (r:0bce777a)
core: Add capability to specify core-db-name in switch.conf.xml to have sqlite in a different location. This is important for everyone with relatively 'high' sip registration since the addition of sip registration to the core require sqlite db to be moved to a faster location (Ramdisk for example). Useful for everyone who moved their sqlite db for sofia to ramdisk because of performance issue. (r:500e9acd)
core: Index column name wrong on table registrations. (This wont create the index for people who already have the table) (r:1096e673)
core: allow uuid bridge on unaswered channels as long as there is media available on at least one (r:4f93ea25)
core: add multiple-registrations flag to the core similar to mod_sofia (r:b36a7c0b)
core: tolerate dtmf where there is no start packet and only end packets (r:097caed4)
core: Fix RTP auto flush during bridge w/Windows causing packet loss (r:f8d326de/FS-3057)
core: possible ill placed assert() before a NULL check in soa_static.c (r:91a5e776/FS-2803)
core: prevent crash on double call to asr_close (r:4f5ca9e8/FS-3077)
core: fix bug in switch_itodtmf (r:b53a6848)
core: use strdup instead of core_session_strdup in hangup hook (r:3a10d6a1)
core: fix jb + no timer situations (r:61d3c56f)
core: Add events PLAYBACK_START and PLAYBACK_STOP, plus some minor improvments for RECORD_STOP (r:bc397ab6/FS-2971)
embedded languages: Provide core level support for conditional Set Global Variable (r:c017c24b/FSCORE-612)
embedded languages: add insertFile front end to switch_ivr_insert_file and reswig (r:c4e350ab)
fs_cli: block control-z from fs cli and print a warning how to exit properly (r:dc436b82)
fs_cli: skip blocking writes on fs_cli to avoid backing up event socket (r:2ec2a9b0)
fs_cli: let ctl-c work until you are connected (r:986f258d)
lang: Improve French phrase files (FSCONFIG-23)
lang: Update langs - Add pt_PT, update es to have es_ES and es_MX, update mod_say_es and add mod_say_pt (FS-2937) (r:c81a9448/FS-2937)
libapr: Fix issue where after a bridge with a member, uuid of Agent is set to single quote character ' (r:3fee704d/FS-2738)
@ -209,6 +234,10 @@ freeswitch (1.0.7)
libesl: Noevent/Noevents disparity (r:d29d83d7/ESL-53)
libesl: FS-2957 esl lib on windows fails to build (r:5254df04/FS-2957)
libesl: Small fix on ESL that cause event_id to be set wrong on headers that had value failure. (r:eb88304a)
libesl: added python eslmod installation to esl Makefiles (r:b83a30ca)
libesl: null terminate buffer after reading from the socket to prevent cross-over to old data that confuses the parser and throws off framing (r:e8a10558/ESL-56)
libesl: add optional job-uuid param to bgapi in oop mod (r:e96acac3)
libesl: fix linger support in esl client lib (r:0444626b)
libfreetdm: implemented freetdm config nodes and ss7 initial configuration
libfreetdm: fix codec for CAS signaling (r:b76e7f18)
libfreetdm: freetdm: ss7- added support for incoming group blocks, started adding support for ansi (r:c219a73c)
@ -230,6 +259,7 @@ freeswitch (1.0.7)
libspandsp: Fix for T.30 processing of operator interrupts, to improve compatibility with some machines, which seem to send them when no operator is around. (r:84ee0ae6)
libspandsp: spandsp t38 fax receiving error in win XP - regression from f029f7ef (r:761cec8f/FS-2766)
libspandsp: Added missing error codes when an ECM FAX is abandoned with the T30_ERR message (r:ec57dc7a)
libstfu: add param to jb to try to recapture latency (disabled by default) (r:d59d41d7)
mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis)
mod_avmd: Add to windows build (r:df4bd935)
mod_avmd: Fix mem leak (r:cd951384/FS-2839)
@ -253,6 +283,9 @@ freeswitch (1.0.7)
mod_callcenter: Make callcenter_config agent get return the value of the item requested. Also added queue param max-wait-time-with-no-agent-time-reached: If the max-wai-time-with-no-agent is already reached for the queue, then new caller can wait for x amount of second before it kicked out of the queue rather than get rejected automatically. (r:81a03869)
mod_callcenter: Add new event socket agent-offering. Plus some documentation and better handling of bad agent type -- FS-2869 (r:80174cf3/FS-2869)
mod_callcenter: Add error response for queue load and queue reload (FS-2988) (r:49a5effc/FS-2988)
mod_callcenter: IMPORTANT UPDATE, DTMF during moh created an loop to reactivate MOH but got canceled right away because of pending DTMF in the queue never been cleaned. Could cause masive disk write of debug, and can cause problem to the rest of FS stability. This patch also include basic fundation for DTMF capture support for member waiting. (r:cd1982ce)
mod_callcenter: force loopback_bowout=false on originate. This will need to be reworked, but should fix basic issues call to an agent using loopback (r:2e399b0b)
mod_callcenter: segfault using busy-delay-time parameter (r:c6f044d5/FS-3067)
mod_cdr_sqlite: initial commit (r:f625fe3b)
mod_cdr_sqlite: config file for mod_cdr_sqlite (r:25bc8fe3)
mod_cdr_sqlite: Drop transaction BEGIN/END around INSERT. We're only executing one command, and autocommit will automatically rollback if the INSERT fails. Sync state_handlers with mod_cdr_csv. Minor libpq fixups. (r:0f95b870)
@ -297,6 +330,11 @@ freeswitch (1.0.7)
mod_conference: Add energy level to conference_add_event_member_data (r:8d6d52e0)
mod_conference: if more digits than the length of the correct pin the remaining digits are accounted for next retry (r:b88cd345/FS-3000)
mod_conference: Fix unexpected behavior with endconf and auto-outcalls and pre_answer (r:6f58e6aa/FS-2771)
mod_conference: Added conference UUID to xml_list (r:10d696eb)
mod_conference: Added to the Auto OutCall support to specify the conf profile to be used using variable : conference_auto_outcall_profile (r:67edc7c3)
mod_conference: don't switch to CS_SOFT_EXECUTE before setting the current extension (r:4b5bcba0)
mod_conference: play files saying vol level in conf in lieu of making a function of say modules to return file_string urls (we need that) (r:94b680fb)
mod_conference: fire auto gain level events (r:d8ef36ed)
mod_curl: use method=post when post requested (r:c6a4ddd0/FSMOD-69)
mod_db: fix stack corruption (MODAPP-407)
mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13)
@ -315,6 +353,8 @@ freeswitch (1.0.7)
mod_dptools: add bind_digit_action application (r:9537197b)
mod_dptools: emit event when user presses DTMFs (r:37298f56)
mod_dptools: Log error when there's no IVR menus configured when you call 'ivr' DP app (r:30034891)
mod_dptools: reset signal_bond variable back to its original value on failed dial in att_xfer (r:330d7418)
mod_dptools: Fix storage class for 'cause' in user_outgoing_channel() so that each call has its very own hangup cause (r:cb6f1ed6)
mod_easyroute: Fix possible segfaults and memory leak during unload, and add new setting odbc-retries (r:7fbc47f8/FS-2973)
mod_erlang_event: Make XML fetch reply ACKs distinguishable, update freeswitch.erl (r:9d44ed04)
mod_erlang_event: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045)
@ -327,6 +367,7 @@ freeswitch (1.0.7)
mod_event_socket: fix up other users of switch_event_xmlize() to use SWITCH_EVENT_NONE (r:d6eb7562)
mod_event_socket: Fix small mem leaks (r:e4f90584/MODEVENT-68)
mod_event_socket: Add "-ERR" to api cmd response when failure occurs (r:58759052/FS-2827)
mod_event_socket: clear unique headers on event_socket filters (r:436413e0)
mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420)
mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94)
mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf)
@ -421,6 +462,7 @@ freeswitch (1.0.7)
mod_lua: spelling error in -ERR return code encounterd -> encountered (r:86e7cdc5/FS-2949)
mod_lua: Make dbh:connected accessible from Lua - thanks Grmt (r:09e6fd3f)
mod_lua: Added optional core: prefix to first arg passed to freeswitch.Dbh for giving direct access to sqlite db (r:a0181479)
mod_lua: expose switch_simple_email as "email" method (r:89c5f3bf/FS-3023)
mod_managed: Added wrapper for switch_event_bind for .net (r:a5f07a80/MODLANG-165)
mod_managed: add additional support (r:5be58aac)
mod_managed: add mono 2.8 patch file see FS-2774 (r:6a948bd9/FS-2774)
@ -436,9 +478,11 @@ freeswitch (1.0.7)
mod_openzap: callwaiting disable (r:e1b60b4c)
mod_openzap: disable dtmf app and cmd line option (r:fb4b7f7a)
mod_openzap: add enable dtmf app (r:3c95106e)
mod_opus: add mod_opus (r:8f565277)
mod_osp: initial check (Open Settlement Protocol)
mod_osp:Changed OSP TCP port from 1080 to 5045. (r:03abefdf)
mod_portaudio: Fix inbound state (CS_ROUTING not CS_INIT) (MODENDP-302)
mod_portaudio: mod_portaudio improvements and bug fixes (r:33b74ca8/FS-3006)
mod_sangoma_codec: Add sample config file
mod_sangoma_codec: added load/noload options for the supported codecs
mod_sangoma_codec: rename load/noload to register/noregister
@ -457,6 +501,7 @@ freeswitch (1.0.7)
mod_say_ja: initial commit, still needs sound files (r:b2423158/FS-2755)
mod_say_ru: Fix saying time with +1 hour of current time (r:68d74c31/MODAPP-444)
mod_say_zh: Number reading should now be OK for the whole range of integers for Cantonese and Mandarin
mod_shout: bump mod_shout to use mpg123-1.13.2 to hopefully address unwanted calls to exit() and inherit other upstream fixes (r:079f3f73)
mod_silk: Fix mod_silk compliance and performance issues (r:2ddbc457/MODCODEC-20)
mod_skinny: Add the missing api files
mod_skinny: add example dialplan and directory config (r:1bfcc17e)
@ -478,6 +523,7 @@ freeswitch (1.0.7)
mod_skinny: allow configuration of softkeys via xml (r:f5a6831f)
mod_skinny: allow skinny-default-soft-key-set-set per device (r:07c3c94d)
mod_skinny: Rename skinny-default-soft-key-set-set to skinny-soft-key-set-set (r:ba3a6ad6)
mod_skinny: centralized registration (r:e7a8189b)
mod_skypopen: making XEvents to works when EARLYMEDIA, and correctly manage threads death
mod_skypopen: now answer a call only when directed to do it (before was trying to answer any incoming call). Lot of changes to a messy part, so maybe some problem will come out... (r:45c6c4d3)
mod_skypopen: ignore early media sent by channels to be bridged before our channel is answered (r:ef14b78a)
@ -605,6 +651,20 @@ freeswitch (1.0.7)
mod_sofia: Places ;fs_path= within the contact string <...> when using NDLB-connectile-dysfunction-2.0, instead of just appending to the end of the contact string. (r:afc02747/FS-2989)
mod_sofia: Fix handling SUBSCRIBE to &quot;park+&quot; fifo, the NOTIFY data was not being generated from mod_fifo data. (r:3dd9d5c0/FS-3007)
mod_sofia: fsctl pause improvements (r:008e527c/FS-3012)
mod_sofia: only pass publish on when you have a subscription (r:85913b70)
mod_sofia: sip_codec_negotiation to override inbound-codec-negotiation setting (r:74a0cfd1/FS-3027)
mod_sofia: fix uuid_jitterbuffer edge case debugging a non-existant jb causing a seg (r:88d410d3)
mod_sofia: tell rtp stack about what remote payload type to expect when the receiving end follows the stupid SHOULD as WONT and sends a different dynamic payload number than the one in the offer (r:c565501f)
mod_sofia: rip off the fs_ args on message like we do in SEND_MESSAGE (r:b7fd81de)
mod_sofia: use the correct URI on endpoints behind nat (r:5f2857b8)
mod_sofia: put transport in the request uri on outbound registers if register_transport is set and proxy does not already contain a transport param (r:4b62ff79)
mod_sofia: pass custom headers backwards over sofia (r:13dc6058)
mod_sofia: fix profile SIP INFO dtmf not working (r:4c4ca08d)
mod_sofia: Fix SIP INFO DTMF (r:39ff78bf/FS-3078)
mod_sofia: contact-params should not be set if the string is empty (r:06988e1a/FS-3084)
mod_sofia: segfault with sofia_contact when invalid parameters are given (r:4e60f14a/FS-3072)
mod_sofia: Fix minupnpd nat_map updated IP not getting set in SIP profiles (r:e7acd4d1/FS-3054)
mod_sofia: add sip_execute_on_image variable similar to execute_on_answer etc so you can run t38_gateway or rxfax etc when you get a T.38 re-invite but no CNG tone or you want to ignore the tone and only react when getting a T.38 re-invite (r:53fc3f7f)
mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8)
mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642)
mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45)
@ -620,10 +680,12 @@ freeswitch (1.0.7)
mod_spidermonkey: allow vars to be set containing vars from languages (r:5cd072a3)
mod_spidermonkey: fix seg in js hangup (r:7d554c11)
mod_spidermonkey: Fix mod_spidermonkey build on FreeBSD, (Undefined symbol PR_LocalTimeParameters). (r:3edb8419)
mod_spidermonkey: Add session.ringReady() to check for CF_RING_READY (r:7386b9f8)
mod_spy: add support for loopback endpoint (MODAPP-416)
mod_spy: fix crash when session can't be located (r:c4154633/FS-2929)
mod_tts_commandline: fix core dump, temp file problem. flush can be called several times (FSMOD-35)
mod_unimrcp: fix fortify findings for mod_unimrcp (r:336f0b4e/FSMOD-67)
mod_unimrcp: fix truncated TTS (r:e37dd41e/FS-3201)
mod_valet_parking: add event data to valet parking hold event
mod_valet_parking: add event for Valet Parking action exit
mod_valet_parking: pass hold class on transfer (r:76a065ec)
@ -640,6 +702,8 @@ freeswitch (1.0.7)
mod_voicemail: Set email address from within directory (r:83ce26b2/FS-2972)
mod_voicemail: add events for record/change greeting and record name (r:54421f59)
mod_voicemail: let vmain-key and operator-key be set empty (r:de49305a)
mod_voicemail: add ability to jump to a specific message (r:0f8fb4b1)
mod_voicemail: vm-skip-instructions param in xml directory to disable instructions how to record a file (r:ed7e1f39)
mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17)
mod_xml_cdr: add leg param to query string (XML-24)
mod_xml_cdr: fix locked sessions (XML-26)
@ -652,6 +716,7 @@ freeswitch (1.0.7)
sofia-sip: fix null derefernce segfault in soa (r:f356c5e6)
sofia-sip: extend timeout for session expires on short timeouts to be 90% of timeout instead of 1/3 to handle devices that do not refresh in time such as polycom (r:a7f48928/SFSIP-212)
tools: Add fs_encode tool (r:89b17601)
tools: Add randomize-passwords.pl script to main tree (r:5e6123ef)
freeswitch (1.0.6)

View File

@ -428,6 +428,7 @@
<!-- The following phrases still need to be recorded -->
<prompt phrase="You are caller number one. Of course, *every* caller is number one in our book so you may be waiting a while." filename="ivr-youre_number_one.wav"/>
<prompt phrase="...has called emergency services" filename="ivr-has_called_emergency_services.wav"/>
</ivr>
<misc>
<prompt phrase="This call has been secured" filename="call_secured.wav"/>

View File

@ -31,9 +31,11 @@
%define build_sng_isdn 0
%define build_sng_ss7 0
%define build_sng_tc 0
%define build_py26_esl 0
%{?with_sang_tc:%define build_sng_tc 1 }
%{?with_sang_isdn:%define build_sng_isdn 1 }
%{?with_sang_ss7:%define build_sng_ss7 1 }
%{?with_py26_esl:%define build_py26_esl 1 }
######################################################################################################################
#
@ -121,6 +123,10 @@ BuildRequires: e2fsprogs-devel
BuildRequires: libtheora-devel
BuildRequires: libxml2-devel
BuildRequires: bison
%if %{build_py26_esl}
BuildRequires: python26-devel
Requires: python26
%endif
Requires: alsa-lib
Requires: libogg
Requires: libvorbis
@ -568,6 +574,7 @@ fi
cd libs/esl
%{__make} pymod
######################################################################################################################
#
# Install it and create some required dirs and links
@ -585,6 +592,16 @@ cd libs/esl
#install the esl stuff
cd libs/esl
%{__make} DESTDIR=%{buildroot} pymod-install
%if %{build_py26_esl}
#install esl for python 26
%{__make} clean
sed -i s/python\ /python26\ /g python/Makefile
%{__make} pymod
%{__mkdir} -p %{buildroot}/usr/lib/python2.6/site-packages
%{__make} DESTDIR=%{buildroot} pymod-install
%endif
cd ../..
%ifos linux

22
libs/.gitignore vendored
View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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$') ||

View File

@ -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;
}

View File

@ -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/

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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");

View File

@ -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
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);
@ -6060,6 +6061,9 @@ FT_DECLARE(ftdm_status_t) ftdm_sigmsg_get_raw_data_detached(ftdm_sigmsg_t *sigms
*data = sigmsg->raw.data;
*datalen = sigmsg->raw.len;
sigmsg->raw.data = NULL;
sigmsg->raw.len = 0;
return FTDM_SUCCESS;
}

View File

@ -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);
}
} 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);

View File

@ -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);

View File

@ -118,7 +118,7 @@
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;C:\Program Files\sangoma\sng_isdn\include&quot;;../../include;&quot;C:\Program Files\Sangoma\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="2"

View File

@ -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>

View File

@ -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);

View File

@ -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;
}

View File

@ -677,12 +677,12 @@ 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",
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_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);
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",

View File

@ -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 {

View File

@ -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);
}

View File

@ -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;

View File

@ -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");

View File

@ -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);

View File

@ -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");

View File

@ -1 +1 @@
Wed Nov 3 13:53:34 EDT 2010
Tue Mar 22 15:01:49 CDT 2011

View File

@ -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

View File

@ -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, &param);
param.sched_priority = 1;
pthread_attr_setschedparam(&attr, &param);
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);

View File

@ -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:

View File

@ -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,

View File

@ -1 +0,0 @@
Fri Mar 16 17:20:44 EDT 2007

View File

@ -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!

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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:

View File

@ -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

View File

@ -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'.

View File

@ -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

View File

@ -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).

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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.

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -143,7 +143,13 @@ sub sendmsg($$$) {
}
$self->output("\n");
return $self->readhash($to);
for(;;) {
$e = $self->readhash(undef);
last if $e->{socketerror} or $e->{'content-type'} eq 'command/reply';
push @{$self->{events}}, $e;
}
return $e;
}
sub command($$) {

View File

@ -24,6 +24,7 @@
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
* Eliot Gable <egable@gmail.com>
*
* switch_apr.h -- APR includes header
*
@ -410,6 +411,65 @@ SWITCH_DECLARE(switch_status_t) switch_mutex_trylock(switch_mutex_t *lock);
/** @} */
/**
* @defgroup switch_atomic Multi-Threaded Adtomic Operations Routines
* @ingroup switch_apr
* @{
*/
/** Opaque type used for the atomic operations */
#ifdef apr_atomic_t
typedef apr_atomic_t switch_atomic_t;
#else
typedef uint32_t switch_atomic_t;
#endif
/**
* Some architectures require atomic operations internal structures to be
* initialized before use.
* @param pool The memory pool to use when initializing the structures.
*/
SWITCH_DECLARE(switch_status_t) switch_atomic_init(switch_memory_pool_t *pool);
/**
* Uses an atomic operation to read the uint32 value at the location specified
* by mem.
* @param mem The location of memory which stores the value to read.
*/
SWITCH_DECLARE(uint32_t) switch_atomic_read(volatile switch_atomic_t *mem);
/**
* Uses an atomic operation to set a uint32 value at a specified location of
* memory.
* @param mem The location of memory to set.
* @param val The uint32 value to set at the memory location.
*/
SWITCH_DECLARE(void) switch_atomic_set(volatile switch_atomic_t *mem, uint32_t val);
/**
* Uses an atomic operation to add the uint32 value to the value at the
* specified location of memory.
* @param mem The location of the value to add to.
* @param val The uint32 value to add to the value at the memory location.
*/
SWITCH_DECLARE(void) switch_atomic_add(volatile switch_atomic_t *mem, uint32_t val);
/**
* Uses an atomic operation to increment the value at the specified memroy
* location.
* @param mem The location of the value to increment.
*/
SWITCH_DECLARE(void) switch_atomic_inc(volatile switch_atomic_t *mem);
/**
* Uses an atomic operation to decrement the value at the specified memroy
* location.
* @param mem The location of the value to decrement.
*/
SWITCH_DECLARE(int) switch_atomic_dec(volatile switch_atomic_t *mem);
/** @} */
/**
* @defgroup switch_thread_rwlock Thread Read/Write lock Routines
* @ingroup switch_apr

View File

@ -315,6 +315,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switc
*/
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension);
SWITCH_DECLARE(void) switch_channel_flip_cid(switch_channel_t *channel);
SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in);
/*!

View File

@ -1940,6 +1940,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid,
\return 0 on success
*/
SWITCH_DECLARE(int32_t) set_high_priority(void);
SWITCH_DECLARE(int32_t) set_normal_priority(void);
/*!
\brief Change user and/or group of the running process
@ -2050,6 +2051,7 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload);
SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token);
#define switch_check_network_list_ip(_ip_str, _list_name) switch_check_network_list_ip_token(_ip_str, _list_name, NULL)
SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable);
SWITCH_DECLARE(void) switch_time_set_timerfd(switch_bool_t enable);
SWITCH_DECLARE(void) switch_time_set_nanosleep(switch_bool_t enable);
SWITCH_DECLARE(void) switch_time_set_matrix(switch_bool_t enable);
SWITCH_DECLARE(void) switch_time_set_cond_yield(switch_bool_t enable);

View File

@ -542,7 +542,7 @@ typedef enum {
SWITCH_RTP_FLAG_BREAK = (1 << 10),
SWITCH_RTP_FLAG_UDPTL = (1 << 11),
SWITCH_RTP_FLAG_DATAWAIT = (1 << 12),
SWITCH_RTP_FLAG_BUGGY_2833 = (1 << 13),
SWITCH_RTP_FLAG_BYTESWAP = (1 << 13),
SWITCH_RTP_FLAG_PASS_RFC2833 = (1 << 14),
SWITCH_RTP_FLAG_AUTO_CNG = (1 << 15),
SWITCH_RTP_FLAG_SECURE_SEND_RESET = (1 << 16),
@ -1107,6 +1107,8 @@ typedef enum {
CF_DIALPLAN,
CF_BLOCK_BROADCAST_UNTIL_MEDIA,
CF_CNG_PLC,
CF_ATTENDED_TRANSFER,
CF_LAZY_ATTENDED_TRANSFER,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CF_FLAG_MAX
} switch_channel_flag_t;

1
src/mod/.gitignore vendored
View File

@ -31,6 +31,7 @@
/endpoints/mod_portaudio/Makefile.in
/endpoints/mod_skinny/Makefile
/endpoints/mod_skinny/Makefile.in
/endpoints/mod_skinny/mod_skinny.log
/endpoints/mod_skypopen/Makefile
/endpoints/mod_skypopen/Makefile.in
/endpoints/mod_sofia/Makefile

View File

@ -160,13 +160,15 @@ struct cc_member_cancel_reason_table {
typedef enum {
CC_MEMBER_CANCEL_REASON_NONE,
CC_MEMBER_CANCEL_REASON_TIMEOUT,
CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT
CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT,
CC_MEMBER_CANCEL_REASON_BREAK_OUT
} cc_member_cancel_reason_t;
static struct cc_member_cancel_reason_table MEMBER_CANCEL_REASON_CHART[] = {
{"NONE", CC_MEMBER_CANCEL_REASON_NONE},
{"TIMEOUT", CC_MEMBER_CANCEL_REASON_TIMEOUT},
{"NO_AGENT_TIMEOUT", CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT},
{"BREAK_OUT", CC_MEMBER_CANCEL_REASON_BREAK_OUT},
{NULL, 0}
};
@ -216,6 +218,7 @@ static char agents_sql[] =
" wrap_up_time INTEGER NOT NULL DEFAULT 0,\n"
" reject_delay_time INTEGER NOT NULL DEFAULT 0,\n"
" busy_delay_time INTEGER NOT NULL DEFAULT 0,\n"
" no_answer_delay_time INTEGER NOT NULL DEFAULT 0,\n"
" last_bridge_start INTEGER NOT NULL DEFAULT 0,\n"
" last_bridge_end INTEGER NOT NULL DEFAULT 0,\n"
" last_offered_call INTEGER NOT NULL DEFAULT 0,\n"
@ -705,6 +708,7 @@ static cc_queue_t *load_queue(const char *queue_name)
switch_cache_db_test_reactive(dbh, "select count(ready_time) from agents", NULL, "alter table agents add ready_time integer not null default 0;"
"alter table agents add reject_delay_time integer not null default 0;"
"alter table agents add busy_delay_time integer not null default 0;");
switch_cache_db_test_reactive(dbh, "select count(no_answer_delay_time) from agents", NULL, "alter table agents add no_answer_delay_time integer not null default 0;");
switch_cache_db_test_reactive(dbh, "select count(ready_time) from agents", "drop table agents", agents_sql);
switch_cache_db_test_reactive(dbh, "select count(queue) from tiers", "drop table tiers" , tiers_sql);
switch_mutex_init(&queue->mutex, SWITCH_MUTEX_NESTED, queue->pool);
@ -768,6 +772,7 @@ struct call_helper {
int max_no_answer;
int reject_delay_time;
int busy_delay_time;
int no_answer_delay_time;
switch_memory_pool_t *pool;
};
@ -1007,6 +1012,12 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
result = CC_STATUS_SUCCESS;
} else if (!strcasecmp(key, "no_answer_delay_time")) {
sql = switch_mprintf("UPDATE agents SET no_answer_delay_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
result = CC_STATUS_SUCCESS;
} else if (!strcasecmp(key, "type")) {
if (strcasecmp(value, CC_AGENT_TYPE_CALLBACK) && strcasecmp(value, CC_AGENT_TYPE_UUID_STANDBY)) {
@ -1203,6 +1214,7 @@ static switch_status_t load_agent(const char *agent_name)
const char *wrap_up_time = switch_xml_attr(x_agent, "wrap-up-time");
const char *reject_delay_time = switch_xml_attr(x_agent, "reject-delay-time");
const char *busy_delay_time = switch_xml_attr(x_agent, "busy-delay-time");
const char *no_answer_delay_time = switch_xml_attr(x_agent, "no-answer-delay-time");
if (type) {
cc_status_t res = cc_agent_add(agent_name, type);
@ -1225,6 +1237,9 @@ static switch_status_t load_agent(const char *agent_name)
if (busy_delay_time) {
cc_agent_update("busy_delay_time", busy_delay_time, agent_name);
}
if (no_answer_delay_time) {
cc_agent_update("no_answer_delay_time", no_answer_delay_time, agent_name);
}
if (type && res == CC_STATUS_AGENT_ALREADY_EXIST) {
cc_agent_update("type", type, agent_name);
@ -1384,8 +1399,6 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent_type", "%s", h->agent_type);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
/* Force loopback to remain live, if not, the loop will detect the actual channel to gone */
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "loopback_bowout", "false");
t_agent_called = switch_epoch_time_now(NULL);
dialstr = switch_mprintf("%s", h->originate_string);
@ -1430,9 +1443,36 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
const char *agent_uuid = switch_core_session_get_uuid(agent_session);
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session);
const char *other_loopback_leg_uuid = switch_channel_get_variable(agent_channel, "other_loopback_leg_uuid");
switch_channel_set_variable(agent_channel, "cc_member_pre_answer_uuid", NULL);
/* Loopback special case */
if (other_loopback_leg_uuid) {
switch_core_session_t *other_loopback_session = switch_core_session_locate(other_loopback_leg_uuid);
if (other_loopback_session) {
switch_channel_t *other_loopback_channel = switch_core_session_get_channel(other_loopback_session);
const char *real_uuid = switch_channel_get_variable(other_loopback_channel, SWITCH_SIGNAL_BOND_VARIABLE);
switch_channel_set_variable(other_loopback_channel, "cc_member_pre_answer_uuid", NULL);
/* Switch the agent session */
if (real_uuid) {
switch_core_session_rwunlock(agent_session);
agent_uuid = real_uuid;
agent_session = switch_core_session_locate(agent_uuid);
agent_channel = switch_core_session_get_channel(agent_session);
switch_channel_set_variable(agent_channel, "cc_queue", h->queue_name);
switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
}
switch_core_session_rwunlock(other_loopback_session);
}
}
if (!strcasecmp(h->queue_strategy,"ring-all")) {
char res[256];
/* Map the Agent to the member */
@ -1466,6 +1506,9 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
@ -1514,9 +1557,14 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_channel_event_set_data(agent_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-end");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Hangup-Cause", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Bridge-Terminated-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
@ -1542,23 +1590,25 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Hangup-Cause", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Terminated");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answer-Time", "%ld", (long) (t_agent_answered - t_agent_called));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Wait-Time", "%ld", (long) (t_agent_answered - t_member_called));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Talk-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_agent_answered));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Total-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-UUID", agent_uuid);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_fire(&event);
}
} else {
int delay_next_agent_call = 0;
/* Agent didn't answer or originate failed */
int delay_next_agent_call = 0;
sql = switch_mprintf("UPDATE members SET state = '%q', serving_agent = '', serving_system = ''"
" WHERE serving_agent = '%q' AND serving_system = '%q' AND uuid = '%q' AND system = 'single_box'",
cc_member_state2str(CC_MEMBER_STATE_WAITING),
@ -1566,33 +1616,25 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s Origination Canceled : %s\n",h->agent_name, switch_channel_cause2str(cause));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s Origination Canceled : %s\n", h->agent_name, switch_channel_cause2str(cause));
switch (cause) {
case SWITCH_CAUSE_USER_NOT_REGISTERED: /* When we are calling a unregistred device */
case SWITCH_CAUSE_USER_BUSY: /* Could be the phone is in Do Not Disturb */
delay_next_agent_call = (h->busy_delay_time > delay_next_agent_call?h->busy_delay_time:delay_next_agent_call);
break;
case SWITCH_CAUSE_CALL_REJECTED: /* User could have press the reject call on their phone */
delay_next_agent_call = (h->reject_delay_time > delay_next_agent_call?h->reject_delay_time:delay_next_agent_call);
break;
default:
break;
}
switch (cause) {
case SWITCH_CAUSE_USER_NOT_REGISTERED: /* When we are calling a unregistred device */
case SWITCH_CAUSE_USER_BUSY: /* Could be the phone is in Do Not Disturb */
case SWITCH_CAUSE_CALL_REJECTED: /* User could have press the reject call on their phone */
/* When we hang-up agents that did not answer in ring-all strategy */
case SWITCH_CAUSE_ORIGINATOR_CANCEL:
if (delay_next_agent_call > 0) {
char ready_epoch[64];
switch_snprintf(ready_epoch, sizeof(ready_epoch), "%" SWITCH_TIME_T_FMT, switch_epoch_time_now(NULL) + delay_next_agent_call); /* Make the time configurable */
cc_agent_update("ready_time", ready_epoch , h->agent_name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s Sleeping for %d secondes\n", h->agent_name, delay_next_agent_call);
}
break;
/* Busy: Do Not Disturb, Circuit congestion */
case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
case SWITCH_CAUSE_USER_BUSY:
delay_next_agent_call = (h->busy_delay_time > delay_next_agent_call? h->busy_delay_time : delay_next_agent_call);
break;
/* Reject: User rejected the call */
case SWITCH_CAUSE_CALL_REJECTED:
delay_next_agent_call = (h->reject_delay_time > delay_next_agent_call? h->reject_delay_time : delay_next_agent_call);
break;
/* No answer: Destination does not answer for some other reason */
default:
delay_next_agent_call = (h->no_answer_delay_time > delay_next_agent_call? h->no_answer_delay_time : delay_next_agent_call);
tiers_state = CC_TIER_STATE_NO_ANSWER;
/* Update Agent NO Answer count */
@ -1607,6 +1649,28 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
h->agent_name, h->max_no_answer);
cc_agent_update("status", cc_agent_status2str(CC_AGENT_STATUS_ON_BREAK), h->agent_name);
}
break;
}
/* Put agent to sleep for some time if necessary */
if (delay_next_agent_call > 0) {
char ready_epoch[64];
switch_snprintf(ready_epoch, sizeof(ready_epoch), "%" SWITCH_TIME_T_FMT, switch_epoch_time_now(NULL) + delay_next_agent_call);
cc_agent_update("ready_time", ready_epoch , h->agent_name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s sleeping for %d seconds\n", h->agent_name, delay_next_agent_call);
}
/* Fire up event when contact agent fails */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-fail");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Hangup-Cause", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_fire(&event);
}
}
@ -1670,14 +1734,14 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
char *sql = NULL;
char res[256];
char *agent_status = argv[2];
char *agent_tier_state = argv[8];
char *agent_last_bridge_end = argv[9];
char *agent_wrap_up_time = argv[10];
char *agent_state = argv[11];
char *agent_ready_time = argv[12];
char *agent_tier_level = argv[13];
char *agent_type = argv[14];
char *agent_uuid = argv[15];
char *agent_tier_state = argv[9];
char *agent_last_bridge_end = argv[10];
char *agent_wrap_up_time = argv[11];
char *agent_state = argv[12];
char *agent_ready_time = argv[13];
char *agent_tier_level = argv[14];
char *agent_type = argv[15];
char *agent_uuid = argv[16];
switch_bool_t contact_agent = SWITCH_TRUE;
@ -1787,6 +1851,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
h->max_no_answer = atoi(argv[5]);
h->reject_delay_time = atoi(argv[6]);
h->busy_delay_time = atoi(argv[7]);
h->no_answer_delay_time = atoi(argv[8]);
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_RECEIVING), h->agent_name);
@ -1895,13 +1960,13 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
switch_safe_free(sql);
sql_order_by = switch_mprintf("level, position");
} else if(!strcasecmp(queue_strategy, "sequentially-by-agent-order")) {
sql_order_by = switch_mprintf("level, position");
sql_order_by = switch_mprintf("level, position, agents.last_offered_call"); /* Default to last_offered_call, let add new strategy if needing it differently */
} else {
/* If the strategy doesn't exist, just fallback to the following */
sql_order_by = switch_mprintf("level, position");
sql_order_by = switch_mprintf("level, position, agents.last_offered_call");
}
sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time,tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.level, agents.type, agents.uuid FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.level, agents.type, agents.uuid FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)"
" WHERE tiers.queue = '%q'"
" AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')"
" ORDER BY %q",
@ -2045,7 +2110,7 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
}
/* Will drop the caller if no agent was found for more than X secondes */
/* Will drop the caller if no agent was found for more than X seconds */
if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - queue->max_wait_time_with_no_agent_time_reached &&
queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) {
m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT;
@ -2301,52 +2366,63 @@ SWITCH_STANDARD_APP(callcenter_function)
h->running = 0;
}
/* Hangup any agents been callback */
if (!switch_channel_up(member_channel)) { /* If channel is still up, it mean that the member didn't hangup, so we should leave the agent alone */
switch_core_session_hupall_matching_var("cc_member_uuid", member_uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL);
/* Check if we were removed be cause FS Core(BREAK) asked us too */
if (h->member_cancel_reason == CC_MEMBER_CANCEL_REASON_NONE && !switch_channel_get_variable(member_channel, "cc_agent_uuid")) {
h->member_cancel_reason = CC_MEMBER_CANCEL_REASON_BREAK_OUT;
}
/* Canceled for some reason */
if (!switch_channel_up(member_channel) || h->member_cancel_reason != CC_MEMBER_CANCEL_REASON_NONE) {
/* Update member state */
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
/* Generate an Event and update some channel variable */
/* Hangup any callback agents */
switch_core_session_hupall_matching_var("cc_member_uuid", member_uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL);
/* Generate an event */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Wait-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Member \"%s\" <%s> exit queue %s due to %s\n",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")),
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")),
queue_name, cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Cancel");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cancel-Reason", cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_fire(&event);
}
/* for xml_cdr needs */
/* Update some channel variables for xml_cdr needs */
switch_channel_set_variable_printf(member_channel, "cc_queue_canceled_epoch", "%ld", (long) switch_epoch_time_now(NULL));
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", cc_member_cancel_reason2str(h->member_cancel_reason));
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "cancel");
switch_channel_set_variable_printf(member_channel, "cc_cancel_reason", "%s", cc_member_cancel_reason2str(h->member_cancel_reason));
/* Send Event with queue count */
cc_queue_count(queue_name);
/* Print some debug log information */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Member \"%s\" <%s> exit queue %s due to %s\n",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")),
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")),
queue_name, cc_member_cancel_reason2str(h->member_cancel_reason));
} else {
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "answered");
/* Update member state */
sql = switch_mprintf("UPDATE members SET state = '%q', bridge_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ANSWERED), (long) switch_epoch_time_now(NULL), member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
/* Send Event with queue count */
cc_queue_count(queue_name);
/* Update some channel variables for xml_cdr needs */
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "answered");
}
/* Send Event with queue count */
cc_queue_count(queue_name);
end:
return;
@ -2394,18 +2470,26 @@ static int list_result_callback(void *pArg, int argc, char **argv, char **column
"callcenter_config agent set ready_time [agent_name] [wait till epoch] | "\
"callcenter_config agent set reject_delay_time [agent_name] [wait second] | "\
"callcenter_config agent set busy_delay_time [agent_name] [wait second] | "\
"callcenter_config agent set no_answer_delay_time [agent_name] [wait second] | "\
"callcenter_config agent get status [agent_name] | " \
"callcenter_config agent list | " \
"callcenter_config tier add [queue_name] [agent_name] [level] [position] | " \
"callcenter_config tier set state [queue_name] [agent_name] [state] | " \
"callcenter_config tier set level [queue_name] [agent_name] [level] | " \
"callcenter_config tier set position [queue_name] [agent_name] [position] | " \
"callcenter_config tier del [queue_name] [agent_name] | " \
"callcenter_config tier list | " \
"callcenter_config queue load [queue_name] | " \
"callcenter_config queue unload [queue_name] | " \
"callcenter_config queue reload [queue_name] | " \
"callcenter_config tier list [queue_name] | " \
"callcenter_config queue list [queue_name] | " \
"callcenter_config queue count [queue_name]"
"callcenter_config queue list | " \
"callcenter_config queue list agents [queue_name] [status] | " \
"callcenter_config queue list members [queue_name] | " \
"callcenter_config queue list tiers [queue_name] | " \
"callcenter_config queue count | " \
"callcenter_config queue count agents [queue_name] [status] | " \
"callcenter_config queue count members [queue_name] | " \
"callcenter_config queue count tiers [queue_name]"
SWITCH_STANDARD_API(cc_config_api_function)
{
@ -2513,6 +2597,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
}
}
} else if (action && !strcasecmp(action, "get")) {
if (argc-initial_argc < 2) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
@ -2538,6 +2623,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
}
}
} else if (action && !strcasecmp(action, "list")) {
struct list_result cbt;
cbt.row_process = 0;
@ -2616,6 +2702,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
goto done;
}
}
} else if (action && !strcasecmp(action, "del")) {
if (argc-initial_argc < 2) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
@ -2635,20 +2722,14 @@ SWITCH_STANDARD_API(cc_config_api_function)
}
} else if (action && !strcasecmp(action, "list")) {
if (argc-initial_argc < 1) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
goto done;
} else {
const char *queue = argv[0 + initial_argc];
struct list_result cbt;
cbt.row_process = 0;
cbt.stream = stream;
sql = switch_mprintf("SELECT * FROM tiers WHERE queue = '%q' ORDER BY level, position", queue);
sql = switch_mprintf("SELECT * FROM tiers ORDER BY level, position");
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
stream->write_function(stream, "%s", "+OK\n");
}
}
} else if (section && !strcasecmp(section, "queue")) {
if (action && !strcasecmp(action, "load")) {
if (argc-initial_argc < 1) {
@ -2664,6 +2745,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%s", "-ERR Invalid Queue not found!\n");
}
}
} else if (action && !strcasecmp(action, "unload")) {
if (argc-initial_argc < 1) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
@ -2674,6 +2756,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%s", "+OK\n");
}
} else if (action && !strcasecmp(action, "reload")) {
if (argc-initial_argc < 1) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
@ -2689,7 +2772,9 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%s", "-ERR Invalid Queue not found!\n");
}
}
} else if (action && !strcasecmp(action, "list")) {
/* queue list */
if (argc-initial_argc < 1) {
switch_hash_index_t *hi;
stream->write_function(stream, "%s", "name|strategy|moh_sound|time_base_score|tier_rules_apply|tier_rule_wait_second|tier_rule_wait_multiply_level|tier_rule_no_agent_no_wait|discard_abandoned_after|abandoned_resume_allowed|max_wait_time|max_wait_time_with_no_agent|max_wait_time_with_no_agent_time_reached|record_template\n");
@ -2708,35 +2793,81 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%s", "+OK\n");
goto done;
} else {
const char *queue_name = argv[0 + initial_argc];
const char *sub_action = argv[0 + initial_argc];
const char *queue_name = argv[1 + initial_argc];
const char *status = NULL;
struct list_result cbt;
/* queue list agents */
if (sub_action && !strcasecmp(sub_action, "agents")) {
if (argc-initial_argc > 2) {
status = argv[2 + initial_argc];
}
if (status) {
sql = switch_mprintf("SELECT agents.* FROM agents,tiers WHERE tiers.agent = agents.name AND tiers.queue = '%q' AND agents.status = '%q'", queue_name, status);
} else {
sql = switch_mprintf("SELECT agents.* FROM agents,tiers WHERE tiers.agent = agents.name AND tiers.queue = '%q'", queue_name);
}
/* queue list members */
} else if (sub_action && !strcasecmp(sub_action, "members")) {
sql = switch_mprintf("SELECT * FROM members WHERE queue = '%q';", queue_name);
/* queue list tiers */
} else if (sub_action && !strcasecmp(sub_action, "tiers")) {
sql = switch_mprintf("SELECT * FROM tiers WHERE queue = '%q';", queue_name);
} else {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
goto done;
}
cbt.row_process = 0;
cbt.stream = stream;
sql = switch_mprintf("SELECT * FROM members WHERE queue = '%q'", queue_name);
cc_execute_sql_callback(NULL /* queue */, NULL /* mutex */, sql, list_result_callback, &cbt /* Call back variables */);
switch_safe_free(sql);
stream->write_function(stream, "%s", "+OK\n");
}
} else if (action && !strcasecmp(action, "count")) {
/* queue count */
if (argc-initial_argc < 1) {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
switch_hash_index_t *hi;
int queue_count = 0;
switch_mutex_lock(globals.mutex);
for (hi = switch_hash_first(NULL, globals.queue_hash); hi; hi = switch_hash_next(hi)) {
queue_count++;
}
switch_mutex_unlock(globals.mutex);
stream->write_function(stream, "%d\n", queue_count);
goto done;
} else {
const char *queue_name = argv[0 + initial_argc];
const char *sub_action = argv[0 + initial_argc];
const char *queue_name = argv[1 + initial_argc];
const char *status = NULL;
char res[256] = "";
switch_event_t *event;
/* Check to see if agent already exist */
sql = switch_mprintf("SELECT count(*) FROM members WHERE queue = '%q'", queue_name);
/* queue count agents */
if (sub_action && !strcasecmp(sub_action, "agents")) {
if (argc-initial_argc > 2) {
status = argv[2 + initial_argc];
}
if (status) {
sql = switch_mprintf("SELECT count(*) FROM agents,tiers WHERE tiers.agent = agents.name AND tiers.queue = '%q' AND agents.status = '%q'", queue_name, status);
} else {
sql = switch_mprintf("SELECT count(*) FROM agents,tiers WHERE tiers.agent = agents.name AND tiers.queue = '%q'", queue_name);
}
/* queue count members */
} else if (sub_action && !strcasecmp(sub_action, "members")) {
sql = switch_mprintf("SELECT count(*) FROM members WHERE queue = '%q';", queue_name);
/* queue count tiers */
} else if (sub_action && !strcasecmp(sub_action, "tiers")) {
sql = switch_mprintf("SELECT count(*) FROM tiers WHERE queue = '%q';", queue_name);
} else {
stream->write_function(stream, "%s", "-ERR Invalid!\n");
goto done;
}
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
stream->write_function(stream, "%d\n", atoi(res));
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res);
switch_event_fire(&event);
}
}
}
}
@ -2789,10 +2920,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_callcenter_load)
switch_console_set_complete("add callcenter_config agent set ready_time");
switch_console_set_complete("add callcenter_config agent set reject_delay_time");
switch_console_set_complete("add callcenter_config agent set busy_delay_time");
switch_console_set_complete("add callcenter_config agent set no_answer_delay_time");
switch_console_set_complete("add callcenter_config agent get status");
switch_console_set_complete("add callcenter_config agent list");
switch_console_set_complete("add callcenter_config tier add");
switch_console_set_complete("add callcenter_config tier del");
switch_console_set_complete("add callcenter_config tier set state");
@ -2804,7 +2935,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_callcenter_load)
switch_console_set_complete("add callcenter_config queue unload");
switch_console_set_complete("add callcenter_config queue reload");
switch_console_set_complete("add callcenter_config queue list");
switch_console_set_complete("add callcenter_config queue list agents");
switch_console_set_complete("add callcenter_config queue list members");
switch_console_set_complete("add callcenter_config queue list tiers");
switch_console_set_complete("add callcenter_config queue count");
switch_console_set_complete("add callcenter_config queue count agents");
switch_console_set_complete("add callcenter_config queue count members");
switch_console_set_complete("add callcenter_config queue count tiers");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;

View File

@ -37,6 +37,7 @@
*/
#include <switch.h>
#define DEFAULT_AGC_LEVEL 1100
#define CONFERENCE_UUID_VARIABLE "conference_uuid"
SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown);
@ -564,7 +565,10 @@ static conference_member_t *conference_member_get(conference_obj_t *conference,
member = NULL;
}
if (member) {
switch_thread_rwlock_rdlock(member->rwlock);
}
switch_mutex_unlock(conference->member_mutex);
return member;
@ -702,6 +706,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
channel = switch_core_session_get_channel(member->session);
switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
switch_channel_set_variable(channel, CONFERENCE_UUID_VARIABLE, conference->uuid_str);
if (conference->count > 1) {
if (conference->moh_sound && !switch_test_flag(conference, CFLAG_WAIT_MOD)) {
@ -4625,6 +4630,7 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
/* move the member from the old conference to the new one */
lock_member(member);
switch_thread_rwlock_unlock(member->rwlock);
if (conference != new_conference) {
conference_del_member(conference, member);
@ -4660,10 +4666,6 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "transfer");
switch_event_fire(&event);
}
if (member) {
switch_thread_rwlock_unlock(member->rwlock);
}
}
if (new_conference) {

View File

@ -0,0 +1,34 @@
# LDNS=ldns-1.6.9
# BASE=../../../..
# LDNS_DIR=$(switch_srcdir)/libs/$(LDNS)
# LDNS_BUILDDIR=$(switch_builddir)/libs/$(LDNS)
# LDNSLA=$(LDNS_BUILDDIR)/libldns.la
# include $(BASE)/build/modmake.rules
# LOCAL_LIBADD=$(LDNSLA)
BASE=../../../..
LDNS=ldns-1.6.9
LDNS_DIR=$(switch_srcdir)/libs/$(LDNS)
LDNS_BUILDDIR=$(switch_builddir)/libs/$(LDNS)
LOCAL_CFLAGS=-I$(LDNS_DIR) -I$(LDNS_DIR)/include
LDNS_LA=$(LDNS_BUILDDIR)/libldns.la
LOCAL_LIBADD=$(LDNS_LA)
include $(BASE)/build/modmake.rules
$(LDNS_DIR)/Makefile.in:
$(GETLIB) $(LDNS).tar.gz
$(LDNS_BUILDDIR)/Makefile: $(LDNS_DIR)/Makefile.in
mkdir -p $(LDNS_BUILDDIR)
cd $(LDNS_BUILDDIR) && $(DEFAULT_VARS) $(LDNS_DIR)/configure $(DEFAULT_ARGS) --srcdir=$(LDNS_DIR) --disable-gost --without-ssl --disable-sha2
$(TOUCH_TARGET)
$(LDNS_LA): $(LDNS_BUILDDIR)/Makefile
cd $(LDNS_BUILDDIR) && $(MAKE)
$(TOUCH_TARGET)

View File

@ -1,13 +0,0 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_enum
UDNS_DIR=$(switch_srcdir)/libs/udns
mod_enum_la_CFLAGS = -I$(UDNS_DIR) -DHAVE_POLL $(AM_CFLAGS)
mod_LTLIBRARIES = mod_enum.la
mod_enum_la_SOURCES = mod_enum.c
mod_enum_la_SOURCES += $(UDNS_DIR)/udns_dn.c $(UDNS_DIR)/udns_dntosp.c $(UDNS_DIR)/udns_parse.c $(UDNS_DIR)/udns_misc.c
mod_enum_la_SOURCES += $(UDNS_DIR)/udns_rr_a.c $(UDNS_DIR)/udns_rr_ptr.c $(UDNS_DIR)/udns_rr_mx.c $(UDNS_DIR)/udns_rr_txt.c $(UDNS_DIR)/udns_bl.c
mod_enum_la_SOURCES += $(UDNS_DIR)/udns_rr_srv.c $(UDNS_DIR)/udns_rr_naptr.c $(UDNS_DIR)/udns_codes.c $(UDNS_DIR)/udns_resolver.c
mod_enum_la_LIBADD = $(switch_builddir)/libfreeswitch.la
mod_enum_la_LDFLAGS = -avoid-version -module -no-undefined -shared

View File

@ -30,11 +30,7 @@
*/
#include <switch.h>
#include <udns.h>
#ifndef WIN32
#define closesocket close
#endif
#include <ldns/ldns.h>
SWITCH_MODULE_LOAD_FUNCTION(mod_enum_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_enum_shutdown);
@ -49,19 +45,10 @@ struct enum_record {
char *route;
int supported;
struct enum_record *next;
struct enum_record *tail;
};
typedef struct enum_record enum_record_t;
struct query {
const char *name; /* original query string */
char *number;
unsigned char dn[DNS_MAXDN];
enum dns_type qtyp; /* type of the query */
enum_record_t *results;
int errs;
};
typedef struct query enum_query_t;
struct route {
char *service;
char *regex;
@ -70,12 +57,11 @@ struct route {
};
typedef struct route enum_route_t;
static enum dns_class qcls = DNS_C_IN;
static switch_event_node_t *NODE = NULL;
static struct {
char *root;
char *server;
char *isn_root;
enum_route_t *route_order;
switch_memory_pool_t *pool;
@ -84,6 +70,7 @@ static struct {
} globals;
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_root, globals.root);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_server, globals.server);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_isn_root, globals.isn_root);
static void add_route(char *service, char *regex, char *replace)
@ -125,6 +112,8 @@ static switch_status_t load_config(void)
const char *val = switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "default-root")) {
set_global_root(val);
} else if (!strcasecmp(var, "use-server")) {
set_global_server(val);
} else if (!strcasecmp(var, "auto-reload")) {
globals.auto_reload = switch_true(val);
} else if (!strcasecmp(var, "query-timeout")) {
@ -168,11 +157,12 @@ static switch_status_t load_config(void)
return status;
}
static char *reverse_number(char *in, char *root)
static char *reverse_number(const char *in, const char *root)
{
switch_size_t len;
char *out = NULL;
char *y, *z;
const char *y;
char *z;
if (!(in && root)) {
return NULL;
@ -198,59 +188,33 @@ static char *reverse_number(char *in, char *root)
return out;
}
static void dnserror(enum_query_t *q, int errnum)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unable to lookup %s record for %s: %s\n",
dns_typename(q->qtyp), dns_dntosp(q->dn), dns_strerror(errnum));
q->errs++;
}
static void add_result(enum_query_t *q, int order, int preference, char *service, char *route, int supported)
static void add_result(enum_record_t **results, int order, int preference, char *service, char *route, int supported)
{
enum_record_t *new_result, *rp, *prev = NULL;
enum_record_t *new_result;
new_result = malloc(sizeof(*new_result));
switch_assert(new_result);
memset(new_result, 0, sizeof(*new_result));
memset(new_result, 0, sizeof(*new_result));
new_result->order = order;
new_result->preference = preference;
new_result->service = strdup(service);
new_result->route = strdup(route);
new_result->supported = supported;
if (!q->results) {
q->results = new_result;
return;
}
rp = q->results;
while (rp && strcasecmp(rp->service, new_result->service)) {
prev = rp;
rp = rp->next;
}
while (rp && !strcasecmp(rp->service, new_result->service) && new_result->order > rp->order) {
prev = rp;
rp = rp->next;
}
while (rp && !strcasecmp(rp->service, new_result->service) && new_result->preference > rp->preference) {
prev = rp;
rp = rp->next;
}
if (prev) {
new_result->next = rp;
prev->next = new_result;
if (!*results) {
*results = new_result;
(*results)->tail = new_result;
} else {
new_result->next = rp;
q->results = new_result;
(*results)->tail->next = new_result;
(*results)->tail = new_result;
}
}
static void free_results(enum_record_t ** results)
{
enum_record_t *fp, *rp;
@ -265,88 +229,100 @@ static void free_results(enum_record_t ** results)
*results = NULL;
}
static void parse_rr(const struct dns_parse *p, enum_query_t *q, struct dns_rr *rr)
static ldns_rdf *ldns_rdf_new_addr_frm_str(const char *str)
{
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;
char flags;
int order;
int preference;
ldns_rdf *a;
ldns_str2rdf_a(&a, str);
if (!a) {
/* maybe ip6 */
ldns_str2rdf_aaaa(&a, str);
if (!a) {
return NULL;
}
}
return a;
}
#define strip_quotes(_s) if (*_s == '"') _s++; if (end_of(_s) == '"') end_of(_s) = '\0'
static void parse_naptr(const ldns_rr *naptr, const char *number, enum_record_t **results)
{
char *str = ldns_rr2str(naptr);
char *argv[11] = { 0 };
int i, argc;
char *pack[4] = { 0 };
int packc;
char *p;
int order = 10;
int preference = 100;
char *service = NULL;
char *regex = NULL;
char *replace = NULL;
char *ptr;
int argc = 0;
char *argv[4] = { 0 };
int n;
char string_arg[3][256] = { {0} };
char *packstr;
switch (rr->dnsrr_typ) {
case DNS_T_NAPTR: /* prio weight port targetDN */
c = dptr;
c += 4; /* order, pref */
char *regex, *replace;
for (n = 0; n < 3; ++n) {
if (c >= dend) {
goto xperr;
if (zstr(str)) {
return;
}
for (p = str; p && *p; p++) {
if (*p == '\t') *p = ' ';
if (*p == ' ' && *(p+1) == '.') *p = '\0';
}
argc = switch_split(str, ' ', argv);
for (i = 0; i < argc; i++) {
if (i > 0) {
strip_quotes(argv[i]);
}
}
service = argv[7];
packstr = argv[8];
if (zstr(service) || zstr(packstr)) {
goto end;
}
if (!zstr(argv[4])) {
order = atoi(argv[4]);
}
if (!zstr(argv[5])) {
preference = atoi(argv[5]);
}
if ((packc = switch_split(packstr, '!', pack))) {
regex = pack[1];
replace = pack[2];
} else {
c += *c + 1;
goto end;
}
for (p = replace; p && *p; p++) {
if (*p == '\\') {
*p = '$';
}
}
if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0 || c != dend) {
goto xperr;
}
c = dptr;
order = dns_get16(c + 0);
preference = dns_get16(c + 2);
flags = (char) dns_get16(c + 4);
c += 4;
for (n = 0; n < 3; n++) {
uint32_t len = *c++, cpylen = len;
switch_assert(string_arg[n]);
if (len > sizeof(string_arg[n]) - 1) {
cpylen = sizeof(string_arg[n]) - 1;
}
strncpy(string_arg[n], (char *) c, cpylen);
*(string_arg[n] + len) = '\0';
c += len;
}
service = string_arg[1];
if ((argc = switch_separate_string(string_arg[2], '!', argv, (sizeof(argv) / sizeof(argv[0]))))) {
regex = argv[1];
replace = argv[2];
} else {
goto xperr;
}
for (ptr = replace; ptr && *ptr; ptr++) {
if (*ptr == '\\') {
*ptr = '$';
}
}
if (flags && service && regex && replace) {
switch_regex_t *re = NULL;
if (service && regex && replace) {
switch_regex_t *re = NULL, *re2 = NULL;
int proceed = 0, ovector[30];
char substituted[1024] = "";
char rbuf[1024] = "";
char *uri;
enum_route_t *route;
int supported = 0;
switch_regex_safe_free(re);
if ((proceed = switch_regex_perform(q->number, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
if ((proceed = switch_regex_perform(number, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
if (strchr(regex, '(')) {
switch_perform_substitution(re, proceed, replace, q->number, substituted, sizeof(substituted), ovector);
switch_perform_substitution(re, proceed, replace, number, substituted, sizeof(substituted), ovector);
uri = substituted;
} else {
uri = replace;
@ -357,109 +333,130 @@ static void parse_rr(const struct dns_parse *p, enum_query_t *q, struct dns_rr *
if (strcasecmp(service, route->service)) {
continue;
}
switch_regex_safe_free(re);
if ((proceed = switch_regex_perform(uri, route->regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
if ((proceed = switch_regex_perform(uri, route->regex, &re2, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
if (strchr(route->regex, '(')) {
switch_perform_substitution(re, proceed, route->replace, uri, rbuf, sizeof(rbuf), ovector);
switch_perform_substitution(re2, proceed, route->replace, uri, rbuf, sizeof(rbuf), ovector);
uri = rbuf;
} else {
uri = route->replace;
}
supported++;
add_result(q, order, preference, service, uri, supported);
}
}
if (!supported) {
add_result(q, order, preference, service, uri, 0);
add_result(results, order, preference, service, uri, supported);
}
switch_regex_safe_free(re2);
}
switch_mutex_unlock(MUTEX);
if (!supported) {
add_result(results, order, preference, service, uri, 0);
}
switch_regex_safe_free(re);
}
break;
default:
break;
}
return;
end:
xperr:
switch_safe_free(str);
return;
}
static void dnscb(struct dns_ctx *ctx, void *result, void *data)
switch_status_t ldns_lookup(const char *number, const char *root, const char *server_name, enum_record_t **results)
{
int r = dns_status(ctx);
enum_query_t *q = data;
struct dns_parse p;
struct dns_rr rr;
unsigned nrr;
unsigned char dn[DNS_MAXDN];
const unsigned char *pkt, *cur, *end, *qdn;
if (!result) {
dnserror(q, r);
return;
ldns_resolver *res = NULL;
ldns_rdf *domain = NULL;
ldns_pkt *p = NULL;
ldns_rr_list *naptr = NULL;
ldns_status s = LDNS_STATUS_ERR;
ldns_rdf *serv_rdf;
switch_status_t status = SWITCH_STATUS_FALSE;
char *name = NULL;
if (!(name = reverse_number(number, root))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Parse Error!\n");
goto end;
}
domain = ldns_dname_new_frm_str(name);
if (!domain) {
goto end;
}
if (!zstr(server_name)) {
res = ldns_resolver_new();
switch_assert(res);
if ((serv_rdf = ldns_rdf_new_addr_frm_str(server_name))) {
s = ldns_resolver_push_nameserver(res, serv_rdf);
ldns_rdf_deep_free(serv_rdf);
}
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 = 0;
p.dnsp_qtyp = 0;
qdn = dn;
nrr = 0;
while ((r = dns_nextrr(&p, &rr)) > 0) {
if (!dns_dnequal(qdn, 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 {
qdn = p.dnsp_dnbuf;
}
}
}
if (!r && !nrr)
r = DNS_E_NODATA;
if (r < 0) {
dnserror(q, r);
free(result);
return;
/* create a new resolver from /etc/resolv.conf */
s = ldns_resolver_new_frm_file(&res, NULL);
}
dns_rewind(&p, NULL);
p.dnsp_qtyp = q->qtyp;
p.dnsp_qcls = qcls;
while (dns_nextrr(&p, &rr)) {
parse_rr(&p, q, &rr);
if (s != LDNS_STATUS_OK) {
goto end;
}
free(result);
/* use the resolver to send a query for the naptr
* records of the domain given on the command line
*/
if ((p = ldns_resolver_query(res,
domain,
LDNS_RR_TYPE_NAPTR,
LDNS_RR_CLASS_IN,
LDNS_RD))) {
/* retrieve the NAPTR records from the answer section of that
* packet
*/
if ((naptr = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NAPTR, LDNS_SECTION_ANSWER))) {
size_t i;
ldns_rr_list_sort(naptr);
for (i = 0; i < ldns_rr_list_rr_count(naptr); i++) {
parse_naptr(ldns_rr_list_rr(naptr, i), number, results);
}
//ldns_rr_list_print(stdout, naptr);
ldns_rr_list_deep_free(naptr);
status = SWITCH_STATUS_SUCCESS;
}
}
end:
switch_safe_free(name);
if (domain) {
ldns_rdf_deep_free(domain);
}
if (p) {
ldns_pkt_free(p);
}
if (res) {
ldns_resolver_deep_free(res);
}
return status;
}
static switch_status_t enum_lookup(char *root, char *in, enum_record_t ** results)
static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results)
{
switch_status_t sstatus = SWITCH_STATUS_SUCCESS;
char *name = NULL;
enum_query_t query = { 0 };
enum dns_type l_qtyp = DNS_T_NAPTR;
int i = 0, abs = 0, j = 0;
dns_socket fd = (dns_socket) - 1;
fd_set fds;
struct timeval tv = { 0 };
time_t now = 0;
struct dns_ctx *nctx = NULL;
char *num, *mnum = NULL, *mroot = NULL, *p;
char *mnum = NULL, *mroot = NULL, *p;
char *server = NULL;
*results = NULL;
@ -475,87 +472,14 @@ static switch_status_t enum_lookup(char *root, char *in, enum_record_t ** result
root = globals.root;
}
num = mnum;
if (!(name = reverse_number(num, root))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Parse Error!\n");
sstatus = SWITCH_STATUS_FALSE;
goto done;
#if 0
if (!(server = switch_core_get_variable("enum-server"))) {
server = globals.server;
}
if (!(nctx = dns_new(NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Memory Error!\n");
sstatus = SWITCH_STATUS_MEMERR;
goto done;
}
fd = dns_open(nctx);
if (fd < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FD Error!\n");
sstatus = SWITCH_STATUS_FALSE;
goto done;
}
dns_ptodn(name, (unsigned int) strlen(name), query.dn, sizeof(query.dn), &abs);
query.name = name;
query.number = num;
query.qtyp = l_qtyp;
if (abs) {
abs = DNS_NOSRCH;
}
if (!dns_submit_dn(nctx, query.dn, qcls, l_qtyp, abs, 0, dnscb, &query)) {
dnserror(&query, dns_status(nctx));
}
FD_ZERO(&fds);
now = 0;
while ((i = dns_timeouts(nctx, 1, now)) > 0) {
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4389 4127)
#endif
FD_SET(fd, &fds);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
j += i;
ldns_lookup(mnum, root, server, results);
if (j > globals.timeout || query.results || query.errs) {
break;
}
tv.tv_sec = i;
tv.tv_usec = 0;
i = select((int) (fd + 1), &fds, 0, 0, &tv);
now = switch_epoch_time_now(NULL);
if (i > 0) {
dns_ioevent(nctx, now);
}
}
if (!query.results) {
sstatus = SWITCH_STATUS_FALSE;
}
*results = query.results;
query.results = NULL;
done:
if (fd > -1) {
closesocket(fd);
fd = (dns_socket) - 1;
}
if (nctx) {
dns_free(nctx);
}
switch_safe_free(name);
switch_safe_free(mnum);
switch_safe_free(mroot);
@ -623,15 +547,17 @@ SWITCH_STANDARD_APP(enum_app_function)
dest = argv[0];
root = argv[1];
if (enum_lookup(root, dest, &results) == SWITCH_STATUS_SUCCESS) {
switch_event_t *vars;
if (switch_channel_get_variables(channel, &vars) == SWITCH_STATUS_SUCCESS) {
switch_event_header_t *hi;
if ((hi = switch_channel_variable_first(channel))) {
for (; hi; hi = hi->next) {
for (hi = vars->headers; hi; hi = hi->next) {
char *vvar = hi->name;
if (vvar && !strncmp(vvar, "enum_", 5)) {
switch_channel_set_variable(channel, (char *) vvar, NULL);
}
}
switch_channel_variable_last(channel);
switch_event_destroy(&vars);
}
for (rp = results; rp; rp = rp->next) {
@ -823,9 +749,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_enum_load)
return SWITCH_STATUS_TERM;
}
if (dns_init(0) < 0) {
return SWITCH_STATUS_FALSE;
}
memset(&globals, 0, sizeof(globals));
do_load();

View File

@ -0,0 +1,5 @@
BASE=../../../..
LOCAL_OBJS += load.o
include $(BASE)/build/modmake.rules

View File

@ -0,0 +1,173 @@
/* load.c
Free software by Richard W.E. Furse. Do with as you will. No
warranty. */
/*****************************************************************************/
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*****************************************************************************/
#include "ladspa.h"
#include "utils.h"
#include "inttypes.h"
#include "switch.h"
/*****************************************************************************/
/* This function provides a wrapping of dlopen(). When the filename is
not an absolute path (i.e. does not begin with / character), this
routine will search the LADSPA_PATH for the file. */
static void *dlopenLADSPA(const char *pcFilename, int iFlag)
{
char *pcBuffer;
const char *pcEnd;
const char *pcLADSPAPath;
const char *pcStart;
int iEndsInSO;
int iNeedSlash;
size_t iFilenameLength;
void *pvResult;
iFilenameLength = strlen(pcFilename);
pvResult = NULL;
if (pcFilename[0] == '/') {
/* The filename is absolute. Assume the user knows what he/she is
doing and simply dlopen() it. */
pvResult = dlopen(pcFilename, iFlag);
if (pvResult != NULL)
return pvResult;
} else {
/* If the filename is not absolute then we wish to check along the
LADSPA_PATH path to see if we can find the file there. We do
NOT call dlopen() directly as this would find plugins on the
LD_LIBRARY_PATH, whereas the LADSPA_PATH is the correct place
to search. */
pcLADSPAPath = getenv("LADSPA_PATH");
if (pcLADSPAPath) {
pcStart = pcLADSPAPath;
while (*pcStart != '\0') {
pcEnd = pcStart;
while (*pcEnd != ':' && *pcEnd != '\0')
pcEnd++;
pcBuffer = malloc(iFilenameLength + 2 + (pcEnd - pcStart));
if (pcEnd > pcStart)
strncpy(pcBuffer, pcStart, pcEnd - pcStart);
iNeedSlash = 0;
if (pcEnd > pcStart)
if (*(pcEnd - 1) != '/') {
iNeedSlash = 1;
pcBuffer[pcEnd - pcStart] = '/';
}
strcpy(pcBuffer + iNeedSlash + (pcEnd - pcStart), pcFilename);
pvResult = dlopen(pcBuffer, iFlag);
free(pcBuffer);
if (pvResult != NULL)
return pvResult;
pcStart = pcEnd;
if (*pcStart == ':')
pcStart++;
}
}
}
/* As a last ditch effort, check if filename does not end with
".so". In this case, add this suffix and recurse. */
iEndsInSO = 0;
if (iFilenameLength > 3)
iEndsInSO = (strcmp(pcFilename + iFilenameLength - 3, ".so") == 0);
if (!iEndsInSO) {
pcBuffer = malloc(iFilenameLength + 4);
strcpy(pcBuffer, pcFilename);
strcat(pcBuffer, ".so");
pvResult = dlopenLADSPA(pcBuffer, iFlag);
free(pcBuffer);
}
if (pvResult != NULL)
return pvResult;
/* If nothing has worked, then at least we can make sure we set the
correct error message - and this should correspond to a call to
dlopen() with the actual filename requested. The dlopen() manual
page does not specify whether the first or last error message
will be kept when multiple calls are made to dlopen(). We've
covered the former case - now we can handle the latter by calling
dlopen() again here. */
return dlopen(pcFilename, iFlag);
}
/*****************************************************************************/
void *loadLADSPAPluginLibrary(const char *pcPluginFilename)
{
void *pvPluginHandle;
pvPluginHandle = dlopenLADSPA(pcPluginFilename, RTLD_NOW);
if (!pvPluginHandle) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load plugin \"%s\": %s\n", pcPluginFilename, dlerror());
}
return pvPluginHandle;
}
/*****************************************************************************/
void unloadLADSPAPluginLibrary(void *pvLADSPAPluginLibrary)
{
dlclose(pvLADSPAPluginLibrary);
}
/*****************************************************************************/
const LADSPA_Descriptor *findLADSPAPluginDescriptor(void *pvLADSPAPluginLibrary, const char *pcPluginLibraryFilename, const char *pcPluginLabel)
{
const LADSPA_Descriptor *psDescriptor;
LADSPA_Descriptor_Function pfDescriptorFunction;
unsigned long lPluginIndex;
dlerror();
pfDescriptorFunction = (LADSPA_Descriptor_Function) (intptr_t)dlsym(pvLADSPAPluginLibrary, "ladspa_descriptor");
if (!pfDescriptorFunction) {
const char *pcError = dlerror();
if (pcError) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Unable to find ladspa_descriptor() function in plugin "
"library file \"%s\": %s.\n" "Are you sure this is a LADSPA plugin file?\n", pcPluginLibraryFilename, pcError);
return NULL;
}
}
for (lPluginIndex = 0;; lPluginIndex++) {
psDescriptor = pfDescriptorFunction(lPluginIndex);
if (psDescriptor == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Unable to find label \"%s\" in plugin library file \"%s\".\n", pcPluginLabel, pcPluginLibraryFilename);
return NULL;
}
if (strcmp(psDescriptor->Label, pcPluginLabel) == 0)
return psDescriptor;
}
}
/*****************************************************************************/
/* EOF */

View File

@ -0,0 +1,674 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
* mod_ladspa.c -- LADSPA
*
*/
#include <switch.h>
#include "ladspa.h"
#include "utils.h"
/* Prototypes */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_ladspa_shutdown);
SWITCH_MODULE_RUNTIME_FUNCTION(mod_ladspa_runtime);
SWITCH_MODULE_LOAD_FUNCTION(mod_ladspa_load);
/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime)
* Defines a switch_loadable_module_function_table_t and a static const char[] modname
*/
SWITCH_MODULE_DEFINITION(mod_ladspa, mod_ladspa_load, mod_ladspa_shutdown, NULL);
#define MAX_INDEX 256
typedef struct {
switch_core_session_t *session;
char *plugin_name;
char *label_name;
void *library_handle;
const LADSPA_Descriptor *ldesc;
LADSPA_Handle handle;
LADSPA_Data config[MAX_INDEX];
int num_idx;
char *str_config[MAX_INDEX];
int str_idx;
uint8_t has_config[MAX_INDEX];
int skip;
LADSPA_Data in_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
LADSPA_Data file_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
LADSPA_Data out_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
LADSPA_Data out_ports[MAX_INDEX];
switch_file_handle_t fh;
} switch_ladspa_t;
int check_range(const LADSPA_Descriptor *ldesc, int i, LADSPA_Data val)
{
if (ldesc->PortRangeHints[i].LowerBound && ldesc->PortRangeHints[i].UpperBound &&
(val < ldesc->PortRangeHints[i].LowerBound || val > ldesc->PortRangeHints[i].UpperBound)) {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_ERROR, "Param %f out of bounds %f-%f\n",
val, ldesc->PortRangeHints[i].LowerBound, ldesc->PortRangeHints[i].UpperBound);
return 0;
}
return 1;
}
int find_default(const LADSPA_Descriptor *ldesc, int i, LADSPA_Data *ptr)
{
LADSPA_Data dftval = 0;
int fail = 0;
LADSPA_PortRangeHintDescriptor port_hint = ldesc->PortRangeHints[i].HintDescriptor;
switch (port_hint & LADSPA_HINT_DEFAULT_MASK) {
case LADSPA_HINT_DEFAULT_NONE:
break;
case LADSPA_HINT_DEFAULT_MINIMUM:
dftval = ldesc->PortRangeHints[i].LowerBound;
break;
case LADSPA_HINT_DEFAULT_LOW:
if (LADSPA_IS_HINT_LOGARITHMIC(port_hint)) {
dftval = exp(log(ldesc->PortRangeHints[i].LowerBound)
* 0.75 + log(ldesc->PortRangeHints[i].UpperBound)
* 0.25);
} else {
dftval = (ldesc->PortRangeHints[i].LowerBound * 0.75 + ldesc->PortRangeHints[i].UpperBound * 0.25);
}
break;
case LADSPA_HINT_DEFAULT_MIDDLE:
if (LADSPA_IS_HINT_LOGARITHMIC(port_hint)) {
dftval = sqrt(ldesc->PortRangeHints[i].LowerBound * ldesc->PortRangeHints[i].UpperBound);
} else {
dftval = 0.5 * (ldesc->PortRangeHints[i].LowerBound + ldesc->PortRangeHints[i].UpperBound);
}
break;
case LADSPA_HINT_DEFAULT_HIGH:
if (LADSPA_IS_HINT_LOGARITHMIC(port_hint)) {
dftval = exp(log(ldesc->PortRangeHints[i].LowerBound)
* 0.25 + log(ldesc->PortRangeHints[i].UpperBound)
* 0.75);
} else {
dftval = (ldesc->PortRangeHints[i].LowerBound * 0.25 + ldesc->PortRangeHints[i].UpperBound * 0.75);
}
break;
case LADSPA_HINT_DEFAULT_MAXIMUM:
dftval = ldesc->PortRangeHints[i].UpperBound;
break;
case LADSPA_HINT_DEFAULT_0:
dftval = 0;
break;
case LADSPA_HINT_DEFAULT_1:
dftval = 1;
break;
case LADSPA_HINT_DEFAULT_100:
dftval = 100;
break;
case LADSPA_HINT_DEFAULT_440:
dftval = 440;
break;
default:
fail = 1;
break;
}
if (!fail) {
*ptr = dftval;
}
return !fail;
}
static void dump_info(const LADSPA_Descriptor *ldesc)
{
int i = 0;
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Plugin Name: \"%s\"\n", ldesc->Name);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Plugin Label: \"%s\"\n", ldesc->Label);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Plugin Unique ID: %lu\n", ldesc->UniqueID);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Maker: \"%s\"\n", ldesc->Maker);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Copyright: \"%s\"\n", ldesc->Copyright);
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Must Run Real-Time: ");
if (LADSPA_IS_REALTIME(ldesc->Properties))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Has activate() Function: ");
if (ldesc->activate != NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Has deactivate() Function: ");
if (ldesc->deactivate != NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Has run_adding() Function: ");
if (ldesc->run_adding != NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
if (ldesc->instantiate == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO INSTANTIATE FUNCTION.\n");
if (ldesc->connect_port == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO CONNECT_PORT FUNCTION.\n");
if (ldesc->run == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO RUN FUNCTION.\n");
if (ldesc->run_adding != NULL && ldesc->set_run_adding_gain == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS RUN_ADDING FUNCTION BUT " "NOT SET_RUN_ADDING_GAIN.\n");
if (ldesc->run_adding == NULL && ldesc->set_run_adding_gain != NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS SET_RUN_ADDING_GAIN FUNCTION BUT " "NOT RUN_ADDING.\n");
if (ldesc->cleanup == NULL)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO CLEANUP FUNCTION.\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Environment: ");
if (LADSPA_IS_HARD_RT_CAPABLE(ldesc->Properties))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Normal or Hard Real-Time\n");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Normal\n");
if (LADSPA_IS_INPLACE_BROKEN(ldesc->Properties))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "This plugin cannot use in-place processing. " "It will not work with all hosts.\n");
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Ports:");
if (ldesc->PortCount == 0)
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\tERROR: PLUGIN HAS NO PORTS.\n");
for (i = 0; i < ldesc->PortCount; i++) {
LADSPA_Data dft = 0.0f;
int found = 0;
if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i])) {
found = find_default(ldesc, i, &dft);
}
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n \"%s\" ", ldesc->PortNames[i]);
if (LADSPA_IS_PORT_INPUT(ldesc->PortDescriptors[i])
&& LADSPA_IS_PORT_OUTPUT(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: INPUT AND OUTPUT");
else if (LADSPA_IS_PORT_INPUT(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "input");
else if (LADSPA_IS_PORT_OUTPUT(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "output");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: NEITHER INPUT NOR OUTPUT");
if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i])
&& LADSPA_IS_PORT_AUDIO(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", ERROR: CONTROL AND AUDIO");
else if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", control");
else if (LADSPA_IS_PORT_AUDIO(ldesc->PortDescriptors[i]))
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", audio");
else
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", ERROR: NEITHER CONTROL NOR AUDIO");
if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i])) {
if (found) {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n RANGE: %f-%f DEFAULT: %f\n",
ldesc->PortRangeHints[i].LowerBound, ldesc->PortRangeHints[i].UpperBound, dft);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n RANGE: %f-%f DEFAULT: none.\n",
ldesc->PortRangeHints[i].LowerBound, ldesc->PortRangeHints[i].UpperBound);
}
}
}
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n\n");
}
static switch_bool_t ladspa_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
switch_ladspa_t *pvt = (switch_ladspa_t *) user_data;
//switch_frame_t *frame = NULL;
switch_channel_t *channel = switch_core_session_get_channel(pvt->session);
switch (type) {
case SWITCH_ABC_TYPE_INIT:
{
switch_codec_implementation_t read_impl = { 0 };
LADSPA_PortDescriptor port_desc;
int i = 0, j = 0, k = 0, str_idx = 0;
switch_core_session_get_read_impl(pvt->session, &read_impl);
if (!(pvt->library_handle = loadLADSPAPluginLibrary(pvt->plugin_name))) {
return SWITCH_FALSE;
}
if (!(pvt->ldesc = findLADSPAPluginDescriptor(pvt->library_handle, pvt->plugin_name, pvt->label_name))) {
return SWITCH_FALSE;
}
pvt->handle = pvt->ldesc->instantiate(pvt->ldesc, read_impl.actual_samples_per_second);
dump_info(pvt->ldesc);
for (i = 0; i < pvt->ldesc->PortCount; i++) {
port_desc = pvt->ldesc->PortDescriptors[i];
if (LADSPA_IS_PORT_CONTROL(port_desc) && LADSPA_IS_PORT_INPUT(port_desc)) {
LADSPA_Data dft = 0.0f;
int found = find_default(pvt->ldesc, i, &dft);
if (found && !pvt->has_config[j]) {
pvt->config[j] = dft;
pvt->has_config[j] = 1;
}
if (pvt->has_config[j]) {
if (!check_range(pvt->ldesc, i, pvt->config[j])) {
pvt->config[j] = dft;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_WARNING, "FALLING TO DEFAULT PARAM %d [%s] (%f)\n",
j+1,
pvt->ldesc->PortNames[i],
pvt->config[j]);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "ADDING PARAM %d [%s] (%f)\n",
j+1,
pvt->ldesc->PortNames[i],
pvt->config[j]);
pvt->ldesc->connect_port(pvt->handle, i, &pvt->config[j++]);
usleep(10000);
}
}
if (LADSPA_IS_PORT_INPUT(port_desc) && LADSPA_IS_PORT_AUDIO(port_desc)) {
int mapped = 0;
if (pvt->str_idx && !zstr(pvt->str_config[str_idx])) {
if (!strcasecmp(pvt->str_config[str_idx], "none")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT NOTHING to port: %s\n",
pvt->ldesc->PortNames[i]
);
mapped = 1;
} else if (!strncasecmp(pvt->str_config[str_idx], "file:", 5)) {
char *file = pvt->str_config[str_idx] + 5;
if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session),
SWITCH_LOG_ERROR, "CAN'T CONNECT FILE [%s] File already mapped\n", file);
} else {
if (switch_core_file_open(&pvt->fh,
file,
read_impl.number_of_channels,
read_impl.actual_samples_per_second,
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot open file: %s\n", file);
return SWITCH_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT FILE [%s] to port: %s\n",
file,
pvt->ldesc->PortNames[i]
);
pvt->ldesc->connect_port(pvt->handle, i, pvt->file_buf);
mapped = 1;
}
}
str_idx++;
}
if (!mapped) {
pvt->ldesc->connect_port(pvt->handle, i, pvt->in_buf);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT CHANNEL AUDIO to port: %s\n",
pvt->ldesc->PortNames[i]
);
}
}
if (LADSPA_IS_PORT_OUTPUT(port_desc)) {
if (LADSPA_IS_PORT_AUDIO(port_desc)) {
pvt->ldesc->connect_port(pvt->handle, i, pvt->out_buf);
} else if (k < MAX_INDEX) {
pvt->ldesc->connect_port(pvt->handle, i, &pvt->out_ports[k++]);
}
}
}
}
break;
case SWITCH_ABC_TYPE_CLOSE:
{
if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) {
switch_core_file_close(&pvt->fh);
}
if (pvt->handle && pvt->ldesc) {
pvt->ldesc->cleanup(pvt->handle);
}
if (pvt->library_handle) {
unloadLADSPAPluginLibrary(pvt->library_handle);
}
}
break;
case SWITCH_ABC_TYPE_WRITE_REPLACE:
case SWITCH_ABC_TYPE_READ_REPLACE:
{
switch_frame_t *rframe;
int16_t *slin, abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
switch_size_t olen = 0;
if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
rframe = switch_core_media_bug_get_read_replace_frame(bug);
} else {
rframe = switch_core_media_bug_get_write_replace_frame(bug);
}
slin = rframe->data;
if (switch_channel_media_ready(channel)) {
switch_short_to_float(slin, pvt->in_buf, rframe->samples);
if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) {
olen = rframe->samples;
if (switch_core_file_read(&pvt->fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
switch_codec_implementation_t read_impl = { 0 };
char *file = switch_core_session_strdup(pvt->session, pvt->fh.file_path);
switch_core_session_get_read_impl(pvt->session, &read_impl);
switch_core_file_close(&pvt->fh);
if (switch_core_file_open(&pvt->fh,
file,
read_impl.number_of_channels,
read_impl.actual_samples_per_second,
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot open file: %s\n", file);
return SWITCH_FALSE;
}
olen = rframe->samples;
if (switch_core_file_read(&pvt->fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot READ file: %s\n", file);
return SWITCH_FALSE;
}
}
switch_short_to_float(abuf, pvt->file_buf, olen);
}
pvt->ldesc->run(pvt->handle, rframe->samples);
switch_float_to_short(pvt->out_buf, slin, rframe->samples);
}
if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
switch_core_media_bug_set_read_replace_frame(bug, rframe);
} else {
switch_core_media_bug_set_write_replace_frame(bug, rframe);
}
if (pvt->skip && !--pvt->skip) {
return SWITCH_FALSE;
}
}
break;
case SWITCH_ABC_TYPE_WRITE:
default:
break;
}
return SWITCH_TRUE;
}
switch_status_t stop_ladspa_session(switch_core_session_t *session)
{
switch_media_bug_t *bug;
switch_channel_t *channel = switch_core_session_get_channel(session);
if ((bug = switch_channel_get_private(channel, "ladspa"))) {
switch_channel_set_private(channel, "ladspa", NULL);
switch_core_media_bug_remove(session, &bug);
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
switch_status_t ladspa_session(switch_core_session_t *session, const char *flags, const char *plugin_name, const char *label, const char *params)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_media_bug_t *bug;
switch_status_t status;
switch_ladspa_t *pvt = { 0 };
switch_codec_implementation_t read_impl = { 0 };
int i, bflags = SMBF_READ_REPLACE | SMBF_ANSWER_REQ;
char *pstr;
int argc;
char *argv[50];
char *dparams = NULL;
if (zstr(plugin_name)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s INVALID PLUGIN\n", switch_channel_get_name(channel));
return SWITCH_STATUS_FALSE;
}
if (zstr(flags)) {
flags = "r";
}
if (strchr(flags, 'w')) {
bflags = SMBF_WRITE_REPLACE;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "FLAGS: %s PLUGIN: %s LABEL: %s PARAMS: %s\n",
flags, plugin_name, label, params);
switch_core_session_get_read_impl(session, &read_impl);
pvt = switch_core_session_alloc(session, sizeof(*pvt));
pvt->session = session;
if (!zstr(label)) {
pvt->label_name = switch_core_session_strdup(session, label);
} else {
char *p;
pvt->label_name = switch_core_session_strdup(session, plugin_name);
if ((p = strrchr(pvt->label_name, '.'))) {
*p = '\0';
}
}
if (strstr(plugin_name, ".so")) {
pvt->plugin_name = switch_core_session_strdup(session, plugin_name);
} else {
pvt->plugin_name = switch_core_session_sprintf(session, "%s.so", plugin_name);
}
dparams = switch_core_session_strdup(session, params);
argc = switch_split(dparams, ' ', argv);
for (i = 0; i < argc; i++) {
if (switch_is_number(argv[i])) {
if (pvt->num_idx < MAX_INDEX) {
pvt->config[pvt->num_idx] = atof(argv[i]);
pvt->has_config[pvt->num_idx] = 1;
pvt->num_idx++;
}
} else {
if (pvt->str_idx < MAX_INDEX) {
pvt->str_config[pvt->str_idx++] = switch_core_session_strdup(session, argv[i]);
}
}
}
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
pstr = switch_core_session_sprintf(session, "%s|%s|%s|%s", flags, plugin_name, label, params);
if ((status = switch_core_media_bug_add(session, "ladspa", pstr,
ladspa_callback, pvt, 0, bflags | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) {
return status;
}
switch_channel_set_private(channel, "ladspa", bug);
return SWITCH_STATUS_SUCCESS;
}
static void ladspa_parse(switch_core_session_t *session, const char *data)
{
char *argv[5] = { 0 };
int argc;
char *lbuf;
if (data) {
lbuf = strdup(data);
argc = switch_separate_string(lbuf, '|', argv, (sizeof(argv) / sizeof(argv[0])));
ladspa_session(session, argv[0], argv[1], argv[2], argv[3]);
free(lbuf);
}
}
#define APP_SYNTAX "<flags>|<plugin>|<label>|<params>"
SWITCH_STANDARD_APP(ladspa_run_function)
{
ladspa_parse(session, data);
}
#define API_SYNTAX "<uuid>|<flags>|<plugin>|<label>|<params>"
SWITCH_STANDARD_API(ladspa_api)
{
char *uuid = NULL;
char *data;
char *p;
switch_core_session_t *ksession = NULL;
if (!cmd) goto err;
data = strdup(cmd);
if ((p = strchr(data, ' '))) {
uuid = data;
*p++ = '\0';
if ((ksession = switch_core_session_locate(uuid))) {
ladspa_parse(ksession, p);
switch_core_session_rwunlock(ksession);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "-ERR non-existant UUID\n");
}
} else {
stream->write_function(stream, "-ERR Usage %s\n", API_SYNTAX);
}
free(data);
return SWITCH_STATUS_SUCCESS;
err:
stream->write_function(stream, "-ERR Operation Failed\n");
return SWITCH_STATUS_SUCCESS;
}
/* Macro expands to: switch_status_t mod_ladspa_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION(mod_ladspa_load)
{
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
char *path = getenv("LADSPA_PATH");
if (zstr(path)) {
if (switch_directory_exists("/usr/lib64/ladspa/", pool) == SWITCH_STATUS_SUCCESS) {
putenv("LADSPA_PATH=/usr/lib64/ladspa/:/usr/local/lib/ladspa");
} else if (switch_directory_exists("/usr/lib/ladspa/", pool) == SWITCH_STATUS_SUCCESS) {
putenv("LADSPA_PATH=/usr/lib/ladspa/:/usr/local/lib/ladspa");
}
}
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_APP(app_interface, "ladspa_run", "ladspa_run", NULL, ladspa_run_function, APP_SYNTAX, SAF_NONE);
SWITCH_ADD_API(api_interface, "uuid_ladspa", "ladspa", ladspa_api, API_SYNTAX);
switch_console_set_complete("add uuid_ladspa ::console::list_uuid");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
/*
Called when the system shuts down
Macro expands to: switch_status_t mod_ladspa_shutdown() */
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_ladspa_shutdown)
{
/* Cleanup dynamically allocated config settings */
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4
*/

View File

@ -0,0 +1,72 @@
/* utils.h
Free software by Richard W.E. Furse. Do with as you will. No
warranty. */
#ifndef LADSPA_SDK_LOAD_PLUGIN_LIB
#define LADSPA_SDK_LOAD_PLUGIN_LIB
/*****************************************************************************/
#include "ladspa.h"
/*****************************************************************************/
/* Functions in load.c: */
/* This function call takes a plugin library filename, searches for
the library along the LADSPA_PATH, loads it with dlopen() and
returns a plugin handle for use with findPluginDescriptor() or
unloadLADSPAPluginLibrary(). Errors are handled by writing a
message to stderr and calling exit(1). It is alright (although
inefficient) to call this more than once for the same file. */
void * loadLADSPAPluginLibrary(const char * pcPluginFilename);
/* This function unloads a LADSPA plugin library. */
void unloadLADSPAPluginLibrary(void * pvLADSPAPluginLibrary);
/* This function locates a LADSPA plugin within a plugin library
loaded with loadLADSPAPluginLibrary(). Errors are handled by
writing a message to stderr and calling exit(1). Note that the
plugin library filename is only included to help provide
informative error messages. */
const LADSPA_Descriptor *
findLADSPAPluginDescriptor(void * pvLADSPAPluginLibrary,
const char * pcPluginLibraryFilename,
const char * pcPluginLabel);
/*****************************************************************************/
/* Functions in search.c: */
/* Callback function for use with LADSPAPluginSearch(). The callback
function passes the filename (full path), a plugin handle (dlopen()
style) and a LADSPA_DescriptorFunction (from which
LADSPA_Descriptors can be acquired). */
typedef void LADSPAPluginSearchCallbackFunction
(const char * pcFullFilename,
void * pvPluginHandle,
LADSPA_Descriptor_Function fDescriptorFunction);
/* Search through the $(LADSPA_PATH) (or a default path) for any
LADSPA plugin libraries. Each plugin library is tested using
dlopen() and dlsym(,"ladspa_descriptor"). After loading each
library, the callback function is called to process it. This
function leaves items passed to the callback function open. */
void LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction);
/*****************************************************************************/
/* Function in default.c: */
/* Find the default value for a port. Return 0 if a default is found
and -1 if not. */
int getLADSPADefault(const LADSPA_PortRangeHint * psPortRangeHint,
const unsigned long lSampleRate,
LADSPA_Data * pfResult);
/*****************************************************************************/
#endif
/* EOF */

View File

@ -2492,6 +2492,7 @@ static switch_status_t deliver_vm(vm_profile_t *profile,
if (copy) {
switch_file_copy(path, file_path, SWITCH_FPROT_FILE_SOURCE_PERMS, pool);
} else {
switch_safe_free(file_path);
file_path = (char *) path;
}

View File

@ -3161,12 +3161,15 @@ static switch_status_t recog_asr_close(switch_asr_handle_t *ah, switch_asr_flag_
if (schannel != NULL && !switch_test_flag(ah, SWITCH_ASR_FLAG_CLOSED)) {
r = (recognizer_data_t *) schannel->data;
speech_channel_stop(schannel);
speech_channel_destroy(schannel);
switch_core_hash_destroy(&r->grammars);
switch_core_hash_destroy(&r->enabled_grammars);
switch_mutex_lock(schannel->mutex);
if (r->dtmf_generator) {
r->dtmf_generator_active = 0;
mpf_dtmf_generator_destroy(r->dtmf_generator);
}
switch_mutex_unlock(schannel->mutex);
speech_channel_destroy(schannel);
}
/* this lets FreeSWITCH's speech_thread know the handle is closed */
switch_set_flag(ah, SWITCH_ASR_FLAG_CLOSED);
@ -3503,12 +3506,14 @@ static apt_bool_t recog_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *fra
frame->type |= MEDIA_FRAME_TYPE_AUDIO;
}
switch_mutex_lock(schannel->mutex);
if (r->dtmf_generator_active) {
if (!mpf_dtmf_generator_put_frame(r->dtmf_generator, frame)) {
if (!mpf_dtmf_generator_sending(r->dtmf_generator))
r->dtmf_generator_active = 0;
}
}
switch_mutex_unlock(schannel->mutex);
return TRUE;
}

View File

@ -1,7 +1,7 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_com_g729
VERSION=193
VERSION=194
if ISLINUX

View File

@ -1373,6 +1373,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if ((len = atoi(msg->string_arg))) {
qlen = len / (tech_pvt->read_impl.microseconds_per_packet / 1000);
if (qlen < 1) {
qlen = 3;
}
}
if (qlen) {
@ -1393,6 +1396,9 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
if (qlen) {
if (maxqlen < qlen) {
maxqlen = qlen * 5;
}
if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen,
tech_pvt->read_impl.samples_per_packet,
tech_pvt->read_impl.samples_per_second, max_drift) == SWITCH_STATUS_SUCCESS) {
@ -1444,20 +1450,21 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
case SWITCH_MESSAGE_INDICATE_BRIDGE:
{
const char *var = switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_during_bridge");
sofia_glue_tech_track(tech_pvt->profile, session);
sofia_glue_tech_simplify(tech_pvt);
if (switch_false(var) && switch_rtp_ready(tech_pvt->rtp_session)) {
if (switch_rtp_ready(tech_pvt->rtp_session)) {
const char *val;
int ok = 0;
if (!(val = switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_during_bridge")) || switch_false(val)) {
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER) && switch_channel_test_cap_partner(tech_pvt->channel, CC_FS_RTP)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s PAUSE Jitterbuffer\n", switch_channel_get_name(channel));
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_TRUE);
sofia_set_flag(tech_pvt, TFLAG_JB_PAUSED);
}
}
if (sofia_test_flag(tech_pvt, TFLAG_PASS_RFC2833) && switch_channel_test_flag_partner(channel, CF_FS_RTP)) {
@ -1466,32 +1473,58 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
"%s activate passthru 2833 mode.\n", switch_channel_get_name(channel));
}
if ((val = switch_channel_get_variable(channel, "rtp_notimer_during_bridge"))) {
ok = switch_true(val);
} else {
ok = sofia_test_pflag(tech_pvt->profile, PFLAG_RTP_NOTIMER_DURING_BRIDGE);
}
if (ok && !switch_rtp_test_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) {
ok = 0;
}
if (ok) {
switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
sofia_set_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE);
}
if (ok && sofia_test_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE)) {
/* these are not compat */
ok = 0;
} else {
if ((val = switch_channel_get_variable(channel, "rtp_autoflush_during_bridge"))) {
ok = switch_true(val);
} else {
ok = sofia_test_pflag(tech_pvt->profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE);
}
}
if (ok) {
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_STICK);
sofia_set_flag(tech_pvt, TFLAG_AUTOFLUSH_DURING_BRIDGE);
} else {
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_ONCE);
}
}
}
goto end;
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
if (switch_rtp_ready(tech_pvt->rtp_session)) {
const char *val;
int ok = 0;
sofia_glue_tech_track(tech_pvt->profile, session);
if (sofia_test_flag(tech_pvt, TFLAG_JB_PAUSED)) {
sofia_clear_flag(tech_pvt, TFLAG_JB_PAUSED);
if (switch_channel_test_flag(tech_pvt->channel, CF_JITTERBUFFER)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s RESUME Jitterbuffer\n", switch_channel_get_name(channel));
switch_rtp_pause_jitter_buffer(tech_pvt->rtp_session, SWITCH_FALSE);
}
}
if (switch_rtp_test_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s deactivate passthru 2833 mode.\n",
@ -1499,14 +1532,15 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
switch_rtp_clear_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833);
}
if ((val = switch_channel_get_variable(channel, "rtp_autoflush_during_bridge"))) {
ok = switch_true(val);
} else {
ok = sofia_test_pflag(tech_pvt->profile, PFLAG_RTP_AUTOFLUSH_DURING_BRIDGE);
if (sofia_test_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE)) {
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_USE_TIMER);
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE);
}
if (ok) {
if (sofia_test_flag(tech_pvt, TFLAG_AUTOFLUSH_DURING_BRIDGE)) {
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_UNSTICK);
sofia_clear_flag(tech_pvt, TFLAG_AUTOFLUSH_DURING_BRIDGE);
} else {
rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_ONCE);
}
@ -1850,6 +1884,17 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote)) {
snprintf(message, sizeof(message), "X-FS-Display-Name: %s\nX-FS-Display-Number: %s\n", name, number);
if (switch_channel_test_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Lazy-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER);
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER)) {
snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Attended-Transfer: true\n");
switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
}
nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/update_display"),
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());

View File

@ -230,6 +230,9 @@ typedef enum {
PFLAG_PRESENCE_ON_REGISTER,
PFLAG_PRESENCE_ON_FIRST_REGISTER,
PFLAG_NO_CONNECTION_REUSE,
PFLAG_RENEG_ON_HOLD,
PFLAG_RENEG_ON_REINVITE,
PFLAG_RTP_NOTIMER_DURING_BRIDGE,
/* No new flags below this line */
PFLAG_MAX
} PFLAGS;
@ -288,6 +291,9 @@ typedef enum {
TFLAG_RECOVERING_BRIDGE,
TFLAG_T38_PASSTHRU,
TFLAG_RECOVERED,
TFLAG_AUTOFLUSH_DURING_BRIDGE,
TFLAG_NOTIMER_DURING_BRIDGE,
TFLAG_JB_PAUSED,
/* No new flags below this line */
TFLAG_MAX
} TFLAGS;
@ -598,6 +604,8 @@ struct private_object {
int codec_order_last;
const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS];
int num_codecs;
const switch_codec_implementation_t *negotiated_codecs[SWITCH_MAX_CODECS];
int num_negotiated_codecs;
switch_codec_t read_codec;
switch_codec_t write_codec;
uint32_t codec_ms;
@ -984,7 +992,7 @@ void sofia_glue_del_every_gateway(sofia_profile_t *profile);
void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent,
const char *network_ip);
void sofia_glue_restart_all_profiles(void);
void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly);
int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly);
const char *sofia_state_string(int state);
switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force);
void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout);

Some files were not shown because too many files have changed in this diff Show More