[eggheads-patches] PATCH1.4: asyncdns.patch
Fabian Knittel
fknittel at gmx.de
Sat Oct 9 12:52:30 CST 1999
[ asncydns.patch ]
This patch adds the "dns" module, which provides asynchronous
dns request possibilities. The patch also adds a lookup
abstraction layer, which makes it possible to transparently
switch between non-blocking (with the dns module) and blocking
mode (using the library functions gethostbyaddr, etc.).
Fabian
-------------- next part --------------
diff -urN eggdrop1.4~/Makefile.in eggdrop1.4/Makefile.in
--- eggdrop1.4~/Makefile.in Sat Oct 9 18:33:39 1999
+++ eggdrop1.4/Makefile.in Sat Oct 9 18:40:19 1999
@@ -93,15 +93,16 @@
@exit 1
OBJS = botcmd.o botmsg.o botnet.o chanprog.o cmds.o dcc.o \
- dccutil.o flags.o language.o main.o mem.o misc.o \
+ dccutil.o dns.o flags.o language.o main.o mem.o misc.o \
modules.o net.o rfc1459.o tcl.o tcldcc.o tclhash.o \
tclmisc.o tcluser.o userent.o userrec.o users.o md5/md5c.o
-GMAKE_STATIC = ${MAKE} 'CC=${CC}' 'LD=${LD}' 'OBJS=${OBJS}'\
-'STRIP=${MOD_STRIP}' 'CFLAGS=${CFLAGS} -DSTATIC' 'XLIBS=@TCL_LIBS@ @LIBS@'
+GMAKE_STATIC = ${MAKE} 'CC=${CC}' 'LD=${LD}' 'OBJS=${OBJS}' \
+'STRIP=${MOD_STRIP}' 'CFLAGS=${CFLAGS} -DSTATIC' 'XLIBS=@TCL_LIBS@ @LIBS@' \
+'RESLIB=@RESLIB@'
GMAKE_SHLIB = ${MAKE} 'CC=${SHLIB_CC}' 'LD=${SHLIB_LD}' \
-'STRIP=${SHLIB_STRIP}' 'CFLAGS=${CFLAGS}'
+'STRIP=${SHLIB_STRIP}' 'CFLAGS=${CFLAGS}' 'RESLIB=@RESLIB@'
GMAKE_MOD = ${MAKE} 'CC=${MOD_CC}' 'LD=${MOD_LD}' 'OBJS=${OBJS}'\
'CFLAGS=${CFLAGS}' 'XREQ=${XREQ}' \
@@ -114,7 +115,7 @@
'XLIBS=@TCL_LIBS@ @LIBS@'
DMAKE_SHLIB = ${MAKE} 'CC=${SHLIB_CC}' 'LD=${SHLIB_LD}' \
-'STRIP=touch' 'CFLAGS=-g3 ${CFLAGS} -DEBUG_MEM'
+'STRIP=touch' 'CFLAGS=-g3 ${CFLAGS} -DEBUG_MEM' 'RESLIB=@RESLIB@'
static: eggtest
@echo ""
diff -urN eggdrop1.4~/configure eggdrop1.4/configure
--- eggdrop1.4~/configure Sat Oct 9 18:33:40 1999
+++ eggdrop1.4/configure Sat Oct 9 18:48:24 1999
@@ -1724,15 +1724,275 @@
fi
fi
+echo $ac_n "checking for res_init""... $ac_c" 1>&6
+echo "configure:1729: checking for res_init" >&5
+if eval "test \"`echo '$''{'ac_cv_func_res_init'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1734 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char res_init(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char res_init();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_res_init) || defined (__stub___res_init)
+choke me
+#else
+res_init();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1757: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_res_init=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_res_init=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'res_init`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for res_init in -lbind""... $ac_c" 1>&6
+echo "configure:1775: checking for res_init in -lbind" >&5
+ac_lib_var=`echo bind'_'res_init | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lbind $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1783 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char res_init();
+
+int main() {
+res_init()
+; return 0; }
+EOF
+if { (eval echo configure:1794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ RESLIB="-lbind"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for res_init in -lresolv""... $ac_c" 1>&6
+echo "configure:1813: checking for res_init in -lresolv" >&5
+ac_lib_var=`echo resolv'_'res_init | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lresolv $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1821 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char res_init();
+
+int main() {
+res_init()
+; return 0; }
+EOF
+if { (eval echo configure:1832: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ RESLIB="-lresolv"
+else
+ echo "$ac_t""no" 1>&6
+{ echo "configure: error: No resolver library found" 1>&2; exit 1; }
+fi
+
+fi
+
+fi
+
+
+echo $ac_n "checking for res_mkquery""... $ac_c" 1>&6
+echo "configure:1859: checking for res_mkquery" >&5
+if eval "test \"`echo '$''{'ac_cv_func_res_mkquery'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1864 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char res_mkquery(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char res_mkquery();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_res_mkquery) || defined (__stub___res_mkquery)
+choke me
+#else
+res_mkquery();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1887: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_res_mkquery=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_res_mkquery=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'res_mkquery`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for res_mkquery in -lbind""... $ac_c" 1>&6
+echo "configure:1905: checking for res_mkquery in -lbind" >&5
+ac_lib_var=`echo bind'_'res_mkquery | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lbind $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1913 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char res_mkquery();
+
+int main() {
+res_mkquery()
+; return 0; }
+EOF
+if { (eval echo configure:1924: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ RESLIB="-lbind"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for res_mkquery in -lresolv""... $ac_c" 1>&6
+echo "configure:1943: checking for res_mkquery in -lresolv" >&5
+ac_lib_var=`echo resolv'_'res_mkquery | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lresolv $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1951 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char res_mkquery();
+
+int main() {
+res_mkquery()
+; return 0; }
+EOF
+if { (eval echo configure:1962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ RESLIB="-lresolv"
+else
+ echo "$ac_t""no" 1>&6
+{ echo "configure: error: No resolver library found" 1>&2; exit 1; }
+fi
+
+fi
+
+fi
+
+
echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:1729: checking whether byte ordering is bigendian" >&5
+echo "configure:1989: checking whether byte ordering is bigendian" >&5
if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_bigendian=unknown
# See if sys/param.h defines the BYTE_ORDER macro.
cat > conftest.$ac_ext <<EOF
-#line 1736 "configure"
+#line 1996 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@@ -1743,11 +2003,11 @@
#endif
; return 0; }
EOF
-if { (eval echo configure:1747: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2007: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
# It does; now see whether it defined to BIG_ENDIAN or not.
cat > conftest.$ac_ext <<EOF
-#line 1751 "configure"
+#line 2011 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@@ -1758,7 +2018,7 @@
#endif
; return 0; }
EOF
-if { (eval echo configure:1762: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2022: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_bigendian=yes
else
@@ -1778,7 +2038,7 @@
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 1782 "configure"
+#line 2042 "configure"
#include "confdefs.h"
main () {
/* Are we little or big endian? From Harbison&Steele. */
@@ -1791,7 +2051,7 @@
exit (u.c[sizeof (long) - 1] == 1);
}
EOF
-if { (eval echo configure:1795: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_bigendian=no
else
@@ -1815,7 +2075,7 @@
fi
echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:1819: checking size of long" >&5
+echo "configure:2079: checking size of long" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1823,7 +2083,7 @@
ac_cv_sizeof_long=0
else
cat > conftest.$ac_ext <<EOF
-#line 1827 "configure"
+#line 2087 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
@@ -1834,7 +2094,7 @@
exit(0);
}
EOF
-if { (eval echo configure:1838: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2098: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_sizeof_long=`cat conftestval`
else
@@ -1854,7 +2114,7 @@
echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:1858: checking size of int" >&5
+echo "configure:2118: checking size of int" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1862,7 +2122,7 @@
ac_cv_sizeof_int=0
else
cat > conftest.$ac_ext <<EOF
-#line 1866 "configure"
+#line 2126 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
@@ -1873,7 +2133,7 @@
exit(0);
}
EOF
-if { (eval echo configure:1877: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2137: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_sizeof_int=`cat conftestval`
else
@@ -1898,12 +2158,12 @@
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
-echo "configure:1902: checking for $ac_hdr that defines DIR" >&5
+echo "configure:2162: checking for $ac_hdr that defines DIR" >&5
if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1907 "configure"
+#line 2167 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
@@ -1911,7 +2171,7 @@
DIR *dirp = 0;
; return 0; }
EOF
-if { (eval echo configure:1915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2175: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_header_dirent_$ac_safe=yes"
else
@@ -1936,7 +2196,7 @@
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:1940: checking for opendir in -ldir" >&5
+echo "configure:2200: checking for opendir in -ldir" >&5
ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1944,7 +2204,7 @@
ac_save_LIBS="$LIBS"
LIBS="-ldir $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1948 "configure"
+#line 2208 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1955,7 +2215,7 @@
opendir()
; return 0; }
EOF
-if { (eval echo configure:1959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2219: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1977,7 +2237,7 @@
else
echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:1981: checking for opendir in -lx" >&5
+echo "configure:2241: checking for opendir in -lx" >&5
ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1985,7 +2245,7 @@
ac_save_LIBS="$LIBS"
LIBS="-lx $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1989 "configure"
+#line 2249 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1996,7 +2256,7 @@
opendir()
; return 0; }
EOF
-if { (eval echo configure:2000: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2260: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2019,12 +2279,12 @@
fi
echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
-echo "configure:2023: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo "configure:2283: checking for sys/wait.h that is POSIX.1 compatible" >&5
if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2028 "configure"
+#line 2288 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/wait.h>
@@ -2040,7 +2300,7 @@
s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
; return 0; }
EOF
-if { (eval echo configure:2044: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2304: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_sys_wait_h=yes
else
@@ -2064,17 +2324,17 @@
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2068: checking for $ac_hdr" >&5
+echo "configure:2328: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2073 "configure"
+#line 2333 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2078: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2338: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2102,12 +2362,12 @@
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:2106: checking for ANSI C header files" >&5
+echo "configure:2366: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2111 "configure"
+#line 2371 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -2115,7 +2375,7 @@
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2119: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2379: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2132,7 +2392,7 @@
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 2136 "configure"
+#line 2396 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -2150,7 +2410,7 @@
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 2154 "configure"
+#line 2414 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -2171,7 +2431,7 @@
:
else
cat > conftest.$ac_ext <<EOF
-#line 2175 "configure"
+#line 2435 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -2182,7 +2442,7 @@
exit (0); }
EOF
-if { (eval echo configure:2186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2446: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
@@ -2206,12 +2466,12 @@
fi
echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:2210: checking for pid_t" >&5
+echo "configure:2470: checking for pid_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2215 "configure"
+#line 2475 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -2239,12 +2499,12 @@
fi
echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:2243: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:2503: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2248 "configure"
+#line 2508 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
@@ -2253,7 +2513,7 @@
struct tm *tp;
; return 0; }
EOF
-if { (eval echo configure:2257: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2517: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_time=yes
else
@@ -2274,21 +2534,21 @@
fi
echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:2278: checking for inline" >&5
+echo "configure:2538: checking for inline" >&5
if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
cat > conftest.$ac_ext <<EOF
-#line 2285 "configure"
+#line 2545 "configure"
#include "confdefs.h"
int main() {
} $ac_kw foo() {
; return 0; }
EOF
-if { (eval echo configure:2292: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2552: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_inline=$ac_kw; break
else
@@ -2317,12 +2577,12 @@
for ac_func in rename getrusage getdtablesize srandom random sigaction
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2321: checking for $ac_func" >&5
+echo "configure:2581: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2326 "configure"
+#line 2586 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2345,7 +2605,7 @@
; return 0; }
EOF
-if { (eval echo configure:2349: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2609: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2372,12 +2632,12 @@
for ac_func in sigemptyset vsprintf strcasecmp setpgid clock dlopen
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2376: checking for $ac_func" >&5
+echo "configure:2636: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2381 "configure"
+#line 2641 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2400,7 +2660,7 @@
; return 0; }
EOF
-if { (eval echo configure:2404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2664: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2427,12 +2687,12 @@
for ac_func in dprintf bzero uname vsnprintf
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2431: checking for $ac_func" >&5
+echo "configure:2691: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2436 "configure"
+#line 2696 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2455,7 +2715,7 @@
; return 0; }
EOF
-if { (eval echo configure:2459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2499,7 +2759,7 @@
fi
echo $ac_n "checking space left in file database struct""... $ac_c" 1>&6
-echo "configure:2503: checking space left in file database struct" >&5
+echo "configure:2763: checking space left in file database struct" >&5
cat > abacab.c <<'EOF'
#include <stdio.h>
#include <sys/time.h>
@@ -2598,7 +2858,7 @@
# check in common places now
echo $ac_n "checking for libtcl""... $ac_c" 1>&6
-echo "configure:2602: checking for libtcl" >&5
+echo "configure:2862: checking for libtcl" >&5
if test ! "x${TCLLIB}" = "x"
then
echo "$ac_t""found in $TCLLIB/lib$TCLLIBFN$TCLLIBEXT" 1>&6
@@ -2654,7 +2914,7 @@
# check in common places now
echo $ac_n "checking for $TCLINCFN""... $ac_c" 1>&6
-echo "configure:2658: checking for $TCLINCFN" >&5
+echo "configure:2918: checking for $TCLINCFN" >&5
if test ! "x${TCLINC}" = "x"
then
echo "$ac_t""found in $TCLINC/$TCLINCFN" 1>&6
@@ -2718,7 +2978,7 @@
else
echo $ac_n "checking for Tcl version""... $ac_c" 1>&6
-echo "configure:2722: checking for Tcl version" >&5
+echo "configure:2982: checking for Tcl version" >&5
for ver in $tclnames
do
@@ -2832,6 +3092,7 @@
+
trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
@@ -2985,6 +3246,7 @@
s%@CP2@%$CP2%g
s%@CP3@%$CP3%g
s%@EGGEXEC@%$EGGEXEC%g
+s%@RESLIB@%$RESLIB%g
s%@SHLIB_LD@%$SHLIB_LD%g
s%@SHLIB_CC@%$SHLIB_CC%g
s%@SHLIB_STRIP@%$SHLIB_STRIP%g
diff -urN eggdrop1.4~/configure.in eggdrop1.4/configure.in
--- eggdrop1.4~/configure.in Sat Oct 9 18:33:40 1999
+++ eggdrop1.4/configure.in Sat Oct 9 18:40:19 1999
@@ -250,6 +250,14 @@
fi
fi
+AC_CHECK_FUNC(res_init, ,
+ AC_CHECK_LIB(bind, res_init, RESLIB="-lbind",
+ AC_CHECK_LIB(resolv, res_init, RESLIB="-lresolv", AC_MSG_ERROR(No resolver library found))))
+
+AC_CHECK_FUNC(res_mkquery, ,
+ AC_CHECK_LIB(bind, res_mkquery, RESLIB="-lbind",
+ AC_CHECK_LIB(resolv, res_mkquery, RESLIB="-lresolv", AC_MSG_ERROR(No resolver library found))))
+
AC_C_BIGENDIAN
AC_CHECK_SIZEOF(long,0)
AC_CHECK_SIZEOF(int,0)
@@ -599,6 +607,7 @@
AC_SUBST(CP3)
AC_SUBST(EGGEXEC)
AC_SUBST(CC)
+AC_SUBST(RESLIB)
AC_SUBST(SHLIB_LD)
AC_SUBST(SHLIB_CC)
AC_SUBST(SHLIB_STRIP)
diff -urN eggdrop1.4~/eggdrop.conf.dist eggdrop1.4/eggdrop.conf.dist
--- eggdrop1.4~/eggdrop.conf.dist Sat Oct 9 18:33:40 1999
+++ eggdrop1.4/eggdrop.conf.dist Sat Oct 9 18:40:20 1999
@@ -358,6 +358,13 @@
set mod-path "modules/"
+#### DNS MODULE #####
+
+# this module provides asynchronous dns support. This will avoid long
+# periods where the bot just hangs there, waiting for a hostname to
+# resolve, which often let it timeout on all other connections.
+#loadmodule dns
+
#### CHANNELS MODULE #####
diff -urN eggdrop1.4~/src/Makefile eggdrop1.4/src/Makefile
--- eggdrop1.4~/src/Makefile Sat Oct 9 18:33:50 1999
+++ eggdrop1.4/src/Makefile Sat Oct 9 18:40:20 1999
@@ -61,6 +61,9 @@
dccutil.o: dccutil.c
${CC} ${CFLAGS} dccutil.c
+dns.o: dns.c
+ ${CC} ${CFLAGS} dns.c
+
flags.o: flags.c
${CC} ${CFLAGS} flags.c
@@ -147,6 +150,8 @@
chan.h \
modules.h \
tandem.h
+dns.o: \
+ main.h
flags.o: \
main.h
language.o: \
diff -urN eggdrop1.4~/src/botnet.c eggdrop1.4/src/botnet.c
--- eggdrop1.4~/src/botnet.c Sat Oct 9 18:33:51 1999
+++ eggdrop1.4/src/botnet.c Sat Oct 9 18:49:21 1999
@@ -870,6 +870,9 @@
return 0;
}
+static void botlink_resolve_success(int);
+static void botlink_resolve_failure(int);
+
/* link to another bot */
int botlink(char *linker, int idx, char *nick)
{
@@ -911,30 +914,58 @@
} else {
context;
correct_handle(nick);
- i = new_dcc(&DCC_FORK_BOT, sizeof(struct bot_info));
- dcc[i].port = bi->telnet_port;
- strcpy(dcc[i].nick, nick);
- strcpy(dcc[i].host, bi->address);
- dcc[i].timeval = now;
- strcpy(dcc[i].u.bot->linker, linker);
- strcpy(dcc[i].u.bot->version, "(primitive bot)");
if (idx > -2)
putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
bi->address, bi->telnet_port);
- dcc[i].u.bot->numver = idx;
+
+ i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
dcc[i].timeval = now;
- dcc[i].u.bot->port = dcc[i].port; /* remember where i started */
- dcc[i].sock = getsock(SOCK_STRONGCONN);
- dcc[i].user = u;
- if (open_telnet_raw(dcc[i].sock, bi->address, dcc[i].port) >= 0)
- return 1;
- failed_link(i);
+ dcc[i].port = bi->telnet_port;
+ strcpy(dcc[i].nick, nick);
+ strcpy(dcc[i].host, bi->address);
+ dcc[i].u.dns->ibuf = idx;
+ dcc[i].u.dns->cptr = linker;
+ dcc[i].u.dns->host = get_data_ptr(strlen(dcc[i].host) + 1);
+ strcpy(dcc[i].u.dns->host, dcc[i].host);
+ dcc[i].u.dns->dns_success = (Function) botlink_resolve_success;
+ dcc[i].u.dns->dns_failure = (Function) botlink_resolve_failure;
+ dcc[i].u.dns->dns_type = RES_IPBYHOST;
+
+ dns_ipbyhost(bi->address);
}
}
return 0;
}
+static void botlink_resolve_failure(int i)
+{
+ char s[81];
+
+ putlog(LOG_BOTS, "*", DCC_LINKFAIL, dcc[i].nick);
+ strcpy(s, dcc[i].nick);
+ lostdcc(i);
+ autolink_cycle(s); /* check for more auto-connections */
+}
+
+static void botlink_resolve_success(int i)
+{
+ int idx = dcc[i].u.dns->ibuf;
+ char *linker = dcc[i].u.dns->cptr;
+
+ dcc[i].addr = dcc[i].u.dns->ip;
+ changeover_dcc(i, &DCC_FORK_BOT, sizeof(struct bot_info));
+ dcc[i].timeval = now;
+ strcpy(dcc[i].u.bot->linker, linker);
+ strcpy(dcc[i].u.bot->version, "(primitive bot)");
+ dcc[i].u.bot->numver = idx;
+ dcc[i].u.bot->port = dcc[i].port; /* remember where i started */
+ dcc[i].sock = getsock(SOCK_STRONGCONN);
+ if (open_telnet_raw(dcc[i].sock, iptostr(my_ntohl(dcc[i].addr)),
+ dcc[i].port) < 0)
+ failed_link(i);
+}
+
static void failed_tandem_relay(int idx)
{
int uidx = (-1), i;
@@ -968,16 +999,22 @@
dcc[uidx].u.relay->sock = dcc[idx].sock;
dcc[idx].port++;
dcc[idx].timeval = now;
- if (open_telnet_raw(dcc[idx].sock, dcc[idx].host, dcc[idx].port) < 0)
+ if (open_telnet_raw(dcc[idx].sock, dcc[idx].addr ?
+ iptostr(my_ntohl(dcc[idx].addr)) :
+ dcc[idx].host, dcc[idx].port) < 0)
failed_tandem_relay(idx);
}
+
+static void tandem_relay_resolve_failure(int);
+static void tandem_relay_resolve_success(int);
+
/* relay to another tandembot */
void tandem_relay(int idx, char *nick, int i)
{
- struct chat_info *ci;
struct userrec *u;
struct bot_addr *bi;
+ struct chat_info *ci;
context;
u = get_user_by_handle(userlist, nick);
@@ -1002,38 +1039,87 @@
dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
return;
}
- i = new_dcc(&DCC_FORK_RELAY, sizeof(struct relay_info));
- dcc[i].u.relay->chat = get_data_ptr(sizeof(struct chat_info));
+ i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
dcc[i].port = bi->relay_port;
- dcc[i].u.relay->port = dcc[i].port;
dcc[i].addr = 0L;
strcpy(dcc[i].nick, nick);
dcc[i].user = u;
strcpy(dcc[i].host, bi->address);
- dcc[i].u.relay->chat->away = NULL;
- dcc[i].u.relay->old_status = dcc[i].status;
dcc[i].status = 0;
- dcc[i].timeval = now;
- dcc[i].u.relay->chat->msgs_per_sec = 0;
- dcc[i].u.relay->chat->con_flags = 0;
- dcc[i].u.relay->chat->buffer = NULL;
- dcc[i].u.relay->chat->max_line = 0;
- dcc[i].u.relay->chat->line_count = 0;
- dcc[i].u.relay->chat->current_lines = 0;
dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick,
bi->address, bi->relay_port);
dprintf(idx, "%s\n", BOT_BYEINFO1);
+ dcc[idx].type = &DCC_PRE_RELAY;
ci = dcc[idx].u.chat;
dcc[idx].u.relay = get_data_ptr(sizeof(struct relay_info));
-
dcc[idx].u.relay->chat = ci;
- dcc[idx].type = &DCC_PRE_RELAY;
dcc[i].sock = getsock(SOCK_STRONGCONN);
dcc[idx].u.relay->sock = dcc[i].sock;
dcc[i].u.relay->sock = dcc[idx].sock;
dcc[i].timeval = now;
- if (open_telnet_raw(dcc[i].sock, dcc[i].host, dcc[i].port) < 0)
+ dcc[i].u.dns->ibuf = dcc[idx].sock;
+ dcc[i].u.dns->host = get_data_ptr(strlen(bi->address) + 1);
+ strcpy(dcc[i].u.dns->host, bi->address);
+ dcc[i].u.dns->dns_success = (Function) tandem_relay_resolve_success;
+ dcc[i].u.dns->dns_failure = (Function) tandem_relay_resolve_failure;
+ dcc[i].u.dns->dns_type = RES_IPBYHOST;
+
+ dns_ipbyhost(bi->address);
+}
+
+static void tandem_relay_resolve_failure(int idx)
+{
+ struct chat_info *ci;
+ int uidx = (-1), i;
+
+ context;
+ for (i = 0; i < dcc_total; i++)
+ if ((dcc[i].type == &DCC_PRE_RELAY) &&
+ (dcc[i].u.relay->sock == dcc[idx].sock)) {
+ uidx = i;
+ break;
+ }
+ if (uidx < 0) {
+ putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
+ dcc[idx].sock, dcc[idx].u.relay->sock);
+ killsock(dcc[idx].sock);
+ lostdcc(idx);
+ return;
+ }
+ ci = dcc[uidx].u.relay->chat;
+ dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
+ nfree(dcc[uidx].u.relay);
+ dcc[uidx].u.chat = ci;
+ dcc[uidx].type = &DCC_CHAT;
+ dcc[uidx].status = dcc[uidx].u.relay->old_status;
+ killsock(dcc[idx].sock);
+ lostdcc(idx);
+ context;
+}
+
+static void tandem_relay_resolve_success(int i)
+{
+ int sock = dcc[i].u.dns->ibuf;
+
+ dcc[i].addr = dcc[i].u.dns->ip;
+ changeover_dcc(i, &DCC_FORK_RELAY, sizeof(struct relay_info));
+ dcc[i].u.relay->chat = get_data_ptr(sizeof(struct chat_info));
+
+ dcc[i].u.relay->sock = sock;
+ dcc[i].u.relay->port = dcc[i].port;
+ dcc[i].u.relay->chat->away = NULL;
+ dcc[i].u.relay->old_status = dcc[i].status;
+ dcc[i].status = 0;
+ dcc[i].u.relay->chat->msgs_per_sec = 0;
+ dcc[i].u.relay->chat->con_flags = 0;
+ dcc[i].u.relay->chat->buffer = NULL;
+ dcc[i].u.relay->chat->max_line = 0;
+ dcc[i].u.relay->chat->line_count = 0;
+ dcc[i].u.relay->chat->current_lines = 0;
+ dcc[i].timeval = now;
+ if (open_telnet_raw(dcc[i].sock, iptostr(my_ntohl(dcc[i].addr)),
+ dcc[i].port) < 0)
failed_tandem_relay(i);
}
@@ -1045,8 +1131,18 @@
context;
for (i = 0; i < dcc_total; i++)
if ((dcc[i].type == &DCC_FORK_RELAY) &&
- (dcc[i].u.relay->sock == dcc[idx].sock))
+ (dcc[i].u.relay->sock == dcc[idx].sock)) {
tidx = i;
+ break;
+ }
+ if (tidx < 0) {
+ for (i = 0; i < dcc_total; i++)
+ if ((dcc[i].type == &DCC_DNSWAIT) &&
+ (dcc[i].sock == dcc[idx].u.relay->sock)) {
+ tidx = i;
+ break;
+ }
+ }
if (tidx < 0) {
putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
dcc[i].sock, dcc[i].u.relay->sock);
@@ -1063,9 +1159,9 @@
dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
putlog(LOG_MISC, "*", "%s %s -> %s", BOT_ABORTRELAY3, dcc[idx].nick,
dcc[tidx].nick);
+ dcc[idx].status = dcc[idx].u.relay->old_status;
nfree(dcc[idx].u.relay);
dcc[idx].u.chat = ci;
- dcc[idx].status = dcc[idx].u.relay->old_status;
dcc[idx].type = &DCC_CHAT;
killsock(dcc[tidx].sock);
lostdcc(tidx);
@@ -1082,13 +1178,24 @@
context;
for (i = 0; i < dcc_total; i++)
if ((dcc[i].type == &DCC_FORK_RELAY) &&
- (dcc[i].u.relay->sock == dcc[idx].sock))
+ (dcc[i].u.relay->sock == dcc[idx].sock)) {
tidx = i;
+ break;
+ }
+ if (tidx < 0) {
+ /* Now try to find it among the DNSWAIT sockets instead */
+ for (i = 0; i < dcc_total; i++)
+ if ((dcc[i].type == &DCC_DNSWAIT) &&
+ (dcc[i].sock == dcc[idx].u.relay->sock)) {
+ tidx = i;
+ break;
+ }
+ }
if (tidx < 0) {
putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
- dcc[i].sock, dcc[i].u.relay->sock);
- killsock(dcc[i].sock);
- lostdcc(i);
+ dcc[idx].sock, dcc[idx].u.relay->sock);
+ killsock(dcc[idx].sock);
+ lostdcc(idx);
return;
}
putlog(LOG_MISC, "*", "%s [%s]%s/%d",
diff -urN eggdrop1.4~/src/dcc.c eggdrop1.4/src/dcc.c
--- eggdrop1.4~/src/dcc.c Sat Oct 9 18:33:51 1999
+++ eggdrop1.4/src/dcc.c Sat Oct 9 18:49:21 1999
@@ -209,7 +209,9 @@
dcc[idx].sock = getsock(SOCK_STRONGCONN);
dcc[idx].port++;
dcc[idx].timeval = now;
- if (open_telnet_raw(dcc[idx].sock, dcc[idx].host, dcc[idx].port) < 0) {
+ if (open_telnet_raw(dcc[idx].sock, dcc[idx].addr ?
+ iptostr(my_ntohl(dcc[idx].addr)) : dcc[idx].host,
+ dcc[idx].port) < 0) {
failed_link(idx);
}
}
@@ -1047,14 +1049,14 @@
return 0;
}
-static void dcc_telnet_got_ident(int, char *);
+static void dcc_telnet_hostresolved(int);
static void dcc_telnet(int idx, char *buf, int i)
{
unsigned long ip;
unsigned short port;
int j = 0, sock;
- char s[UHOSTLEN + 1], s2[UHOSTLEN + 20];
+ char s[UHOSTLEN + 1];
context;
if (dcc_total + 1 > max_dcc) {
@@ -1092,32 +1094,67 @@
killsock(sock);
return;
}
+ i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
+ dcc[i].sock = sock;
+ dcc[i].addr = ip;
+ dcc[i].port = port;
+ dcc[i].timeval = now;
+ strcpy(dcc[i].nick, "*");
+ dcc[i].u.dns->ip = ip;
+ dcc[i].u.dns->dns_success = (Function) dcc_telnet_hostresolved;
+ dcc[i].u.dns->dns_failure = (Function) dcc_telnet_hostresolved;
+ dcc[i].u.dns->dns_type = RES_HOSTBYIP;
+ dcc[i].u.dns->ibuf = dcc[idx].sock;
+
+ dns_hostbyip(ip);
+}
+
+static void dcc_telnet_got_ident(int, char *);
+
+static void dcc_telnet_hostresolved(int i)
+{
+ int idx;
+ int j = 0, sock;
+ char s[UHOSTLEN + 1], s2[UHOSTLEN + 20];
+
+ strncpy(dcc[i].host, dcc[i].u.dns->host, UHOSTLEN - 1);
+ dcc[i].host[UHOSTLEN - 1] = 0;
+
+ for (idx = 0; idx < dcc_total; idx++)
+ if ((dcc[idx].type == &DCC_TELNET) &&
+ (dcc[idx].sock == dcc[i].u.dns->ibuf)) {
+ break;
+ }
+ if (dcc_total == idx) {
+ putlog(LOG_BOTS, "*", "Lost listening socket while resolving %s",
+ dcc[i].host);
+ killsock(dcc[i].sock);
+ lostdcc(i);
+ return;
+ }
if (dcc[idx].host[0] == '@') {
/* restrict by hostname */
- if (!wild_match(dcc[idx].host + 1, s)) {
+ if (!wild_match(dcc[idx].host + 1, dcc[i].host)) {
putlog(LOG_BOTS, "*", DCC_BADHOST, s);
- killsock(sock);
+ killsock(dcc[i].sock);
+ lostdcc(i);
return;
}
}
context;
- sprintf(s2, "telnet!telnet@%s", s);
+ sprintf(s2, "telnet!telnet@%s", dcc[i].host);
if (match_ignore(s2) || detect_telnet_flood(s2)) {
- killsock(sock);
+ killsock(dcc[i].sock);
+ lostdcc(i);
return;
}
+
context;
- i = new_dcc(&DCC_IDENTWAIT, 0);
- dcc[i].sock = sock;
- dcc[i].addr = ip;
- dcc[i].port = port;
+ changeover_dcc(i, &DCC_IDENTWAIT, 0);
dcc[i].timeval = now;
- dcc[i].u.ident_sock = dcc[idx].sock;
- strncpy(dcc[i].host, s, UHOSTLEN - 1);
- dcc[i].host[UHOSTLEN - 1] = 0;
- strcpy(dcc[i].nick, "*");
- sock = open_telnet(s, 113);
- putlog(LOG_MISC, "*", DCC_TELCONN, s, port);
+ dcc[i].u.ident_sock = dcc[j].sock;
+ sock = open_telnet(iptostr(my_htonl(dcc[i].addr)), 113);
+ putlog(LOG_MISC, "*", DCC_TELCONN, dcc[i].host, dcc[i].port);
s[0] = 0;
context;
if (sock < 0) {
@@ -1142,7 +1179,7 @@
context;
dcc[j].sock = sock;
dcc[j].port = 113;
- dcc[j].addr = ip;
+ dcc[j].addr = dcc[i].addr;
strcpy(dcc[j].host, dcc[i].host);
strcpy(dcc[j].nick, "*");
dcc[j].u.ident_sock = dcc[i].sock;
diff -urN eggdrop1.4~/src/dccutil.c eggdrop1.4/src/dccutil.c
--- eggdrop1.4~/src/dccutil.c Sat Oct 9 18:33:51 1999
+++ eggdrop1.4/src/dccutil.c Sat Oct 9 18:40:20 1999
@@ -410,6 +410,25 @@
}
+/* Changes the given dcc entry to another type */
+void changeover_dcc(int i, struct dcc_table *type, int xtra_size)
+{
+ /* free old structure */
+ if (dcc[i].type && dcc[i].type->kill)
+ dcc[i].type->kill(i, dcc[i].u.other);
+ else if (dcc[i].u.other) {
+ nfree(dcc[i].u.other);
+ dcc[i].u.other = NULL;
+ }
+
+ dcc[i].type = type;
+ if (xtra_size) {
+ dcc[i].u.other = nmalloc(xtra_size);
+ bzero(dcc[i].u.other, xtra_size);
+ }
+}
+
+
int detect_dcc_flood(time_t * timer, struct chat_info *chat, int idx)
{
time_t t;
diff -urN eggdrop1.4~/src/dns.c eggdrop1.4/src/dns.c
--- eggdrop1.4~/src/dns.c Thu Jan 1 01:00:00 1970
+++ eggdrop1.4/src/dns.c Sat Oct 9 18:40:20 1999
@@ -0,0 +1,191 @@
+/*
+ * dns.c - handles DNS calls. Also provides the code used by the bot
+ * if the DNS module is not loaded.
+ */
+/*
+ * This file is part of the eggdrop source code.
+ *
+ * Copyright (C) 1999 Eggheads
+ * Copyright (C) 1997 Robey Pointer
+ *
+ * Distributed according to the GNU General Public License. For full
+ * details, read the top of 'main.c' or the file called COPYING that
+ * was distributed with this code.
+ */
+/*
+ * Mon Oct 04 22:24:51 1999 Fabian Knittel
+ * * minor fixes
+ * Sun Oct 03 18:34:41 1999 Fabian Knittel
+ * * Initial release
+ */
+
+
+#include "main.h"
+#include <netdb.h>
+#include <setjmp.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+extern struct dcc_t *dcc;
+extern int dcc_total;
+extern int resolve_timeout;
+extern time_t now;
+extern jmp_buf alarmret;
+
+
+void dcc_dnswait(int idx, char *buf, int len)
+{
+ /* ignore anything now */
+ context;
+}
+
+void eof_dcc_dnswait(int idx)
+{
+ putlog(LOG_MISC, "*", "Lost connection while resolving hostname [%s/%d]",
+ iptostr(dcc[idx].addr), dcc[idx].port);
+ killsock(dcc[idx].sock);
+ lostdcc(idx);
+}
+
+static void display_dcc_dnswait(int idx, char *buf)
+{
+ sprintf(buf, "dns waited %lus", now - dcc[idx].timeval);
+}
+
+static int expmem_dcc_dnswait(void *x)
+{
+ register struct dns_info *p = (struct dns_info *) x;
+ int size = 0;
+
+ if (p) {
+ size = sizeof(struct dns_info);
+ if (p->host)
+ size += strlen(p->host) + 1;
+ if (p->cbuf)
+ size += strlen(p->cbuf) + 1;
+ }
+ return size;
+}
+
+static void kill_dcc_dnswait(int idx, void *x)
+{
+ register struct dns_info *p = (struct dns_info *) x;
+
+ if (p) {
+ if (p->host)
+ nfree(p->host);
+ if (p->cbuf)
+ nfree(p->cbuf);
+ nfree(p);
+ }
+}
+
+struct dcc_table DCC_DNSWAIT =
+{
+ "DNSWAIT",
+ DCT_VALIDIDX,
+ eof_dcc_dnswait,
+ dcc_dnswait,
+ 0,
+ 0,
+ display_dcc_dnswait,
+ expmem_dcc_dnswait,
+ kill_dcc_dnswait,
+ 0
+};
+
+/* Walk through every dcc entry and look for waiting DNS requests
+ * of RES_HOSTBYIP for our IP address */
+void call_hostbyip(IP ip, char *hostn, int ok)
+{
+ int idx;
+
+ for (idx = 0; idx < dcc_total; idx++) {
+ if ((dcc[idx].type == &DCC_DNSWAIT) &&
+ (dcc[idx].u.dns->dns_type == RES_HOSTBYIP) &&
+ (dcc[idx].u.dns->ip == ip)) {
+ if (dcc[idx].u.dns->host)
+ nfree(dcc[idx].u.dns->host);
+ dcc[idx].u.dns->host = get_data_ptr(strlen(hostn) + 1);
+ strcpy(dcc[idx].u.dns->host, hostn);
+ if (ok)
+ dcc[idx].u.dns->dns_success(idx);
+ else
+ dcc[idx].u.dns->dns_failure(idx);
+ }
+ }
+}
+
+/* Walk through every dcc entry and look for waiting DNS requests
+ * of RES_IPBYHOST for our hostname */
+void call_ipbyhost(char *hostn, IP ip, int ok)
+{
+ int idx;
+
+ for (idx = 0; idx < dcc_total; idx++) {
+ if ((dcc[idx].type == &DCC_DNSWAIT) &&
+ (dcc[idx].u.dns->dns_type == RES_IPBYHOST) &&
+ !strcmp(dcc[idx].u.dns->host, hostn)) {
+ dcc[idx].u.dns->ip = ip;
+ if (ok)
+ dcc[idx].u.dns->dns_success(idx);
+ else
+ dcc[idx].u.dns->dns_failure(idx);
+ }
+ }
+}
+
+
+/*
+ * Async DNS emulation
+ */
+
+void block_dns_hostbyip(IP ip)
+{
+ struct hostent *hp;
+ unsigned long addr = htonl(ip);
+ unsigned char *p;
+ static char s[UHOSTLEN];
+
+ /*
+ * This actually copies hostnamefromip(), which is ugly, but there
+ * is no way to determine if the lookup was successful or not, using
+ * that interface.
+ */
+ if (!setjmp(alarmret)) {
+ alarm(resolve_timeout);
+ hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
+ alarm(0);
+ } else {
+ hp = NULL;
+ }
+ if (hp == NULL) {
+ p = (unsigned char *) &addr;
+ sprintf(s, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
+ } else {
+ strncpy(s, hp->h_name, UHOSTLEN - 1);
+ s[UHOSTLEN - 1] = 0;
+ }
+ /* call hooks */
+ call_hostbyip(ip, s, hp ? 1 : 0);
+}
+
+void block_dns_ipbyhost(char *host)
+{
+ if (!setjmp(alarmret)) {
+ struct hostent *hp;
+ struct in_addr *in;
+ IP ip = 0;
+
+ alarm(resolve_timeout);
+ hp = gethostbyname(host);
+ alarm(0);
+
+ in = (struct in_addr *) (hp->h_addr_list[0]);
+ ip = (IP) (in->s_addr);
+ call_ipbyhost(host, ip, 1);
+ } else {
+ call_ipbyhost(host, 0, 0);
+ }
+}
diff -urN eggdrop1.4~/src/eggdrop.h eggdrop1.4/src/eggdrop.h
--- eggdrop1.4~/src/eggdrop.h Sat Oct 9 18:33:51 1999
+++ eggdrop1.4/src/eggdrop.h Sat Oct 9 18:40:20 1999
@@ -173,6 +173,9 @@
/***********************************************************************/
+/* it's used in so many places, let's put it here */
+typedef int (*Function) ();
+
/* public structure for the listening port map */
struct portmap {
int realport;
@@ -216,6 +219,7 @@
struct bot_info *bot;
struct relay_info *relay;
struct script_info *script;
+ struct dns_info *dns;
int ident_sock;
void *other;
} u; /* special use depending on type */
@@ -275,6 +279,22 @@
char command[121];
};
+struct dns_info {
+ Function dns_success; /* is called if the dns request succeeds */
+ Function dns_failure; /* is called if it fails */
+ char *host; /* hostname */
+ char *cbuf; /* temporary buffer. Memory will be free'd
+ as soon as dns_info is free'd */
+ char *cptr; /* temporary pointer */
+ IP ip; /* IP address */
+ int ibuf; /* temporary buffer for one integer */
+ char dns_type; /* lookup type, e.g. RES_HOSTBYIP */
+};
+
+/* flags for dns_type */
+#define RES_HOSTBYIP 1 /* hostname to IP address */
+#define RES_IPBYHOST 2 /* IP address to hostname */
+
/* flags about dcc types */
#define DCT_CHAT 0x00000001 /* this dcc type receives botnet chatter */
#define DCT_MASTER 0x00000002 /* received master chatter */
@@ -386,14 +406,15 @@
#define FILEDB_UNSHARE 4
/* socket flags: */
-#define SOCK_UNUSED 0x01 /* empty socket */
-#define SOCK_BINARY 0x02 /* do not buffer input */
-#define SOCK_LISTEN 0x04 /* listening port */
-#define SOCK_CONNECT 0x08 /* connection attempt */
-#define SOCK_NONSOCK 0x10 /* used for file i/o on debug */
-#define SOCK_STRONGCONN 0x20 /* don't report success until sure */
-#define SOCK_EOFD 0x40 /* it EOF'd recently during a write */
-#define SOCK_PROXYWAIT 0x80 /* waiting for SOCKS traversal */
+#define SOCK_UNUSED 0x001 /* empty socket */
+#define SOCK_BINARY 0x002 /* do not buffer input */
+#define SOCK_LISTEN 0x004 /* listening port */
+#define SOCK_CONNECT 0x008 /* connection attempt */
+#define SOCK_NONSOCK 0x010 /* used for file i/o on debug */
+#define SOCK_STRONGCONN 0x020 /* don't report success until sure */
+#define SOCK_EOFD 0x040 /* it EOF'd recently during a write */
+#define SOCK_PROXYWAIT 0x080 /* waiting for SOCKS traversal */
+#define SOCK_PASS 0x100 /* passed on; only notify in case of traffic */
/* fake idx's for dprintf - these should be ridiculously large +ve nums */
#define DP_STDOUT 0x7FF1
@@ -423,14 +444,11 @@
#define HELP_TEXT 2
#define HELP_IRC 16
-/* it's used in so many places, let's put it here */
-typedef int (*Function) ();
-
/* this is used by the net module to keep track of sockets and what's
* queued on them */
typedef struct {
int sock;
- char flags;
+ short flags;
char *inbuf;
char *outbuf;
unsigned long outbuflen; /* outbuf could be binary data */
diff -urN eggdrop1.4~/src/main.h eggdrop1.4/src/main.h
--- eggdrop1.4~/src/main.h Sat Oct 9 18:34:15 1999
+++ eggdrop1.4/src/main.h Sat Oct 9 18:40:21 1999
@@ -44,7 +44,7 @@
extern struct dcc_table DCC_CHAT, DCC_BOT, DCC_LOST, DCC_SCRIPT, DCC_BOT_NEW,
DCC_RELAY, DCC_RELAYING, DCC_FORK_RELAY, DCC_PRE_RELAY, DCC_CHAT_PASS,
DCC_FORK_BOT, DCC_SOCKET, DCC_TELNET_ID, DCC_TELNET_NEW, DCC_TELNET_PW,
- DCC_TELNET, DCC_IDENT, DCC_IDENTWAIT;
+ DCC_TELNET, DCC_IDENT, DCC_IDENTWAIT, DCC_DNSWAIT;
#endif
@@ -60,6 +60,11 @@
#endif
#define iptolong(a) (0xffffffff & (long)(swap_long((unsigned long)a)))
#define fixcolon(x) if (x[0]==':') {x++;} else {x=newsplit(&x);}
+
+#define my_ntohs(sh) swap_short(sh)
+#define my_htons(sh) swap_short(sh)
+#define my_ntohl(ln) swap_long(ln)
+#define my_htonl(ln) swap_long(ln)
/* Stupid Borg Cube crap ;p */
#ifdef BORGCUBES
diff -urN eggdrop1.4~/src/mod/Makefile eggdrop1.4/src/mod/Makefile
--- eggdrop1.4~/src/mod/Makefile Sat Oct 9 18:33:43 1999
+++ eggdrop1.4/src/mod/Makefile Sat Oct 9 18:40:21 1999
@@ -1,6 +1,6 @@
# Source-make
-GMAKE=${MAKE} 'LD=${LD}' 'STRIP=${STRIP}' 'CC=${CC}' 'CFLAGS=${CFLAGS}'
+GMAKE=${MAKE} 'LD=${LD}' 'STRIP=${STRIP}' 'CC=${CC}' 'CFLAGS=${CFLAGS}' 'RESLIB=${RESLIB}'
doofus:
@echo ""
diff -urN eggdrop1.4~/src/mod/Makefile.generic eggdrop1.4/src/mod/Makefile.generic
--- eggdrop1.4~/src/mod/Makefile.generic Sat Oct 9 18:33:43 1999
+++ eggdrop1.4/src/mod/Makefile.generic Sat Oct 9 18:40:21 1999
@@ -14,7 +14,7 @@
static: ../${FILENAME}.o
../../../${FILENAME}.so: ${FILENAME}.o
- ${LD} -o ../../../${FILENAME}.so ${FILENAME}.o
+ ${LD} ${LDFLAGS} -o ../../../${FILENAME}.so ${FILENAME}.o
${STRIP} ../../../${FILENAME}.so
${FILENAME}.o: ${FILENAME}.c ../module.h ../modvals.h ../../eggdrop.h
diff -urN eggdrop1.4~/src/mod/dns.mod/Makefile eggdrop1.4/src/mod/dns.mod/Makefile
--- eggdrop1.4~/src/mod/dns.mod/Makefile Thu Jan 1 01:00:00 1970
+++ eggdrop1.4/src/mod/dns.mod/Makefile Sat Oct 9 18:40:21 1999
@@ -0,0 +1,11 @@
+# Source-make
+FILENAME=dns
+LDFLAGS=${RESLIB}
+
+include ../Makefile.generic
+
+dns.o: \
+ ../module.h \
+ dns.h \
+ dns.c \
+ coredns.c
diff -urN eggdrop1.4~/src/mod/dns.mod/coredns.c eggdrop1.4/src/mod/dns.mod/coredns.c
--- eggdrop1.4~/src/mod/dns.mod/coredns.c Thu Jan 1 01:00:00 1970
+++ eggdrop1.4/src/mod/dns.mod/coredns.c Sat Oct 9 18:40:21 1999
@@ -0,0 +1,1138 @@
+/*
+ * dnscore.c - This file contains all core functions needed for the
+ * eggdrop dns module. Many of them are only minimaly modified from
+ * the original source.
+ *
+ * Portions copyright (C) 1999 Eggheads
+ * Written by Fabian Knittel <fknittel at gmx.de>
+ *
+ * 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Borrowed from mtr -- a network diagnostic tool
+ * Copyright (C) 1997,1998 Matt Kimball <mkimball at xmission.com>
+ * Released under the GPL, as above.
+ *
+ * Non-blocking DNS portion --
+ * Copyright (C) 1998 Simon Kirby <sim at neato.org>
+ * Released under the GPL, as above.
+ */
+
+/*
+ * Tue Oct 05 21:52:03 1999 Fabian
+ * * #include tweaking
+ * Sun Oct 03 18:34:41 1999 Fabian
+ * * Initial release
+ */
+
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <errno.h>
+
+
+/* Defines */
+
+#define BASH_SIZE 8192 /* Size of hash tables */
+#define HOSTNAMELEN 255 /* From RFC */
+#define RES_RETRYDELAY 3
+#define RES_MAXSENDS 4
+#define RES_FAILEDDELAY 3600 /* Keep failed record for 1 hour */
+#define RES_MAX_TTL 86400 /* Maximum TTL is 1d */
+
+#define RES_ERR "DNS Resolver error: "
+#define RES_MSG "DNS Resolver: "
+#define RES_WRN "DNS Resolver warning: "
+
+#define MAX_PACKETSIZE (PACKETSZ)
+#define MAX_DOMAINLEN (MAXDNAME)
+
+/* Macros */
+
+#define nonull(s) (s) ? s : nullstring
+#define BASH_MODULO(x) ((x) & 8191) /* Modulo for hash table size */
+
+/* Non-blocking nameserver interface routines */
+
+#define OPCODES_COUNT 3
+char *opcodes[OPCODES_COUNT + 1] = {
+ "standard query",
+ "inverse query",
+ "server status request",
+ "unknown",
+};
+
+#define RESPONSECODES_COUNT 6
+char *responsecodes[RESPONSECODES_COUNT + 1] = {
+ "no error",
+ "format error in query",
+ "server failure",
+ "queried domain name does not exist",
+ "requested query type not implemented",
+ "refused by name server",
+ "unknown error",
+};
+
+#define RESOURCETYPES_COUNT 17
+char *resourcetypes[RESOURCETYPES_COUNT + 1] = {
+ "unknown type",
+ "A: host address",
+ "NS: authoritative name server",
+ "MD: mail destination (OBSOLETE)",
+ "MF: mail forwarder (OBSOLETE)",
+ "CNAME: name alias",
+ "SOA: authority record",
+ "MB: mailbox domain name (EXPERIMENTAL)",
+ "MG: mail group member (EXPERIMENTAL)",
+ "MR: mail rename domain name (EXPERIMENTAL)",
+ "NULL: NULL RR (EXPERIMENTAL)",
+ "WKS: well known service description",
+ "PTR: domain name pointer",
+ "HINFO: host information",
+ "MINFO: mailbox or mail list information",
+ "MX: mail exchange",
+ "TXT: text string",
+ "unknown type",
+};
+
+#define CLASSTYPES_COUNT 5
+char *classtypes[CLASSTYPES_COUNT + 1] = {
+ "unknown class",
+ "IN: the Internet",
+ "CS: CSNET (OBSOLETE)",
+ "CH: CHAOS",
+ "HS: Hesoid [Dyer 87]",
+ "unknown class"
+};
+
+char *rrtypes[] = {
+ "Unknown",
+ "Query",
+ "Answer",
+ "Authority reference",
+ "Resource reference",
+};
+
+enum {
+ RR_UNKNOWN,
+ RR_QUERY,
+ RR_ANSWER,
+ RR_AUTHORITY,
+ RR_RESOURCE,
+};
+
+typedef struct {
+ word id; /* Packet id */
+ byte databyte_a;
+ /* rd:1 recursion desired
+ * tc:1 truncated message
+ * aa:1 authoritive answer
+ * opcode:4 purpose of message
+ * qr:1 response flag
+ */
+ byte databyte_b;
+ /* rcode:4 response code
+ * unassigned:2 unassigned bits
+ * pr:1 primary server required (non standard)
+ * ra:1 recursion available
+ */
+ word qdcount; /* Query record count */
+ word ancount; /* Answer record count */
+ word nscount; /* Authority reference record count */
+ word arcount; /* Resource reference record count */
+} packetheader;
+
+#ifndef HFIXEDSZ
+#define HFIXEDSZ (sizeof(packetheader))
+#endif
+
+/*
+ * Byte order independent macros for packetheader
+ */
+#define getheader_rd(x) (x->databyte_a & 1)
+#define getheader_tc(x) ((x->databyte_a >> 1) & 1)
+#define getheader_aa(x) ((x->databyte_a >> 2) & 1)
+#define getheader_opcode(x) ((x->databyte_a >> 3) & 15)
+#define getheader_qr(x) (x->databyte_a >> 7)
+#define getheader_rcode(x) (x->databyte_b & 15)
+#define getheader_pr(x) ((x->databyte_b >> 6) & 1)
+#define getheader_ra(x) (x->databyte_b >> 7)
+
+#define sucknetword(x) ((x)+=2,((word) (((x)[-2] << 8) | ((x)[-1] << 0))))
+#define sucknetshort(x) ((x)+=2,((short) (((x)[-2] << 8) | ((x)[-1] << 0))))
+#define sucknetdword(x) ((x)+=4,((dword) (((x)[-4] << 24) | ((x)[-3] << 16) | \
+ ((x)[-2] << 8) | ((x)[-1] << 0))))
+#define sucknetlong(x) ((x)+=4,((long) (((x)[-4] << 24) | ((x)[-3] << 16) | \
+ ((x)[-2] << 8) | ((x)[-1] << 0))))
+
+
+dword resrecvbuf[(MAX_PACKETSIZE + 7) >> 2]; /* MUST BE DWORD ALIGNED */
+
+struct resolve *idbash[BASH_SIZE];
+struct resolve *ipbash[BASH_SIZE];
+struct resolve *hostbash[BASH_SIZE];
+struct resolve *expireresolves = NULL;
+
+IP alignedip;
+IP localhost;
+
+long idseed = 0xdeadbeef;
+long aseed;
+
+int resfd;
+
+char tempstring[16384 + 1 + 1];
+char sendstring[1024 + 1];
+char namestring[1024 + 1];
+char stackstring[1024 + 1];
+
+char nullstring[] = "";
+
+
+/*
+ * Miscellaneous helper functions
+ */
+
+/* Displays the time difference passed in signeddiff */
+static char *strtdiff(char *d, long signeddiff)
+{
+ dword diff;
+ dword seconds, minutes, hours;
+ long day;
+
+ context;
+ if ((diff = labs(signeddiff))) {
+ seconds = diff % 60;
+ diff /= 60;
+ minutes = diff % 60;
+ diff /= 60;
+ hours = diff % 24;
+ day = signeddiff / (60 * 60 * 24);
+ if (day)
+ sprintf(d, "%lid", day);
+ else
+ *d = '\0';
+ if (hours)
+ sprintf(d + strlen(d), "%luh", hours);
+ if (minutes)
+ sprintf(d + strlen(d), "%lum", minutes);
+ if (seconds)
+ sprintf(d + strlen(d), "%lus", seconds);
+ } else
+ sprintf(d, "0s");
+ return d;
+}
+
+/* Allocate memory to hold one resolve request structure */
+static struct resolve *allocresolve()
+{
+ struct resolve *rp;
+
+ rp = (struct resolve *) nmalloc(sizeof(struct resolve));
+ bzero(rp, sizeof(struct resolve));
+ return rp;
+}
+
+
+/*
+ * Hash and linked-list related functions
+ */
+
+/* Return the hash bucket number for id */
+static dword getidbash(word id)
+{
+ return (dword) BASH_MODULO(id);
+}
+
+/* Return the hash bucket number for ip */
+static dword getipbash(IP ip)
+{
+ return (dword) BASH_MODULO(ip);
+}
+
+/* Return the hash bucket number for host */
+static dword gethostbash(char *host)
+{
+ dword bashvalue = 0;
+
+ for (; *host; host++) {
+ bashvalue ^= *host;
+ bashvalue += (*host >> 1) + (bashvalue >> 1);
+ }
+ return BASH_MODULO(bashvalue);
+}
+
+/* Insert request structure addrp into the id hash table */
+static void linkresolveid(struct resolve *addrp)
+{
+ struct resolve *rp;
+ dword bashnum;
+
+ context;
+ bashnum = getidbash(addrp->id);
+ rp = idbash[bashnum];
+ if (rp) {
+ while ((rp->nextid) && (addrp->id > rp->nextid->id))
+ rp = rp->nextid;
+ while ((rp->previousid) && (addrp->id < rp->previousid->id))
+ rp = rp->previousid;
+ if (rp->id < addrp->id) {
+ addrp->previousid = rp;
+ addrp->nextid = rp->nextid;
+ if (rp->nextid)
+ rp->nextid->previousid = addrp;
+ rp->nextid = addrp;
+ } else if (rp->id > addrp->id) {
+ addrp->previousid = rp->previousid;
+ addrp->nextid = rp;
+ if (rp->previousid)
+ rp->previousid->nextid = addrp;
+ rp->previousid = addrp;
+ } else /* trying to add the same id */
+ return;
+ } else
+ addrp->nextid = addrp->previousid = NULL;
+ idbash[bashnum] = addrp;
+}
+
+/* Remove request structure rp from the id hash table */
+static void unlinkresolveid(struct resolve *rp)
+{
+ dword bashnum;
+
+ context;
+ bashnum = getidbash(rp->id);
+ if (idbash[bashnum] == rp) {
+ if (rp->previousid)
+ idbash[bashnum] = rp->previousid;
+ else
+ idbash[bashnum] = rp->nextid;
+ }
+ if (rp->nextid)
+ rp->nextid->previousid = rp->previousid;
+ if (rp->previousid)
+ rp->previousid->nextid = rp->nextid;
+}
+
+/* Insert request structure addrp intp the host hash table */
+static void linkresolvehost(struct resolve *addrp)
+{
+ struct resolve *rp;
+ dword bashnum;
+ int ret;
+
+ context;
+ bashnum = gethostbash(addrp->hostn);
+ rp = hostbash[bashnum];
+ if (rp) {
+ while ((rp->nexthost) &&
+ (strcasecmp(addrp->hostn, rp->nexthost->hostn) < 0))
+ rp = rp->nexthost;
+ while ((rp->previoushost) &&
+ (strcasecmp(addrp->hostn, rp->previoushost->hostn) > 0))
+ rp = rp->previoushost;
+ ret = strcasecmp(addrp->hostn, rp->hostn);
+ if (ret < 0) {
+ addrp->previoushost = rp;
+ addrp->nexthost = rp->nexthost;
+ if (rp->nexthost)
+ rp->nexthost->previoushost = addrp;
+ rp->nexthost = addrp;
+ } else if (ret > 0) {
+ addrp->previoushost = rp->previoushost;
+ addrp->nexthost = rp;
+ if (rp->previoushost)
+ rp->previoushost->nexthost = addrp;
+ rp->previoushost = addrp;
+ } else /* trying to add the same host */
+ return;
+ } else
+ addrp->nexthost = addrp->previoushost = NULL;
+ hostbash[bashnum] = addrp;
+}
+
+/* Remove request structure rp from the host hash table */
+static void unlinkresolvehost(struct resolve *rp)
+{
+ dword bashnum;
+
+ context;
+ bashnum = gethostbash(rp->hostn);
+ if (hostbash[bashnum] == rp) {
+ if (rp->previoushost)
+ hostbash[bashnum] = rp->previoushost;
+ else
+ hostbash[bashnum] = rp->nexthost;
+ }
+ if (rp->nexthost)
+ rp->nexthost->previoushost = rp->previoushost;
+ if (rp->previoushost)
+ rp->previoushost->nexthost = rp->nexthost;
+ nfree(rp->hostn);
+}
+
+/* Insert request structure addrp into the ip hash table */
+static void linkresolveip(struct resolve *addrp)
+{
+ struct resolve *rp;
+ dword bashnum;
+
+ context;
+ bashnum = getipbash(addrp->ip);
+ rp = ipbash[bashnum];
+ if (rp) {
+ while ((rp->nextip) && (addrp->ip > rp->nextip->ip))
+ rp = rp->nextip;
+ while ((rp->previousip) && (addrp->ip < rp->previousip->ip))
+ rp = rp->previousip;
+ if (rp->ip < addrp->ip) {
+ addrp->previousip = rp;
+ addrp->nextip = rp->nextip;
+ if (rp->nextip)
+ rp->nextip->previousip = addrp;
+ rp->nextip = addrp;
+ } else if (rp->ip > addrp->ip) {
+ addrp->previousip = rp->previousip;
+ addrp->nextip = rp;
+ if (rp->previousip)
+ rp->previousip->nextip = addrp;
+ rp->previousip = addrp;
+ } else /* trying to add the same ip */
+ return;
+ } else
+ addrp->nextip = addrp->previousip = NULL;
+ ipbash[bashnum] = addrp;
+}
+
+/* Remove request structure rp from the ip hash table */
+static void unlinkresolveip(struct resolve *rp)
+{
+ dword bashnum;
+
+ context;
+ bashnum = getipbash(rp->ip);
+ if (ipbash[bashnum] == rp) {
+ if (rp->previousip)
+ ipbash[bashnum] = rp->previousip;
+ else
+ ipbash[bashnum] = rp->nextip;
+ }
+ if (rp->nextip)
+ rp->nextip->previousip = rp->previousip;
+ if (rp->previousip)
+ rp->previousip->nextip = rp->nextip;
+}
+
+/* Add request structure rp to the expireresolves list. Entries are sorted
+ * by expire time. */
+static void linkresolve(struct resolve *rp)
+{
+ struct resolve *irp;
+
+ context;
+ if (expireresolves) {
+ irp = expireresolves;
+ while ((irp->next) && (rp->expiretime >= irp->expiretime))
+ irp = irp->next;
+ if (rp->expiretime >= irp->expiretime) {
+ rp->next = NULL;
+ rp->previous = irp;
+ irp->next = rp;
+ } else {
+ rp->previous = irp->previous;
+ rp->next = irp;
+ if (irp->previous)
+ irp->previous->next = rp;
+ else
+ expireresolves = rp;
+ irp->previous = rp;
+ }
+ } else {
+ rp->next = NULL;
+ rp->previous = NULL;
+ expireresolves = rp;
+ }
+}
+
+/* Remove reqeust structure rp from the expireresolves list */
+static void untieresolve(struct resolve *rp)
+{
+ context;
+ if (rp->previous)
+ rp->previous->next = rp->next;
+ else
+ expireresolves = rp->next;
+ if (rp->next)
+ rp->next->previous = rp->previous;
+}
+
+/* Remove request structure rp from all lists and hash tables and
+ * then delete and free the structure */
+static void unlinkresolve(struct resolve *rp)
+{
+ context;
+ untieresolve(rp);
+ unlinkresolveid(rp);
+ unlinkresolveip(rp);
+ if (rp->hostn)
+ unlinkresolvehost(rp);
+ nfree(rp);
+ context;
+}
+
+/* Find request structure using the id */
+static struct resolve *findid(word id)
+{
+ struct resolve *rp;
+ int bashnum;
+
+ context;
+ bashnum = getidbash(id);
+ rp = idbash[bashnum];
+ if (rp) {
+ while ((rp->nextid) && (id >= rp->nextid->id))
+ rp = rp->nextid;
+ while ((rp->previousid) && (id <= rp->previousid->id))
+ rp = rp->previousid;
+ if (id == rp->id) {
+ idbash[bashnum] = rp;
+ return rp;
+ } else
+ return NULL;
+ }
+ return rp; /* NULL */
+}
+
+/* Find request structure using the host */
+static struct resolve *findhost(char *hostn)
+{
+ struct resolve *rp;
+ int bashnum;
+
+ context;
+ bashnum = gethostbash(hostn);
+ rp = hostbash[bashnum];
+ if (rp) {
+ while ((rp->nexthost)
+ && (strcasecmp(hostn, rp->nexthost->hostn) >= 0))
+ rp = rp->nexthost;
+ while ((rp->previoushost)
+ && (strcasecmp(hostn, rp->nexthost->hostn) <= 0))
+ rp = rp->previoushost;
+ if (strcasecmp(hostn, rp->hostn))
+ return NULL;
+ else {
+ hostbash[bashnum] = rp;
+ return rp;
+ }
+ }
+ return rp; /* NULL */
+}
+
+/* Find request structure using the ip */
+static struct resolve *findip(IP ip)
+{
+ struct resolve *rp;
+ dword bashnum;
+
+ context;
+ bashnum = getipbash(ip);
+ rp = ipbash[bashnum];
+ if (rp) {
+ while ((rp->nextip) && (ip >= rp->nextip->ip))
+ rp = rp->nextip;
+ while ((rp->previousip) && (ip <= rp->previousip->ip))
+ rp = rp->previousip;
+ if (ip == rp->ip) {
+ ipbash[bashnum] = rp;
+ return rp;
+ } else
+ return NULL;
+ }
+ return rp; /* NULL */
+}
+
+
+/*
+ * Network and resolver related functions
+ */
+
+/* Create packet for the request and send it to all available nameservers */
+static void dorequest(char *s, int type, word id)
+{
+ packetheader *hp;
+ int r, i;
+ char buf[(MAX_PACKETSIZE / sizeof(char)) + 1];
+
+ context;
+ r = res_mkquery(QUERY, s, C_IN, type, NULL, 0, NULL, buf,
+ MAX_PACKETSIZE);
+ if (r == -1) {
+ debug0(RES_ERR "Query too large.");
+ return;
+ }
+ hp = (packetheader *) buf;
+ hp->id = id; /* my_htons() deliberately left out (redundant) */
+ for (i = 0; i < _res.nscount; i++)
+ (void) sendto(resfd, buf, r, 0,
+ (struct sockaddr *) &_res.nsaddr_list[i],
+ sizeof(struct sockaddr));
+}
+
+/* (Re-)send request with existing id */
+static void resendrequest(struct resolve *rp, int type)
+{
+ context;
+ rp->sends++;
+ /* update expire time */
+ rp->expiretime = now + (RES_RETRYDELAY * rp->sends);
+ /* add (back) to expire list */
+ linkresolve(rp);
+
+ if (type == T_A) {
+ dorequest(rp->hostn, type, rp->id);
+ debug1(RES_MSG "Sent domain lookup request for \"%s\".",
+ rp->hostn);
+ } else if (type == T_PTR) {
+ sprintf(tempstring, "%u.%u.%u.%u.in-addr.arpa",
+ ((byte *) & rp->ip)[3],
+ ((byte *) & rp->ip)[2],
+ ((byte *) & rp->ip)[1], ((byte *) & rp->ip)[0]);
+ dorequest(tempstring, type, rp->id);
+ debug1(RES_MSG "Sent domain lookup request for \"%s\".",
+ iptostr(rp->ip));
+ }
+}
+
+/* Send request for the first time */
+static void sendrequest(struct resolve *rp, int type)
+{
+ context;
+ /* Create unique id */
+ do {
+ idseed = (((idseed + idseed) | (long) time(NULL))
+ + idseed - 0x54bad4a) ^ aseed;
+ aseed ^= idseed;
+ rp->id = (word) idseed;
+ } while (findid(rp->id));
+ linkresolveid(rp); /* Add id to id hash table */
+ resendrequest(rp, type); /* Send request */
+}
+
+/* Gets called as soon as the request turns out to have failed . Calls
+ * the eggdrop hook. */
+static void failrp(struct resolve *rp)
+{
+ context;
+ if (rp->state == STATE_FINISHED)
+ return;
+ rp->expiretime = now + RES_FAILEDDELAY;
+ rp->state = STATE_FAILED;
+
+ /* expire time was changed, reinsert entry to maintain order */
+ untieresolve(rp);
+ linkresolve(rp);
+
+ debug0(RES_MSG "Lookup failed.");
+ dns_event_failure(rp);
+}
+
+/* Gets called as soon as the request turns out to be successful. Calls
+ * the eggdrop hook. */
+static void passrp(struct resolve *rp, long ttl, int type)
+{
+ context;
+ rp->state = STATE_FINISHED;
+
+ /* Do not cache entries for too long. */
+ if (ttl < RES_MAX_TTL)
+ rp->expiretime = now + (time_t) ttl;
+ else
+ rp->expiretime = now + RES_MAX_TTL;
+
+ /* Expire time was changed, reinsert entry to maintain order */
+ untieresolve(rp);
+ linkresolve(rp);
+
+ debug1(RES_MSG "Lookup successful: %s", rp->hostn);
+ dns_event_success(rp, type);
+}
+
+/* Parses the response packets received */
+static void parserespacket(byte * s, int l)
+{
+ struct resolve *rp;
+ packetheader *hp;
+ byte *eob;
+ byte *c;
+ long ttl;
+ int r, usefulanswer;
+ word rr, datatype, class, qdatatype, qclass;
+ byte rdatalength;
+
+ context;
+ if (l < sizeof(packetheader)) {
+ debug0(RES_ERR "Packet smaller than standard header size.");
+ return;
+ }
+ if (l == sizeof(packetheader)) {
+ debug0(RES_ERR "Packet has empty body.");
+ return;
+ }
+ hp = (packetheader *) s;
+ /* Convert data to host byte order */
+ /* hp->id does not need to be redundantly byte-order flipped, it
+ * is only echoed by nameserver */
+ rp = findid(hp->id);
+ if (!rp)
+ return;
+ if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED))
+ return;
+ hp->qdcount = my_ntohs(hp->qdcount);
+ hp->ancount = my_ntohs(hp->ancount);
+ hp->nscount = my_ntohs(hp->nscount);
+ hp->arcount = my_ntohs(hp->arcount);
+ if (getheader_tc(hp)) { /* Packet truncated */
+ debug0(RES_ERR "Nameserver packet truncated.");
+ return;
+ }
+ if (!getheader_qr(hp)) { /* Not a reply */
+ debug0(RES_ERR "Query packet received on nameserver communication socket.");
+ return;
+ }
+ if (getheader_opcode(hp)) { /* Not opcode 0 (standard query) */
+ debug0(RES_ERR "Invalid opcode in response packet.");
+ return;
+ }
+ eob = s + l;
+ c = s + HFIXEDSZ;
+ context;
+ switch (getheader_rcode(hp)) {
+ case NOERROR:
+ context;
+ if (hp->ancount) {
+ debug4(RES_MSG
+ "Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)",
+ hp->qdcount, hp->ancount, hp->nscount, hp->arcount);
+ if (hp->qdcount != 1) {
+ debug0(RES_ERR "Reply does not contain one query.");
+ return;
+ }
+ if (c > eob) {
+ debug0(RES_ERR "Reply too short.");
+ return;
+ }
+ switch (rp->state) { /* Construct expected query reply */
+ case STATE_PTRREQ:
+ sprintf(stackstring,
+ "%u.%u.%u.%u.in-addr.arpa",
+ ((byte *) & rp->ip)[3],
+ ((byte *) & rp->ip)[2],
+ ((byte *) & rp->ip)[1], ((byte *) & rp->ip)[0]);
+ break;
+ case STATE_AREQ:
+ strncpy(stackstring, rp->hostn, 1024);
+ }
+ *namestring = '\0';
+ r = dn_expand(s, s + l, c, namestring, MAXDNAME);
+ if (r == -1) {
+ debug0(RES_ERR "dn_expand() failed while expanding query domain.");
+ return;
+ }
+ namestring[strlen(stackstring)] = '\0';
+ if (strcasecmp(stackstring, namestring)) {
+ debug2(RES_MSG "Unknown query packet dropped. (\"%s\" does not match \"%s\")", stackstring, namestring);
+ return;
+ }
+ debug1(RES_MSG "Queried domain name: \"%s\"", namestring);
+ c += r;
+ if (c + 4 > eob) {
+ debug0(RES_ERR "Query resource record truncated.");
+ return;
+ }
+ qdatatype = sucknetword(c);
+ qclass = sucknetword(c);
+ if (qclass != C_IN) {
+ debug2(RES_ERR "Received unsupported query class: %u (%s)",
+ qclass, qclass < CLASSTYPES_COUNT ?
+ classtypes[qclass] :
+ classtypes[CLASSTYPES_COUNT]);
+ }
+ switch (qdatatype) {
+ case T_PTR:
+ if (!IS_PTR(rp)) {
+ debug0(RES_WRN "Ignoring response with unexpected query type \"PTR\".");
+ return;
+ }
+ break;
+ case T_A:
+ if (!IS_A(rp)) {
+ debug0(RES_WRN "Ignoring response with unexpected query type \"PTR\".");
+ return;
+ }
+ break;
+ default:
+ debug2(RES_ERR "Received unimplemented query type: %u (%s)",
+ qdatatype,
+ qdatatype < RESOURCETYPES_COUNT ?
+ resourcetypes[qdatatype] :
+ resourcetypes[RESOURCETYPES_COUNT]);
+ }
+ for (rr = hp->ancount + hp->nscount + hp->arcount; rr; rr--) {
+ context;
+ if (c > eob) {
+ debug0(RES_ERR "Packet does not contain all specified resouce records.");
+ return;
+ }
+ *namestring = '\0';
+ r = dn_expand(s, s + l, c, namestring, MAXDNAME);
+ if (r == -1) {
+ debug0(RES_ERR "dn_expand() failed while expanding answer domain.");
+ return;
+ }
+ namestring[strlen(stackstring)] = '\0';
+ if (strcasecmp(stackstring, namestring))
+ usefulanswer = 0;
+ else
+ usefulanswer = 1;
+ debug1(RES_MSG "answered domain query: \"%s\"", namestring);
+ c += r;
+ if (c + 10 > eob) {
+ debug0(RES_ERR "Resource record truncated.");
+ return;
+ }
+ datatype = sucknetword(c);
+ class = sucknetword(c);
+ ttl = sucknetlong(c);
+ rdatalength = sucknetword(c);
+ if (class != qclass) {
+ debug2(RES_MSG "query class: %u (%s)",
+ qclass,
+ qclass < CLASSTYPES_COUNT ?
+ classtypes[qclass] :
+ classtypes[CLASSTYPES_COUNT]);
+ debug2(RES_MSG "rr class: %u (%s)", class,
+ class < CLASSTYPES_COUNT ?
+ classtypes[class] :
+ classtypes[CLASSTYPES_COUNT]);
+ debug0(RES_ERR "Answered class does not match queried class.");
+ return;
+ }
+ if (!rdatalength) {
+ debug0(RES_ERR "Zero size rdata.");
+ return;
+ }
+ if (c + rdatalength > eob) {
+ debug0(RES_ERR "Specified rdata length exceeds packet size.");
+ return;
+ }
+ context;
+ if (datatype == qdatatype) {
+ debug1(RES_MSG "TTL: %s", strtdiff(sendstring, ttl));
+ debug1(RES_MSG "TYPE: %s", datatype < RESOURCETYPES_COUNT ?
+ resourcetypes[datatype] :
+ resourcetypes[RESOURCETYPES_COUNT]);
+ if (usefulanswer)
+ switch (datatype) {
+ case T_A:
+ if (rdatalength != 4) {
+ debug1(RES_ERR "Unsupported rdata format for \"A\" type. (%u bytes)", rdatalength);
+ return;
+ }
+ my_memcpy(&rp->ip, (IP *) c, sizeof(IP));
+ linkresolveip(rp);
+ passrp(rp, ttl, T_A);
+ return;
+ case T_PTR:
+ *namestring = '\0';
+ r = dn_expand(s, s + l, c, namestring, MAXDNAME);
+ if (r == -1) {
+ debug0(RES_ERR "dn_expand() failed while expanding domain in rdata.");
+ return;
+ }
+ debug1(RES_MSG "Answered domain: \"%s\"",
+ namestring);
+ if (r > HOSTNAMELEN) {
+ debug0(RES_ERR "Domain name too long.");
+ failrp(rp);
+ return;
+ }
+ if (!rp->hostn) {
+ rp->hostn = (char *)nmalloc(strlen(namestring) + 1);
+ strcpy(rp->hostn, namestring);
+ linkresolvehost(rp);
+ passrp(rp, ttl, T_PTR);
+ return;
+ }
+ break;
+ default:
+ debug2(RES_ERR "Received unimplemented data type: %u (%s)",
+ datatype,
+ datatype < RESOURCETYPES_COUNT ?
+ resourcetypes[datatype] :
+ resourcetypes[RESOURCETYPES_COUNT]);
+ }
+ } else if (datatype == T_CNAME) {
+ *namestring = '\0';
+ r = dn_expand(s, s + l, c, namestring, MAXDNAME);
+ if (r == -1) {
+ debug0(RES_ERR "dn_expand() failed while expanding domain in rdata.");
+ return;
+ }
+ debug1(RES_MSG "answered domain is CNAME for: %s",
+ namestring);
+ /* The next responses will be related to the domain
+ * pointed to by CNAME, so we need to update which
+ * respones we regard as important. */
+ strncpy(stackstring, namestring, 1024);
+ } else {
+ debug2(RES_MSG "Ignoring resource type %u. (%s)",
+ datatype, datatype < RESOURCETYPES_COUNT ?
+ resourcetypes[datatype] :
+ resourcetypes[RESOURCETYPES_COUNT]);
+ }
+ c += rdatalength;
+ }
+ } else
+ debug0(RES_ERR "No error returned but no answers given.");
+ break;
+ case NXDOMAIN:
+ context;
+ debug0(RES_MSG "Host not found.");
+ failrp(rp);
+ break;
+ default:
+ context;
+ debug2(RES_MSG "Received error response %u. (%s)",
+ getheader_rcode(hp),
+ getheader_rcode(hp) < RESPONSECODES_COUNT ?
+ responsecodes[getheader_rcode(hp)] :
+ responsecodes[RESPONSECODES_COUNT]);
+ }
+ context;
+}
+
+/* Read data received on our dns socket. This function should be called
+ * as soon as traffic is detected. */
+static void dns_ack(void)
+{
+ struct sockaddr_in from;
+ int fromlen = sizeof(struct sockaddr_in);
+ int r, i;
+
+ context;
+ r = recvfrom(resfd, (byte *) resrecvbuf, MAX_PACKETSIZE, 0,
+ (struct sockaddr *) &from, &fromlen);
+ if (r <= 0) {
+ debug1(RES_MSG "Socket error: %s", strerror(errno));
+ return;
+ }
+ /* Check to see if this server is actually one we sent to */
+ if (from.sin_addr.s_addr == localhost) {
+ for (i = 0; i < _res.nscount; i++)
+ /* 0.0.0.0 replies as 127.0.0.1 */
+ if ((_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr)
+ || (!_res.nsaddr_list[i].sin_addr.s_addr))
+ break;
+ } else {
+ for (i = 0; i < _res.nscount; i++)
+ if (_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr)
+ break;
+ }
+ if (i == _res.nscount) {
+ debug1(RES_ERR "Received reply from unknown source: %s",
+ iptostr(from.sin_addr.s_addr));
+ } else
+ parserespacket((byte *) resrecvbuf, r);
+ context;
+}
+
+/* Remove or resend expired requests. Called once a second. */
+static void dns_check_expires(void)
+{
+ struct resolve *rp, *nextrp;
+
+ context;
+ for (rp = expireresolves; (rp) && (now >= rp->expiretime);
+ rp = nextrp) {
+ nextrp = rp->next;
+ untieresolve(rp);
+ switch (rp->state) {
+ case STATE_FINISHED: /* TTL has expired */
+ case STATE_FAILED: /* Fake TTL has expired */
+ context;
+ debug4(RES_MSG "Cache record for \"%s\" (%s) has expired. (state: %u) Marked for expire at: %ld.",
+ nonull(rp->hostn), iptostr(rp->ip), rp->state,
+ rp->expiretime);
+ unlinkresolve(rp);
+ break;
+ case STATE_PTRREQ: /* T_PTR send timed out */
+ context;
+ if (rp->sends <= RES_MAXSENDS) {
+ debug1(RES_MSG "Resend #%d for \"PTR\" query...", rp->sends - 1);
+ resendrequest(rp, T_PTR);
+ } else {
+ debug0(RES_MSG "\"PTR\" query timed out.");
+ failrp(rp);
+ }
+ break;
+ case STATE_AREQ: /* T_A send timed out */
+ context;
+ if (rp->sends <= RES_MAXSENDS) {
+ debug1(RES_MSG "Resend #%d for \"A\" query...", rp->sends - 1);
+ resendrequest(rp, T_A);
+ } else {
+ debug0(RES_MSG "\"A\" query timed out.");
+ failrp(rp);
+ }
+ break;
+ default: /* Unknown state, let it expire */
+ debug1(RES_WRN "Unknown request state %d. Request expired.",
+ rp->state);
+ failrp(rp);
+ }
+ }
+ context;
+}
+
+/* Start searching for a host-name using it's ip-address */
+static void dns_lookup(IP ip)
+{
+ struct resolve *rp;
+
+ context;
+ ip = htonl(ip);
+ if ((rp = findip(ip))) {
+ if ((rp->state == STATE_FINISHED)
+ || (rp->state == STATE_FAILED)) {
+ if ((rp->state == STATE_FINISHED) && (rp->hostn)) {
+ debug2(RES_MSG "Used cached record: %s == \"%s\".",
+ iptostr(ip), rp->hostn);
+ dns_event_success(rp, T_PTR);
+ } else {
+ debug1(RES_MSG "Used failed record: %s == ???", iptostr(ip));
+ dns_event_failure(rp);
+ }
+ }
+ return;
+ }
+
+ context;
+ debug0(RES_MSG "Creating new record");
+ rp = allocresolve();
+ rp->state = STATE_PTRREQ;
+ rp->sends = 1;
+ rp->ip = ip;
+ linkresolveip(rp);
+ sendrequest(rp, T_PTR);
+ context;
+}
+
+/* Start searching for an ip-address using it's host-name */
+static void dns_forward(char *hostn)
+{
+ struct resolve *rp;
+
+ context;
+ if ((rp = findhost(hostn))) {
+ if ((rp->state == STATE_FINISHED)
+ || (rp->state == STATE_FAILED)) {
+ if ((rp->state == STATE_FINISHED) && (rp->ip)) {
+ debug2(RES_MSG "Used cached record: %s == \"%s\".", hostn,
+ iptostr(rp->ip));
+ dns_event_success(rp, T_A);
+ } else {
+ debug1(RES_MSG "Used failed record: %s == ???", hostn);
+ dns_event_failure(rp);
+ }
+ }
+ return;
+ }
+
+ context;
+ debug0(RES_MSG "Creating new record");
+ rp = allocresolve();
+ rp->state = STATE_AREQ;
+ rp->sends = 1;
+ rp->hostn = (char *)nmalloc(strlen(hostn) + 1);
+ strcpy(rp->hostn, hostn);
+ linkresolvehost(rp);
+ sendrequest(rp, T_A);
+ context;
+}
+
+/* Initialise the network */
+static int init_network(void)
+{
+ int option;
+ struct in_addr inaddr;
+
+ context;
+ resfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (resfd == -1) {
+ putlog(LOG_MISC, "*",
+ "Unable to allocate socket for nameserver communication: %s",
+ strerror(errno));
+ return 0;
+ }
+ (void) allocsock(resfd, SOCK_PASS);
+ option = 1;
+ if (setsockopt(resfd, SOL_SOCKET, SO_BROADCAST, (char *) &option,
+ sizeof(option))) {
+ putlog(LOG_MISC, "*",
+ "Unable to setsockopt() on nameserver communication socket: %s",
+ strerror(errno));
+ killsock(resfd);
+ return 0;
+ }
+
+ inet_aton("127.0.0.1", &inaddr);
+ localhost = inaddr.s_addr;
+ return 1;
+}
+
+/* Initialise the core dns system, returns 1 if all goes well, 0 if not */
+static int dns_open(void)
+{
+ int i;
+
+ context;
+ /* Initialise the resolv library */
+ res_init();
+ if (!_res.nscount) {
+ putlog(LOG_MISC, "*", "No nameservers defined.");
+ return 0;
+ }
+ _res.options |= RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
+ for (i = 0; i < _res.nscount; i++)
+ _res.nsaddr_list[i].sin_family = AF_INET;
+
+ if (!init_network())
+ return 0;
+
+ context;
+ /* Initialise the hash tables */
+ aseed = time(NULL) ^ (time(NULL) << 3) ^ (dword) getpid();
+ for (i = 0; i < BASH_SIZE; i++) {
+ idbash[i] = NULL;
+ hostbash[i] = NULL;
+ }
+ context;
+ return 1;
+}
diff -urN eggdrop1.4~/src/mod/dns.mod/dns.c eggdrop1.4/src/mod/dns.mod/dns.c
--- eggdrop1.4~/src/mod/dns.mod/dns.c Thu Jan 1 01:00:00 1970
+++ eggdrop1.4/src/mod/dns.mod/dns.c Sat Oct 9 18:40:21 1999
@@ -0,0 +1,252 @@
+/*
+ * dns.c - domain lookup glue code for eggdrop
+ *
+ * Copyright (C) 1999 Eggheads
+ * Written by Fabian Knittel <fknittel at gmx.de>
+ *
+ * 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Sun Oct 03 18:34:41 1999 Fabian
+ * * Initial release
+ */
+
+
+#define MODULE_NAME "dns"
+
+#include "../module.h"
+#include "dns.h"
+
+static void dns_event_success();
+static void dns_event_failure();
+
+
+static Function *global = NULL;
+
+#include "coredns.c"
+
+
+/*
+ * DNS event related code
+ */
+
+static void dns_event_success(struct resolve *rp, int type)
+{
+ if (!rp)
+ return;
+
+ if (type == T_PTR) {
+ debug2("DNS resolved %s to %s", iptostr(rp->ip), rp->hostn);
+ call_hostbyip(ntohl(rp->ip), rp->hostn, 1);
+ } else if (type == T_A) {
+ debug2("DNS resolved %s to %s", rp->hostn, iptostr(rp->ip));
+ call_ipbyhost(rp->hostn, ntohl(rp->ip), 1);
+ }
+}
+
+static void dns_event_failure(struct resolve *rp)
+{
+ if (!rp)
+ return;
+
+ /* T_PTR */
+ if (rp->ip) {
+ static char s[UHOSTLEN];
+
+ debug1("DNS resolve failed for %s", iptostr(rp->ip));
+ strcpy(s, iptostr(rp->ip));
+ call_hostbyip(ntohl(rp->ip), s, 0);
+ }
+ /* T_A */
+ else if (rp->hostn) {
+ debug1("DNS resolve failed for %s", rp->hostn);
+ call_ipbyhost(rp->hostn, 0, 0);
+ }
+ return;
+}
+
+
+/*
+ * DNS Socket related code
+ */
+
+static void eof_dns_socket(int idx)
+{
+ putlog(LOG_MISC, "*", "DNS Error: socket closed.");
+ killsock(dcc[idx].sock);
+ /* try to reopen socket */
+ if (init_network()) {
+ putlog(LOG_MISC, "*", "DNS socket successfully reopened!");
+ dcc[idx].sock = resfd;
+ dcc[idx].timeval = now;
+ } else
+ lostdcc(idx);
+}
+
+static void dns_socket(int idx, char *buf, int len)
+{
+ dns_ack();
+}
+
+static void display_dns_socket(int idx, char *buf)
+{
+ strcpy(buf, "dns (ready)");
+}
+
+struct dcc_table DCC_DNS =
+{
+ "DNS",
+ DCT_LISTEN,
+ eof_dns_socket,
+ dns_socket,
+ 0,
+ 0,
+ display_dns_socket,
+ 0,
+ 0,
+ 0
+};
+
+
+/*
+ * DNS module related code
+ */
+
+static void cmd_resolve(struct userrec *u, int idx, char *par)
+{
+ struct in_addr inaddr;
+
+ context;
+ if (inet_aton(par, &inaddr)) {
+ dns_lookup(my_ntohl(inaddr.s_addr));
+ } else {
+ dns_forward(par);
+ }
+ return;
+}
+
+
+static void dns_free_cache(void)
+{
+ struct resolve *rp = expireresolves, *rpnext;
+
+ context;
+ while (rp) {
+ rpnext = rp->next;
+ if (rp->hostn)
+ nfree(rp->hostn);
+ nfree(rp);
+ rp = rpnext;
+ }
+ expireresolves = NULL;
+}
+
+static int dns_cache_expmem(void)
+{
+ struct resolve *rp = expireresolves;
+ int size = 0;
+
+ while (rp) {
+ size += sizeof(struct resolve);
+ if (rp->hostn)
+ size += strlen(rp->hostn) + 1;
+ rp = rp->next;
+ }
+
+ return size;
+}
+
+static int dns_expmem(void)
+{
+ return dns_cache_expmem();
+}
+
+static int dns_report(int idx, int details)
+{
+ dprintf(idx, " DNS resolver is active.\n");
+ if (details)
+ dprintf(idx, " (cache uses %d bytes of memory)\n", dns_cache_expmem());
+ return 0;
+}
+
+static cmd_t dns_dcc[] = {
+ {"resolve", "", (Function) cmd_resolve, NULL},
+ {NULL, NULL, NULL, NULL}
+};
+
+static char *dns_close()
+{
+ int i;
+
+ context;
+ del_hook(HOOK_DNS_HOSTBYIP, dns_lookup);
+ del_hook(HOOK_DNS_IPBYHOST, dns_forward);
+ del_hook(HOOK_SECONDLY, dns_check_expires);
+ rem_builtins(H_dcc, dns_dcc);
+
+ context;
+ for (i = 0; i < dcc_total; i++) {
+ if ((dcc[i].type == &DCC_DNS) &&
+ (dcc[i].sock == resfd)) {
+ killsock(dcc[i].sock);
+ lostdcc(i);
+ break;
+ }
+ }
+
+ context;
+ dns_free_cache();
+ context;
+ module_undepend(MODULE_NAME);
+ context;
+ return NULL;
+}
+
+char *dns_start();
+
+static Function dns_table[] =
+{
+ /* 0 - 3 */
+ (Function) dns_start,
+ (Function) dns_close,
+ (Function) dns_expmem,
+ (Function) dns_report,
+ /* 4 - 7 */
+};
+
+char *dns_start(Function * global_funcs)
+{
+ int i;
+
+ global = global_funcs;
+ context;
+ if (!dns_open())
+ return "DNS initialisation failed.";
+ i = new_dcc(&DCC_DNS, 0);
+ dcc[i].sock = resfd;
+ dcc[i].timeval = now;
+ strcpy(dcc[i].nick, "(dns)");
+
+ context;
+ module_register(MODULE_NAME, dns_table, 1, 0);
+ context;
+ add_hook(HOOK_SECONDLY, dns_check_expires);
+ add_hook(HOOK_DNS_HOSTBYIP, dns_lookup);
+ add_hook(HOOK_DNS_IPBYHOST, dns_forward);
+ add_builtins(H_dcc, dns_dcc);
+ context;
+ return NULL;
+}
diff -urN eggdrop1.4~/src/mod/dns.mod/dns.h eggdrop1.4/src/mod/dns.mod/dns.h
--- eggdrop1.4~/src/mod/dns.mod/dns.h Thu Jan 1 01:00:00 1970
+++ eggdrop1.4/src/mod/dns.mod/dns.h Sat Oct 9 18:40:21 1999
@@ -0,0 +1,68 @@
+/*
+ * dns.h - dns module header file
+ *
+ * Copyright (C) 1999 Eggheads
+ * Written by Fabian Knittel <fknittel at gmx.de>
+ *
+ * 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 program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Borrowed from mtr -- a network diagnostic tool
+ * Copyright (C) 1997,1998 Matt Kimball <mkimball at xmission.com>
+ * Released under GPL, as above.
+ *
+ * Non-blocking DNS portion --
+ * Copyright (C) 1998 Simon Kirby <sim at neato.org>
+ * Released under GPL, as above.
+ */
+
+#ifndef MOD_DNS_H
+#define MOD_DNS_H
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long dword;
+typedef unsigned int ip_t;
+
+struct resolve {
+ struct resolve *next;
+ struct resolve *previous;
+ struct resolve *nextid;
+ struct resolve *previousid;
+ struct resolve *nextip;
+ struct resolve *previousip;
+ struct resolve *nexthost;
+ struct resolve *previoushost;
+ time_t expiretime;
+ char *hostn;
+ ip_t ip;
+ word id;
+ byte state;
+ byte sends;
+};
+
+enum {
+ STATE_FINISHED,
+ STATE_FAILED,
+ STATE_PTRREQ,
+ STATE_AREQ,
+};
+
+#define IS_PTR(x) (x->state == STATE_PTRREQ)
+#define IS_A(x) (x->state == STATE_AREQ)
+
+#endif /* MOD_DNS_H */
+
diff -urN eggdrop1.4~/src/mod/filesys.mod/filesys.c eggdrop1.4/src/mod/filesys.mod/filesys.c
--- eggdrop1.4~/src/mod/filesys.mod/filesys.c Sat Oct 9 18:33:46 1999
+++ eggdrop1.4/src/mod/filesys.mod/filesys.c Sat Oct 9 18:40:21 1999
@@ -558,13 +558,16 @@
out_dcc_files
};
+
+static void filesys_dcc_send_lookupfailure(int);
+static void filesys_dcc_send_lookupsuccess(int);
+
/* received a ctcp-dcc */
static void filesys_dcc_send(char *nick, char *from, struct userrec *u,
char *text)
{
- char *param, *ip, *prt, buf[512], s1[512], *msg = buf;
- FILE *f;
- int atr = u ? u->flags : 0, i, j;
+ char *param, *ip, *prt, buf[512], *msg = buf;
+ int atr = u ? u->flags : 0, i;
context;
strcpy(buf, text);
@@ -607,25 +610,62 @@
/* This looks like a good place for a sanity check. */
if (!sanitycheck_dcc(nick, from, ip, prt))
return;
- i = new_dcc(&DCC_FORK_SEND, sizeof(struct xfer_info));
+ i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
if (i < 0) {
dprintf(DP_HELP, "NOTICE %s :Sorry, too many DCC connections.\n",
nick);
putlog(LOG_MISC, "*", "DCC connections full: SEND %s (%s!%s)",
param, nick, from);
+ return;
}
dcc[i].addr = my_atoul(ip);
dcc[i].port = atoi(prt);
dcc[i].sock = -1;
+ dcc[i].user = u;
strcpy(dcc[i].nick, nick);
strcpy(dcc[i].host, from);
+ dcc[i].u.dns->cbuf = get_data_ptr(strlen(param) + 1);
+ strcpy(dcc[i].u.dns->cbuf, param);
+ dcc[i].u.dns->ibuf = atoi(msg);
+ dcc[i].u.dns->ip = dcc[i].addr;
+ dcc[i].u.dns->dns_type = RES_HOSTBYIP;
+ dcc[i].u.dns->dns_success = (Function) filesys_dcc_send_lookupsuccess;
+ dcc[i].u.dns->dns_failure = (Function) filesys_dcc_send_lookupfailure;
+
+ dns_hostbyip(dcc[i].addr);
+ }
+ }
+}
+
+static void filesys_dcc_send_lookupfailure(int i)
+{
+ putlog(LOG_DEBUG, "*", "Reverse lookup failed for %s",
+ iptostr(my_htonl(dcc[i].addr)));
+ lostdcc(i);
+}
+
+static void filesys_dcc_send_lookupsuccess(int i)
+{
+ FILE *f;
+ char s1[512], param[512];
+ int len = dcc[i].u.dns->ibuf, j;
+
+ strncpy(param, dcc[i].u.dns->cbuf, 511);
+ sprintf(s1, "%d", dcc[i].port);
+ if (!hostsanitycheck_dcc(dcc[i].nick, dcc[i].host, dcc[i].addr,
+ dcc[i].u.dns->host, s1)) {
+ lostdcc(i);
+ return;
+ }
+
+ changeover_dcc(i, &DCC_FORK_SEND, sizeof(struct xfer_info));
if (param[0] == '.')
param[0] = '_';
strncpy(dcc[i].u.xfer->filename, param, 120);
dcc[i].u.xfer->filename[120] = 0;
if (upload_to_cd) {
- char *p = get_user(&USERENTRY_DCCDIR, u);
+ char *p = get_user(&USERENTRY_DCCDIR, dcc[i].user);
if (p)
sprintf(dcc[i].u.xfer->dir, "%s%s/", dccdir, p);
@@ -633,13 +673,13 @@
sprintf(dcc[i].u.xfer->dir, "%s", dccdir);
} else
strcpy(dcc[i].u.xfer->dir, dccin);
- dcc[i].u.xfer->length = atoi(msg);
+ dcc[i].u.xfer->length = len;
sprintf(s1, "%s%s", dcc[i].u.xfer->dir, param);
context;
f = fopen(s1, "r");
if (f) {
fclose(f);
- dprintf(DP_HELP, "NOTICE %s :That file already exists.\n", nick);
+ dprintf(DP_HELP, "NOTICE %s :That file already exists.\n", dcc[i].nick);
lostdcc(i);
} else {
/* check for dcc-sends in process with the same filename */
@@ -648,8 +688,8 @@
if ((dcc[j].type->flags & (DCT_FILETRAN | DCT_FILESEND))
== (DCT_FILETRAN | DCT_FILESEND)) {
if (!strcmp(param, dcc[j].u.xfer->filename)) {
- dprintf(DP_HELP,
- "NOTICE %s :That file is already being sent.\n", nick);
+ dprintf(DP_HELP, "NOTICE %s :That file is already being sent.\n",
+ dcc[i].nick);
lostdcc(i);
return;
}
@@ -661,15 +701,17 @@
if (dcc[i].u.xfer->f == NULL) {
dprintf(DP_HELP,
"NOTICE %s :Can't create that file (temp dir error)\n",
- nick);
+ dcc[i].nick);
lostdcc(i);
} else {
+ char prt[100], ip[100];
+
dcc[i].timeval = now;
dcc[i].sock = getsock(SOCK_BINARY);
+ sprintf(prt, "%d", dcc[i].port);
+ sprintf(ip, "%lu", iptolong(my_ntohl(dcc[i].addr)));
if (open_telnet_dcc(dcc[i].sock, ip, prt) < 0) {
dcc[i].type->eof(i);
- }
- }
}
}
}
diff -urN eggdrop1.4~/src/mod/module.h eggdrop1.4/src/mod/module.h
--- eggdrop1.4~/src/mod/module.h Sat Oct 9 18:33:43 1999
+++ eggdrop1.4/src/mod/module.h Sat Oct 9 18:44:03 1999
@@ -322,6 +322,17 @@
/* 232 - 235 */
#define contextnote(note) (global[232](MODULE_NAME, __FILE__, __LINE__, note))
#define assert_failed (global[233])
+#define allocsock ((int(*)(int sock,int options))global[234])
+#define call_hostbyip ((void(*)(IP, char *, int))global[235])
+/* 236 - 239 */
+#define call_ipbyhost ((void(*)(char *, IP, int))global[236])
+#define iptostr ((char *(*)(IP))global[237])
+#define DCC_DNSWAIT (*(struct dcc_table *)(global[238]))
+#define hostsanitycheck_dcc ((int(*)(char *, char *, IP, char *, char *))global[239])
+/* 240 - 243 */
+#define dns_ipbyhost ((void (*)(char *))(*(Function**)(global[240])))
+#define dns_hostbyip ((void (*)(IP))(*(Function**)(global[241])))
+#define changeover_dcc ((void (*)(int, struct dcc_table *, int))global[242])
#define ASSERT(expr) { if (!(expr)) assert_failed (MODULE_NAME, __FILE__, __LINE__); }
diff -urN eggdrop1.4~/src/mod/modvals.h eggdrop1.4/src/mod/modvals.h
--- eggdrop1.4~/src/mod/modvals.h Sat Oct 9 18:33:43 1999
+++ eggdrop1.4/src/mod/modvals.h Sat Oct 9 18:46:38 1999
@@ -1,25 +1,27 @@
/* these *were* something, but changed */
-#define HOOK_GET_FLAGREC 0
-#define HOOK_BUILD_FLAGREC 1
-#define HOOK_SET_FLAGREC 2
-#define HOOK_READ_USERFILE 3
-#define HOOK_REHASH 4
-#define HOOK_MINUTELY 5
-#define HOOK_DAILY 6
-#define HOOK_HOURLY 7
-#define HOOK_USERFILE 8
-#define HOOK_SECONDLY 9
-#define HOOK_PRE_REHASH 10
-#define HOOK_IDLE 11
-#define HOOK_5MINUTELY 12
-#define REAL_HOOKS 13
-#define HOOK_SHAREOUT 105
-#define HOOK_SHAREIN 106
-#define HOOK_ENCRYPT_PASS 107
-#define HOOK_QSERV 108
-#define HOOK_ADD_MODE 109
-#define HOOK_MATCH_NOTEREJ 110
-#define HOOK_RFC_CASECMP 111
+#define HOOK_GET_FLAGREC 0
+#define HOOK_BUILD_FLAGREC 1
+#define HOOK_SET_FLAGREC 2
+#define HOOK_READ_USERFILE 3
+#define HOOK_REHASH 4
+#define HOOK_MINUTELY 5
+#define HOOK_DAILY 6
+#define HOOK_HOURLY 7
+#define HOOK_USERFILE 8
+#define HOOK_SECONDLY 9
+#define HOOK_PRE_REHASH 10
+#define HOOK_IDLE 11
+#define HOOK_5MINUTELY 12
+#define REAL_HOOKS 13
+#define HOOK_SHAREOUT 105
+#define HOOK_SHAREIN 106
+#define HOOK_ENCRYPT_PASS 107
+#define HOOK_QSERV 108
+#define HOOK_ADD_MODE 109
+#define HOOK_MATCH_NOTEREJ 110
+#define HOOK_RFC_CASECMP 111
+#define HOOK_DNS_HOSTBYIP 112
+#define HOOK_DNS_IPBYHOST 113
/* these are FIXED once they are in a release they STAY
* well, unless im feeling grumpy ;) */
diff -urN eggdrop1.4~/src/mod/server.mod/server.c eggdrop1.4/src/mod/server.mod/server.c
--- eggdrop1.4~/src/mod/server.mod/server.c Sat Oct 9 18:33:49 1999
+++ eggdrop1.4/src/mod/server.mod/server.c Sat Oct 9 18:40:22 1999
@@ -62,6 +62,7 @@
static int must_be_owner; /* arthur2 */
static char connectserver[121]; /* what, if anything, to do before connect
* to the server */
+static int resolvserv = 0; /* in the process of resolving a server host */
/* allow a msgs being twice in a queue ? */
static int double_mode;
@@ -697,16 +698,17 @@
Tcl_UntraceVar(interp,name,TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, \
tcl_eggserver,(ClientData)ptr)
+static void dcc_chat_failure(int);
+static void dcc_chat_success(int);
/* this only handles CHAT requests, otherwise it's handled in filesys */
static int ctcp_DCC_CHAT(char *nick, char *from, char *handle,
char *object, char *keyword, char *text)
{
char *action, *param, *ip, *prt, buf[512], *msg = buf;
- int i, sock;
+ int i;
struct userrec *u = get_user_by_handle(userlist, handle);
- struct flag_record fr =
- {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
+ struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
strcpy(msg, text);
action = newsplit(&msg);
@@ -741,36 +743,74 @@
} else {
if (!sanitycheck_dcc(nick, from, ip, prt))
return 1;
- sock = getsock(0);
- if (open_telnet_dcc(sock, ip, prt) < 0) {
+ i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
+
+ if (i < 0) {
+ putlog(LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", dcc[i].nick, ip);
+ return 1;
+ }
+ dcc[i].addr = my_atoul(ip);
+ dcc[i].port = atoi(prt);
+ dcc[i].sock = -1;
+ strcpy(dcc[i].nick, u->handle);
+ strcpy(dcc[i].host, from);
+ dcc[i].timeval = now;
+ dcc[i].user = u;
+ dcc[i].u.dns->ip = dcc[i].addr;
+ dcc[i].u.dns->dns_type = RES_HOSTBYIP;
+ dcc[i].u.dns->dns_success = (Function) dcc_chat_success;
+ dcc[i].u.dns->dns_failure = (Function) dcc_chat_failure;
+
+ dns_hostbyip(dcc[i].addr);
+ }
+ return 1;
+}
+
+static void dcc_chat_failure(int i)
+{
+ putlog(LOG_DEBUG, "*", "Reverse lookup failed %s",
+ iptostr(my_htonl(dcc[i].addr)));
+ lostdcc(i);
+}
+
+static void dcc_chat_success(int i)
+{
+ char buf[512], ip[512];
+ struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
+
+ sprintf(buf, "%d", dcc[i].port);
+ if (!hostsanitycheck_dcc(dcc[i].nick, dcc[i].host, dcc[i].addr,
+ dcc[i].u.dns->host, buf)) {
+ lostdcc(i);
+ return;
+ }
+
+ dcc[i].sock = getsock(0);
+ sprintf(ip, "%lu", iptolong(my_ntohl(dcc[i].addr)));
+ if (open_telnet_dcc(dcc[i].sock, ip, buf) < 0) {
neterror(buf);
if(!quiet_reject)
- dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", nick,
+ dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", dcc[i].nick,
DCC_CONNECTFAILED1, buf);
putlog(LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED2,
- nick, from);
+ dcc[i].nick, dcc[i].host);
putlog(LOG_MISC, "*", " (%s)", buf);
- killsock(sock);
+ killsock(dcc[i].sock);
+ lostdcc(i);
} else {
- i = new_dcc(&DCC_CHAT_PASS, sizeof(struct chat_info));
-
- dcc[i].addr = my_atoul(ip);
- dcc[i].port = atoi(prt);
- dcc[i].sock = sock;
- strcpy(dcc[i].nick, u->handle);
- strcpy(dcc[i].host, from);
+ changeover_dcc(i, &DCC_CHAT_PASS, sizeof(struct chat_info));
dcc[i].status = STAT_ECHO;
+ get_user_flagrec(dcc[i].user, &fr, 0);
if (glob_party(fr))
dcc[i].status |= STAT_PARTY;
strcpy(dcc[i].u.chat->con_chan, chanset ? chanset->name : "*");
dcc[i].timeval = now;
- dcc[i].user = u;
/* ok, we're satisfied with them now: attempt the connect */
- putlog(LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", nick, from);
+ putlog(LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", dcc[i].nick,
+ dcc[i].host);
dprintf(i, "%s\n", DCC_ENTERPASS);
}
- }
- return 1;
+ return;
}
static void server_secondly()
@@ -778,7 +818,7 @@
if (cycle_time)
cycle_time--;
deq_msg();
- if (serv < 0)
+ if (!resolvserv && serv < 0)
connect_server();
}
diff -urN eggdrop1.4~/src/mod/server.mod/servmsg.c eggdrop1.4/src/mod/server.mod/servmsg.c
--- eggdrop1.4~/src/mod/server.mod/servmsg.c Sat Oct 9 18:33:49 1999
+++ eggdrop1.4/src/mod/server.mod/servmsg.c Sat Oct 9 18:40:22 1999
@@ -1040,13 +1040,16 @@
{0, 0, 0, 0}
};
+static void server_resolve_success(int);
+static void server_resolve_failure(int);
+
/* hook up to a server */
/* works a little differently now... async i/o is your friend */
static void connect_server(void)
{
- char s[121], pass[121], botserver[UHOSTLEN + 1];
+ char pass[121], botserver[UHOSTLEN + 1];
static int oldserv = -1;
- int servidx, botserverport;
+ int servidx, botserverport = 0;
waiting_for_awake = 0;
trying_server = now;
@@ -1063,29 +1066,67 @@
newserverport = 0;
newserverpass[0] = 0;
oldserv = (-1);
- }
+ } else
+ pass[0] = 0;
if (!cycle_time) {
if (connectserver[0]) /* drummer */
do_tcl("connect-server", connectserver);
next_server(&curserv, botserver, &botserverport, pass);
putlog(LOG_SERV, "*", "%s %s:%d", IRC_SERVERTRY, botserver, botserverport);
- serv = open_telnet(botserver, botserverport);
+
+ servidx = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
+ dcc[servidx].port = botserverport;
+ strcpy(dcc[servidx].nick, "(server)");
+ strncpy(dcc[servidx].host, botserver, UHOSTLEN);
+ dcc[servidx].host[UHOSTLEN] = 0;
+ dcc[servidx].timeval = now;
+ dcc[servidx].u.dns->host = get_data_ptr(strlen(dcc[servidx].host) + 1);
+ strcpy(dcc[servidx].u.dns->host, dcc[servidx].host);
+ dcc[servidx].u.dns->cbuf = get_data_ptr(strlen(pass) + 1);
+ strcpy(dcc[servidx].u.dns->cbuf, pass);
+ dcc[servidx].u.dns->dns_success = (Function) server_resolve_success;
+ dcc[servidx].u.dns->dns_failure = (Function) server_resolve_failure;
+ dcc[servidx].u.dns->dns_type = RES_IPBYHOST;
+
+ resolvserv = 1;
+ dns_ipbyhost(dcc[servidx].host);
+ if (server_cycle_wait)
+ /* back to 1st server & set wait time */
+ /* put it here, just in case the server quits on us quickly */
+ cycle_time = server_cycle_wait;
+ }
+}
+
+static void server_resolve_failure(int servidx)
+{
+ serv = -1;
+ resolvserv = 0;
+ putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, dcc[servidx].host,
+ IRC_DNSFAILED);
+ lostdcc(servidx);
+}
+
+static void server_resolve_success(int servidx)
+{
+ int oldserv = dcc[servidx].u.dns->ibuf;
+ char s[121], pass[121];
+
+ resolvserv = 0;
+ dcc[servidx].addr = dcc[servidx].u.dns->ip;
+ strcpy(pass, dcc[servidx].u.dns->cbuf);
+ changeover_dcc(servidx, &SERVER_SOCKET, 0);
+ serv = open_telnet(iptostr(my_ntohl(dcc[servidx].addr)),
+ dcc[servidx].port);
if (serv < 0) {
- if (serv == (-2))
- strcpy(s, IRC_DNSFAILED);
- else
neterror(s);
- putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, botserver, s);
+ putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, dcc[servidx].host,
+ s);
+ lostdcc(servidx);
if ((oldserv == curserv) && !(never_give_up))
fatal("NO SERVERS WILL ACCEPT MY CONNECTION.", 0);
} else {
- /* queue standard login */
- servidx = new_dcc(&SERVER_SOCKET, 0);
dcc[servidx].sock = serv;
- dcc[servidx].port = botserverport;
- strcpy(dcc[servidx].nick, "(server)");
- strncpy(dcc[servidx].host, botserver, UHOSTLEN);
- dcc[servidx].host[UHOSTLEN] = 0;
+ /* queue standard login */
dcc[servidx].timeval = now;
SERVER_SOCKET.timeout_val = &server_timeout;
strcpy(botname, origbotname);
@@ -1094,14 +1135,9 @@
if (pass[0])
dprintf(DP_MODE, "PASS %s\n", pass);
dprintf(DP_MODE, "USER %s %s %s :%s\n",
- botuser, bothost, botserver, botrealname);
+ botuser, bothost, dcc[servidx].host, botrealname);
cycle_time = 0;
/* We join channels AFTER getting the 001 -Wild */
/* wait for async result now */
- }
- if (server_cycle_wait)
- /* back to 1st server & set wait time */
- /* put it here, just in case the server quits on us quickly */
- cycle_time = server_cycle_wait;
}
}
diff -urN eggdrop1.4~/src/modules.c eggdrop1.4/src/modules.c
--- eggdrop1.4~/src/modules.c Sat Oct 9 18:33:52 1999
+++ eggdrop1.4/src/modules.c Sat Oct 9 18:48:15 1999
@@ -128,7 +128,6 @@
dprintf(idx, "s un Not sharing userfile.\n");
}
-/* these are obscure ones that I hope to neaten eventually :/ */
void (*encrypt_pass) (char *, char *) = 0;
void (*shareout) () = null_func;
void (*sharein) (int, char *) = null_share;
@@ -139,6 +138,8 @@
int (*rfc_ncasecmp) (const char *, const char *, int) = _rfc_ncasecmp;
int (*rfc_toupper) (int) = _rfc_toupper;
int (*rfc_tolower) (int) = _rfc_tolower;
+void (*dns_hostbyip) (IP) = block_dns_hostbyip;
+void (*dns_ipbyhost) (char *) = block_dns_ipbyhost;
module_entry *module_list;
dependancy *dependancy_list = NULL;
@@ -467,6 +468,17 @@
/* 232 - 235 */
(Function) mod_contextnote,
(Function) assert_failed,
+ (Function) allocsock,
+ (Function) call_hostbyip,
+ /* 236 - 239 */
+ (Function) call_ipbyhost,
+ (Function) iptostr,
+ (Function) & DCC_DNSWAIT, /* struct dcc_table * */
+ (Function) hostsanitycheck_dcc,
+ /* 240 - 243 */
+ (Function) & dns_ipbyhost, /* Function * */
+ (Function) & dns_hostbyip, /* Function * */
+ (Function) changeover_dcc,
};
void init_modules(void)
@@ -899,6 +911,14 @@
if (match_noterej == false_func)
match_noterej = func;
break;
+ case HOOK_DNS_HOSTBYIP:
+ if (dns_hostbyip == block_dns_hostbyip)
+ dns_hostbyip = func;
+ break;
+ case HOOK_DNS_IPBYHOST:
+ if (dns_ipbyhost == block_dns_ipbyhost)
+ dns_ipbyhost = func;
+ break;
}
}
@@ -945,6 +965,14 @@
case HOOK_MATCH_NOTEREJ:
if (match_noterej == func)
match_noterej = false_func;
+ break;
+ case HOOK_DNS_HOSTBYIP:
+ if (dns_hostbyip == func)
+ dns_hostbyip = block_dns_hostbyip;
+ break;
+ case HOOK_DNS_IPBYHOST:
+ if (dns_ipbyhost == func)
+ dns_ipbyhost = block_dns_ipbyhost;
break;
}
}
diff -urN eggdrop1.4~/src/net.c eggdrop1.4/src/net.c
--- eggdrop1.4~/src/net.c Sat Oct 9 18:33:52 1999
+++ eggdrop1.4/src/net.c Sat Oct 9 18:40:22 1999
@@ -65,11 +65,6 @@
return ret;
}
-#define my_ntohs(sh) swap_short(sh)
-#define my_htons(sh) swap_short(sh)
-#define my_ntohl(ln) swap_long(ln)
-#define my_htonl(ln) swap_long(ln)
-
/* i read somewhere that memcpy() is broken on some machines */
/* it's easy to replace, so i'm not gonna take any chances, because
* it's pretty important that it work correctly here */
@@ -214,12 +209,12 @@
}
}
-/* request a normal socket for i/o */
-void setsock(int sock, int options)
+/* return a free entry in the socket entry */
+int allocsock(int sock, int options)
{
int i;
- int parm;
+ context;
for (i = 0; i < MAXSOCKS; i++) {
if (socklist[i].flags & SOCK_UNUSED) {
/* yay! there is table space */
@@ -227,11 +222,23 @@
socklist[i].outbuflen = 0;
socklist[i].flags = options;
socklist[i].sock = sock;
+ return i;
+ }
+ }
+ fatal("Socket table is full!", 0);
+ return -1; /* never reached */
+}
+
+/* request a normal socket for i/o */
+void setsock(int sock, int options)
+{
+ int i = allocsock(sock, options);
+ int parm;
+
if (((sock != STDOUT) || backgrd) &&
!(socklist[i].flags & SOCK_NONSOCK)) {
parm = 1;
- setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &parm,
- sizeof(int));
+ setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &parm, sizeof(int));
parm = 0;
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &parm, sizeof(int));
@@ -244,10 +251,6 @@
}
/* yay async i/o ! */
fcntl(sock, F_SETFL, O_NONBLOCK);
- return;
- }
- }
- fatal("Socket table is full!", 0);
}
int getsock(int options)
@@ -328,6 +331,11 @@
}
/* starts a connection attempt to a socket
+ *
+ * If given a normal hostname, this will be resolved to the corresponding
+ * IP address first. PLEASE try to use the non-blocking dns functions
+ * instead and then call this function with the IP address to avoid blocking.
+ *
* returns <0 if connection refused:
* -1 neterror() type error
* -2 can't resolve hostname */
@@ -372,6 +380,7 @@
name.sin_addr.s_addr = inet_addr(host);
else {
/* no, must be host.domain */
+ debug0("Warning: open_telnet_raw() is about to block in gethostbyname()!");
if (!setjmp(alarmret)) {
alarm(resolve_timeout);
hp = gethostbyname(host);
@@ -450,14 +459,17 @@
return sock;
}
-/* given network-style IP address, return hostname */
-/* hostname will be "##.##.##.##" format if there was an error */
+/* Given a network-style IP address, returns the hostname. The hostname
+ * will be in the "##.##.##.##" format if there was an error.
+ *
+ * NOTE: This function is depreciated. Try using the async dns approach
+ * instead. */
char *hostnamefromip(unsigned long ip)
{
struct hostent *hp;
unsigned long addr = ip;
unsigned char *p;
- static char s[121];
+ static char s[UHOSTLEN];
if (!setjmp(alarmret)) {
alarm(resolve_timeout);
@@ -471,11 +483,21 @@
sprintf(s, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
return s;
}
- strncpy(s, hp->h_name, 120);
- s[120] = 0;
+ strncpy(s, hp->h_name, UHOSTLEN - 1);
+ s[UHOSTLEN - 1] = 0;
return s;
}
+/* returns a given network-style IP address as a string in the
+ * "##.##.##.##" format */
+char *iptostr(IP ip)
+{
+ struct in_addr a;
+
+ a.s_addr = ip;
+ return inet_ntoa(a);
+}
+
/* short routine to answer a connect received on a socket made previously
* by open_listen ... returns hostname of the caller & the new socket
* does NOT dispose of old "public" socket! */
@@ -484,14 +506,18 @@
{
int new_sock, addrlen;
struct sockaddr_in from;
- addrlen = sizeof(struct sockaddr);
+ addrlen = sizeof(struct sockaddr);
new_sock = accept(sock, (struct sockaddr *) &from, &addrlen);
if (new_sock < 0)
return -1;
if (ip != NULL) {
*ip = from.sin_addr.s_addr;
- strncpy(caller, hostnamefromip(*ip), 120);
+ /* This is now done asynchronously. Instead, we just provide the
+ * IP address.
+ * strncpy(caller, hostnamefromip(*ip), 120);
+ */
+ strncpy(caller, iptostr(*ip), 120);
caller[120] = 0;
*ip = my_ntohl(*ip);
}
@@ -589,6 +615,10 @@
*len = 0;
return i;
}
+ } else if (socklist[i].flags & SOCK_PASS) {
+ s[0] = 0;
+ *len = 0;
+ return i;
}
if ((socklist[i].sock == STDOUT) && !backgrd)
x = read(STDIN, s, grab);
@@ -711,6 +741,7 @@
return ret;
}
/* binary and listening sockets don't get buffered */
+ /* passed on sockets don't get buffered either (Fabian)*/
if (socklist[ret].flags & SOCK_CONNECT) {
if (socklist[ret].flags & SOCK_STRONGCONN) {
socklist[ret].flags &= ~SOCK_STRONGCONN;
@@ -726,7 +757,8 @@
my_memcpy(s, xx, *len);
return socklist[ret].sock;
}
- if (socklist[ret].flags & SOCK_LISTEN)
+ if ((socklist[ret].flags & SOCK_LISTEN) ||
+ (socklist[ret].flags & SOCK_PASS))
return socklist[ret].sock;
context;
/* might be necessary to prepend stored-up data! */
@@ -905,6 +937,8 @@
strcat(s, " (binary)");
if (socklist[i].flags & SOCK_LISTEN)
strcat(s, " (listen)");
+ if (socklist[i].flags & SOCK_PASS)
+ strcat(s, " (passed on)");
if (socklist[i].flags & SOCK_CONNECT)
strcat(s, " (connecting)");
if (socklist[i].flags & SOCK_STRONGCONN)
@@ -933,7 +967,7 @@
{
/* According to the latest RFC, the clients SHOULD be able to handle
* DNS names that are up to 255 characters long. This is not broken. */
- char hostname[256], dnsname[256], badaddress[16];
+ char badaddress[16];
IP ip = my_atoul(ipaddy);
int prt = atoi(port);
@@ -942,23 +976,39 @@
return 1;
context; /* This should be pretty solid, but
* something _might_ break. */
- sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
- (ip >> 8) & 0xff, ip & 0xff);
if (prt < 1) {
putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible port of %u!",
nick, from, prt);
return 0;
}
+ sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
+ (ip >> 8) & 0xff, ip & 0xff);
if (ip < (1 << 24)) {
putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!",
nick, from, badaddress);
return 0;
}
+ return 1;
+}
+
+int hostsanitycheck_dcc(char *nick, char *from, IP ip, char *dnsname,
+ char *prt)
+{
+ /* According to the latest RFC, the clients SHOULD be able to handle
+ * DNS names that are up to 255 characters long. This is not broken. */
+ char hostname[256], badaddress[16];
+
+ /* It is disabled HERE so we only have to check in *one* spot! */
+ if (!dcc_sanitycheck)
+ return 1;
+ context; /* This should be pretty solid, but
+ * something _might_ break. */
+ sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
+ (ip >> 8) & 0xff, ip & 0xff);
/* These should pad like crazy with zeros, since 120 bytes or so is
* where the routines providing our data currently lose interest. I'm
* using the n-variant in case someone changes that... */
strncpy(hostname, extracthostname(from), 256);
- strncpy(dnsname, hostnamefromip(my_htonl(ip)), 256);
if (!strcasecmp(hostname, dnsname)) {
putlog(LOG_DEBUG, "*", "DNS information for submitted IP checks out.");
return 1;
diff -urN eggdrop1.4~/src/proto.h eggdrop1.4/src/proto.h
--- eggdrop1.4~/src/proto.h Sat Oct 9 18:33:52 1999
+++ eggdrop1.4/src/proto.h Sat Oct 9 18:40:22 1999
@@ -128,13 +128,21 @@
void not_away(int);
void set_away(int, char *);
void *_get_data_ptr(int, char *, int);
-
#define get_data_ptr(x) _get_data_ptr(x,__FILE__,__LINE__)
void flush_lines(int, struct chat_info *);
struct dcc_t *find_idx(int);
int new_dcc(struct dcc_table *, int);
void del_dcc(int);
char *add_cr(char *);
+void changeover_dcc(int, struct dcc_table *, int);
+
+/* dns.c */
+extern void (*dns_hostbyip) (IP);
+extern void (*dns_ipbyhost) (char *);
+void block_dns_hostbyip(IP);
+void block_dns_ipbyhost(char *);
+void call_hostbyip(IP, char *, int);
+void call_ipbyhost(char *, IP, int);
/* gotdcc.c */
void gotdcc(char *, char *, struct userrec *, char *);
@@ -205,7 +213,9 @@
IP getmyip();
void neterror(char *);
void setsock(int, int);
+int allocsock(int, int);
int getsock(int);
+char *hostnamefromip(unsigned long);
void killsock(int);
int answer(int, char *, unsigned long *, unsigned short *, int);
int open_listen(int *);
@@ -217,6 +227,8 @@
int sockgets(char *, int *);
void tell_netdebug(int);
int sanitycheck_dcc(char *, char *, char *, char *);
+int hostsanitycheck_dcc(char *, char *, IP, char *, char *);
+char *iptostr(IP);
/* tcl.c */
void protect_tcl();
diff -urN eggdrop1.4~/doc/UPDATES1.4 eggdrop1.4/doc/UPDATES1.4
--- eggdrop1.4~/doc/UPDATES1.4 Sat Oct 9 18:33:36 1999
+++ eggdrop1.4/doc/UPDATES1.4 Sat Oct 9 19:21:55 1999
@@ -5,4 +5,5 @@
1.4.0
Foundby Fixedby What....
-
+ Fabian added an asynchronous DNS request module which prevents
+ the bot from hanging on dns lookups.
More information about the Patches
mailing list