[cvslog] [CVS] Module eggdrop1.8: Change committed

cvs at eggheads.org cvs at eggheads.org
Thu Aug 5 12:12:15 CST 2010


CVSROOT    : /usr/local/cvsroot
Module     : eggdrop1.8
Commit time: 2010-08-05 18:12:15 UTC
Committer  : Rumen Stoyanov <pseudo at egg6.net>

Modified files:
     README aclocal.m4 config.h.in configure configure.ac eggdrop.conf
     doc/CONTENTS doc/Changes1.8 doc/html/egg-core.html
     doc/html/faqs.html doc/settings/core.settings help/cmds1.help
     help/core.help help/set/cmds1.help src/botnet.c src/cmds.c
     src/dcc.c src/dccutil.c src/dns.c src/dns.h src/eggdrop.h
     src/main.c src/main.h src/modules.c src/net.c src/patch.h
     src/proto.h src/tcl.c src/tcldcc.c src/tclmisc.c src/tcluser.c
     src/userent.c src/users.c src/compat/Makefile.in
     src/compat/compat.h src/mod/module.h
     src/mod/channels.mod/cmdschan.c src/mod/channels.mod/userchan.c
     src/mod/ctcp.mod/ctcp.c src/mod/dns.mod/coredns.c
     src/mod/dns.mod/dns.c src/mod/dns.mod/dns.h
     src/mod/filesys.mod/filedb3.c src/mod/filesys.mod/filesys.c
     src/mod/server.mod/server.c src/mod/server.mod/servmsg.c
     src/mod/share.mod/share.c src/mod/transfer.mod/transfer.c

Added files:
     doc/IPV6 src/compat/gethostbyname2.c src/compat/gethostbyname2.h
     src/compat/in6.c src/compat/in6.h src/compat/inet_ntop.c
     src/compat/inet_ntop.h src/compat/inet_pton.c
     src/compat/inet_pton.h

Log message:

Added new, full IPv6 support to eggdrop.

---------------------- diff included ----------------------
Index: eggdrop1.8/README
diff -u eggdrop1.8/README:1.2 eggdrop1.8/README:1.3
--- eggdrop1.8/README:1.2	Tue Jul 27 15:49:41 2010
+++ eggdrop1.8/README	Thu Aug  5 12:12:04 2010
@@ -1,4 +1,4 @@
-$Id: README,v 1.2 2010/07/27 21:49:41 pseudo Exp $
+$Id: README,v 1.3 2010/08/05 18:12:04 pseudo Exp $
 
 Readme
 Last revised: June 5, 2002
@@ -23,25 +23,24 @@
     5. Command line
     6. Frequently Asked Questions
        6a. What do I do if I get the error "User file not found"?
-       6b. My Eggdrop won't run; It just says "Can't find your hostname!"
-       6c. What the Heck is Tcl?
-       6d. My bot dies and the last entry in the logfile is "Received terminate
+       6b. What the Heck is Tcl?
+       6c. My bot dies and the last entry in the logfile is "Received terminate
            signal". What does that mean and can I prevent it?
-       6e. Someone else set up a bot I don't like. Are there any backdoors I
+       6d. Someone else set up a bot I don't like. Are there any backdoors I
            can use to take their bot down?
-       6f. What are modules?
-       6g. Can I compile Eggdrop without dynamic modules?
+       6e. What are modules?
+       6f. Can I compile Eggdrop without dynamic modules?
            6g1. Do I still need to "loadmodule" modules?
-       6h. Where can I get a pre-compiled Eggdrop for my computer?
-       6i. I get "Makefile:3 : invalid operator" or some such thing when I
+       6g. Where can I get a pre-compiled Eggdrop for my computer?
+       6h. I get "Makefile:3 : invalid operator" or some such thing when I
            try to "make".
-       6j. When I "tclsh scripts/weed <userfile> c" It barfs chunks at me
+       6i. When I "tclsh scripts/weed <userfile> c" It barfs chunks at me
            and dies.
-       6k. I get "ld-elf.so.1: Shared object "libtcl80.so.1" not found" or
+       6j. I get "ld-elf.so.1: Shared object "libtcl80.so.1" not found" or
            "eggdrop: error in loading shared libraries / libtcl8.1.so: cannot
            open shared object file: No such file or directory" when I try to
            start my bot.
-       6l. I get a whole pile of "unresolved symbol 'Tcl_AppendResult'" (or
+       6k. I get a whole pile of "unresolved symbol 'Tcl_AppendResult'" (or
            some other symbol) when I try to load a module.
     7. Setting up a crontab
        7a. Setting up a crontab using autobotchk
@@ -273,13 +272,7 @@
          (nobody else will become an owner if they say "hello"), but in the
          future, don't use the "-m" option when running the bot.
 
-    6b. MY EGGDROP WON'T RUN; IT JUST SAYS "CAN'T FIND YOUR HOSTNAME!"
-
-      Your machine is set up strangely, and Eggdrop can't figure out its
-      network hostname. You can get around this by setting the my-ip setting
-      in the config file correctly.
-
-    6c. WHAT THE HECK IS Tcl?
+    6b. WHAT THE HECK IS Tcl?
 
       Tcl is a scripting language written by John Ousterhout. It's much better
       than most "built-in" script languages (like the one in ircII) and is
@@ -291,7 +284,7 @@
       around on the ftp/web sites if you like working by example (which is
       typically the best way).
 
-    6d. MY BOT DIES, AND THE LAST ENTRY IN THE LOGFILE IS "RECEIVED TERMINATE
+    6c. MY BOT DIES, AND THE LAST ENTRY IN THE LOGFILE IS "RECEIVED TERMINATE
         SIGNAL". WHAT DOES THAT MEAN, AND CAN I PREVENT IT?
 
       There's nothing you can do to prevent it. It means the system
@@ -302,7 +295,7 @@
       kill the bot manually. For example, if he/she doesn't want bots running
       on the system.
 
-    6e. SOMEONE ELSE SET UP A BOT I DON'T LIKE. ARE THERE ANY BACKDOORS I CAN
+    6d. SOMEONE ELSE SET UP A BOT I DON'T LIKE. ARE THERE ANY BACKDOORS I CAN
         USE TO TAKE THEIR BOT DOWN?
 
       No, there have never been any backdoors and there never will be, so
@@ -311,13 +304,13 @@
       about them. If you want to bring down someone else's bot, you will not
       have my/our help.
 
-    6f. WHAT ARE MODULES?
+    6e. WHAT ARE MODULES?
 
       Modules are a way of adding extra features to the bot, much like Tcl
       scripts, without requiring the bot to be recompiled. See doc/MODULES
       for more information.
 
-    6g. CAN I COMPILE EGGDROP WITHOUT DYNAMIC MODULES?
+    6f. CAN I COMPILE EGGDROP WITHOUT DYNAMIC MODULES?
 
        Yes, you can. If the configure script detects that your system CAN'T
        run modules, it will setup 'make' to link the modules in statically
@@ -325,14 +318,14 @@
        You can also try to compile dynamic modules on a static-only system
        by using 'make eggdrop'.
 
-    6g1. DO I STILL NEED TO 'loadmodule' MODULES?
+    6f1. DO I STILL NEED TO 'loadmodule' MODULES?
 
       YES, when you compile statically, all the modules are linked into the
       main executable. HOWEVER, they are not enabled until you use loadmodule
       to enable them, hence you get nearly the same functionality with static
       modules as with dynamic modules.
 
-    6h. WHERE CAN I GET A PRE-COMPILED EGGDROP FOR MY COMPUTER?
+    6g. WHERE CAN I GET A PRE-COMPILED EGGDROP FOR MY COMPUTER?
 
       It is HIGHLY recommended AGAINST using pre-compiled Eggdrops from
       un-trusted sources. Eggdrop has been a regular target for hacking and
@@ -342,12 +335,12 @@
       computer account directly. Don't advertise your pre-compiled Eggdrop
       binary sites on the Eggdrop list either. =P
 
-    6i. I GET 'Makefile:3 :invalid operator' OR SOME-SUCH-THING WHEN I TRY
+    6h. I GET 'Makefile:3 :invalid operator' OR SOME-SUCH-THING WHEN I TRY
         TO 'make'.
 
       Try 'gmake'.
 
-    6j. WHEN I 'tclsh scripts/weed <userfile> c' IT BARFS CHUNKS AT ME AND
+    6i. WHEN I 'tclsh scripts/weed <userfile> c' IT BARFS CHUNKS AT ME AND
         DIES. :(
 
       Upgrade your Tcl. You are probably using Tcl 7.5 or earlier. Some of the
@@ -355,7 +348,7 @@
       the offending lines from you userfile manually (those starting with '.'
       generally) and accept the loss of that data.
 
-    6k. I GET "ld-elf.so.1: Shared object "libtcl80.so.1" not found" or
+    6j. I GET "ld-elf.so.1: Shared object "libtcl80.so.1" not found" or
         "eggdrop: error in loading shared libraries libtcl8.1.so: \
         cannot open shared object file: No such file or directory" WHEN I TRY
         TO START MY BOT.
@@ -390,10 +383,10 @@
         If everything else fails, try to install Tcl to your home dir ;)
         (Suggested by dw at Undernet, dw at lixom.nu)
 
-    6l. I GET A WHOLE PILE OF "Unresolved symbol 'Tcl_AppendResult'" (OR SOME
+    6k. I GET A WHOLE PILE OF "Unresolved symbol 'Tcl_AppendResult'" (OR SOME
         OTHER SYMBOL) WHEN I TRY TO LOAD A MODULES.
 
-      POSSIBILITY A: See section 6k.
+      POSSIBILITY A: See section 6j.
 
       POSSIBILITY B:
 
Index: eggdrop1.8/aclocal.m4
diff -u eggdrop1.8/aclocal.m4:1.2 eggdrop1.8/aclocal.m4:1.3
--- eggdrop1.8/aclocal.m4:1.2	Tue Jul 27 15:49:41 2010
+++ eggdrop1.8/aclocal.m4	Thu Aug  5 12:12:04 2010
@@ -16,7 +16,7 @@
 dnl along with this program; if not, write to the Free Software
 dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 dnl
-dnl $Id: aclocal.m4,v 1.2 2010/07/27 21:49:41 pseudo Exp $
+dnl $Id: aclocal.m4,v 1.3 2010/08/05 18:12:04 pseudo Exp $
 dnl
 
 
@@ -1795,3 +1795,90 @@
     ])
   ])
 ])
+
+
+dnl EGG_IPV6_COMPAT
+dnl
+AC_DEFUN([EGG_IPV6_COMPAT],
+[
+if test "$enable_ipv6" = "yes"; then
+  AC_CHECK_FUNCS([inet_pton gethostbyname2])
+  AC_CHECK_TYPES([struct in6_addr], egg_cv_var_have_in6_addr="yes",
+    egg_cv_var_have_in6_addr="no", [#include <netinet/in.h>])
+  if test "$egg_cv_var_have_in6_addr" = "yes"; then
+    # Check for in6addr_any
+    AC_CACHE_CHECK([for the in6addr_any constant], [egg_cv_var_have_in6addr_any], [
+      AC_TRY_COMPILE([#include <netinet/in.h>],
+        [struct in6_addr i6 = in6addr_any;],
+        egg_cv_var_have_in6addr_any="yes",
+        egg_cv_var_have_in6addr_any="no"
+      )
+    ])
+    if test "$egg_cv_var_have_in6addr_any" = "yes"; then
+      AC_DEFINE(HAVE_IN6ADDR_ANY, 1, [Define to 1 if you have the in6addr_any constant.])
+    fi
+    # Check for in6addr_loopback
+    AC_CACHE_CHECK([for the in6addr_loopback constant], [egg_cv_var_have_in6addr_loopback], [
+      AC_TRY_COMPILE([#include <netinet/in.h>],
+        [struct in6_addr i6 = in6addr_loopback;],
+        egg_cv_var_have_in6addr_loopback="yes",
+        egg_cv_var_have_in6addr_loopback="no"
+      )
+    ])
+    if test "$egg_cv_var_have_in6addr_loopback" = "yes"; then
+      AC_DEFINE(HAVE_IN6ADDR_LOOPBACK, 1, [Define to 1 if you have the in6addr_loopback constant.])
+    fi
+    AC_CHECK_TYPES([struct sockaddr_in6], , , [#include <netinet/in.h>])
+  else
+    AC_MSG_NOTICE([no in6_addr found, skipping dependent checks. Custom definitions will be used.])
+  fi
+fi
+])
+
+
+dnl EGG_IPV6_ENABLE
+dnl
+AC_DEFUN([EGG_IPV6_ENABLE],
+[
+  AC_ARG_ENABLE(ipv6,
+    [  --enable-ipv6           enable IPv6 support (autodetect)],
+    [enable_ipv6="$enableval"], [enable_ipv6="$egg_cv_var_ipv6_supported"])
+  AC_ARG_ENABLE(ipv6,
+    [  --disable-ipv6          disable IPv6 support ], [enable_ipv6="$enableval"])
+
+  if test "$enable_ipv6" = "yes"; then
+    if test "$egg_cv_var_ipv6_supported" = "no"; then
+      AC_MSG_WARN([You have enabled IPv6 but your system doesn't seem to support it.])
+      AC_MSG_WARN([Eggdrop will compile but will be limited to IPv4 on this host.])
+    fi
+    AC_DEFINE(IPV6, 1, [Define to 1 if you want to enable IPv6 support.])
+  fi
+])
+
+
+dnl EGG_IPV6_STATUS
+dnl
+AC_DEFUN([EGG_IPV6_STATUS],
+[
+  AC_CACHE_CHECK([for system IPv6 support], [egg_cv_var_ipv6_supported], [
+    AC_RUN_IFELSE([[
+      #include <unistd.h>
+      #include <sys/socket.h>
+      #include <netinet/in.h>
+  
+      int main()
+      {
+        int s = socket(AF_INET6, SOCK_STREAM, 0);
+
+        if (s != -1)
+          close(s);
+
+        return((s == -1));
+       }
+    ]], [
+      egg_cv_var_ipv6_supported="yes"
+     ], [
+      egg_cv_var_ipv6_supported="no"
+    ])
+  ])
+])
Index: eggdrop1.8/config.h.in
diff -u eggdrop1.8/config.h.in:1.1.1.1 eggdrop1.8/config.h.in:1.2
--- eggdrop1.8/config.h.in:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/config.h.in	Thu Aug  5 12:12:04 2010
@@ -90,15 +90,30 @@
 /* Define to 1 if you have the `getdtablesize' function. */
 #undef HAVE_GETDTABLESIZE
 
+/* Define to 1 if you have the `gethostbyname2' function. */
+#undef HAVE_GETHOSTBYNAME2
+
 /* Define to 1 if you have the `getpagesize' function. */
 #undef HAVE_GETPAGESIZE
 
 /* Define to 1 if you have the `getrusage' function. */
 #undef HAVE_GETRUSAGE
 
+/* Define to 1 if you have the in6addr_any constant. */
+#undef HAVE_IN6ADDR_ANY
+
+/* Define to 1 if you have the in6addr_loopback constant. */
+#undef HAVE_IN6ADDR_LOOPBACK
+
 /* Define to 1 if you have the `inet_aton' function. */
 #undef HAVE_INET_ATON
 
+/* Define to 1 if you have the `inet_ntop' function. */
+#undef HAVE_INET_NTOP
+
+/* Define to 1 if you have the `inet_pton' function. */
+#undef HAVE_INET_PTON
+
 /* Define to 1 if the system has the type `intptr_t'. */
 #undef HAVE_INTPTR_T
 
@@ -234,6 +249,12 @@
 /* Define to 1 if you have the `strncasecmp' function. */
 #undef HAVE_STRNCASECMP
 
+/* Define to 1 if the system has the type `struct in6_addr'. */
+#undef HAVE_STRUCT_IN6_ADDR
+
+/* Define to 1 if the system has the type `struct sockaddr_in6'. */
+#undef HAVE_STRUCT_SOCKADDR_IN6
+
 /* Define to 1 if `tm_zone' is a member of `struct tm'. */
 #undef HAVE_STRUCT_TM_TM_ZONE
 
@@ -304,6 +325,9 @@
 /* Define to 1 if you have the <wchar.h> header file. */
 #undef HAVE_WCHAR_H
 
+/* Define to 1 if you want to enable IPv6 support. */
+#undef IPV6
+
 /* Define if modules will work on your system. */
 #undef MODULES_OK
 
Index: eggdrop1.8/configure
diff -u eggdrop1.8/configure:1.3 eggdrop1.8/configure:1.4
--- eggdrop1.8/configure:1.3	Tue Jul 27 15:49:41 2010
+++ eggdrop1.8/configure	Thu Aug  5 12:12:04 2010
@@ -706,6 +706,7 @@
 enable_debug_dns
 enable_debug_context
 with_handlen
+enable_ipv6
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1347,6 +1348,8 @@
   --enable-debug-context  enable context debug code (default)
   --disable-debug-context disable context debug code
   --with-handlen=VALUE    set the maximum length a handle on the bot can be
+  --enable-ipv6           enable IPv6 support (autodetect)
+  --disable-ipv6          disable IPv6 support
 
 Some influential environment variables:
   CC          C compiler command
@@ -6513,7 +6516,7 @@
 
 
 # Checks for functions and their arguments.
-for ac_func in clock dprintf fsync getdtablesize getrusage inet_aton isascii mbrlen memcpy memset random rand lrand48 rename setpgid sigaction sigemptyset snprintf strcasecmp strncasecmp uname vsnprintf
+for ac_func in clock dprintf fsync getdtablesize getrusage inet_aton isascii mbrlen memcpy memset random rand lrand48 rename setpgid sigaction sigemptyset snprintf strcasecmp strncasecmp uname vsnprintf inet_ntop
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -7953,6 +7956,198 @@
 
 
 
+# Check for IPv6
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for system IPv6 support" >&5
+$as_echo_n "checking for system IPv6 support... " >&6; }
+if test "${egg_cv_var_ipv6_supported+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run test program while cross compiling
+See \`config.log' for more details." "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+      #include <unistd.h>
+      #include <sys/socket.h>
+      #include <netinet/in.h>
+
+      int main()
+      {
+        int s = socket(AF_INET6, SOCK_STREAM, 0);
+
+        if (s != -1)
+          close(s);
+
+        return((s == -1));
+       }
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+      egg_cv_var_ipv6_supported="yes"
+
+else
+
+      egg_cv_var_ipv6_supported="no"
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $egg_cv_var_ipv6_supported" >&5
+$as_echo "$egg_cv_var_ipv6_supported" >&6; }
+
+
+  # Check whether --enable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then :
+  enableval=$enable_ipv6; enable_ipv6="$enableval"
+else
+  enable_ipv6="$egg_cv_var_ipv6_supported"
+fi
+
+  # Check whether --enable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then :
+  enableval=$enable_ipv6; enable_ipv6="$enableval"
+fi
+
+
+  if test "$enable_ipv6" = "yes"; then
+    if test "$egg_cv_var_ipv6_supported" = "no"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You have enabled IPv6 but your system doesn't seem to support it." >&5
+$as_echo "$as_me: WARNING: You have enabled IPv6 but your system doesn't seem to support it." >&2;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Eggdrop will compile but will be limited to IPv4 on this host." >&5
+$as_echo "$as_me: WARNING: Eggdrop will compile but will be limited to IPv4 on this host." >&2;}
+    fi
+
+$as_echo "#define IPV6 1" >>confdefs.h
+
+  fi
+
+
+if test "$enable_ipv6" = "yes"; then
+  for ac_func in inet_pton gethostbyname2
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+   if test "x$as_val" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+  ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "#include <netinet/in.h>
+"
+if test "x$ac_cv_type_struct_in6_addr" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_IN6_ADDR 1
+_ACEOF
+
+egg_cv_var_have_in6_addr="yes"
+else
+  egg_cv_var_have_in6_addr="no"
+fi
+
+  if test "$egg_cv_var_have_in6_addr" = "yes"; then
+    # Check for in6addr_any
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the in6addr_any constant" >&5
+$as_echo_n "checking for the in6addr_any constant... " >&6; }
+if test "${egg_cv_var_have_in6addr_any+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netinet/in.h>
+int
+main ()
+{
+struct in6_addr i6 = in6addr_any;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  egg_cv_var_have_in6addr_any="yes"
+else
+  egg_cv_var_have_in6addr_any="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $egg_cv_var_have_in6addr_any" >&5
+$as_echo "$egg_cv_var_have_in6addr_any" >&6; }
+    if test "$egg_cv_var_have_in6addr_any" = "yes"; then
+
+$as_echo "#define HAVE_IN6ADDR_ANY 1" >>confdefs.h
+
+    fi
+    # Check for in6addr_loopback
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the in6addr_loopback constant" >&5
+$as_echo_n "checking for the in6addr_loopback constant... " >&6; }
+if test "${egg_cv_var_have_in6addr_loopback+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netinet/in.h>
+int
+main ()
+{
+struct in6_addr i6 = in6addr_loopback;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  egg_cv_var_have_in6addr_loopback="yes"
+else
+  egg_cv_var_have_in6addr_loopback="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $egg_cv_var_have_in6addr_loopback" >&5
+$as_echo "$egg_cv_var_have_in6addr_loopback" >&6; }
+    if test "$egg_cv_var_have_in6addr_loopback" = "yes"; then
+
+$as_echo "#define HAVE_IN6ADDR_LOOPBACK 1" >>confdefs.h
+
+    fi
+    ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "#include <netinet/in.h>
+"
+if test "x$ac_cv_type_struct_sockaddr_in6" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_IN6 1
+_ACEOF
+
+
+fi
+
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: no in6_addr found, skipping dependent checks. Custom definitions will be used." >&5
+$as_echo "$as_me: no in6_addr found, skipping dependent checks. Custom definitions will be used." >&6;}
+  fi
+fi
+
+
+
 # Substitute Makefile variables.
 
   EGGVERSION=`grep 'char.egg_version' $srcdir/src/main.c | $AWK '{gsub(/(\"|\;)/, "", $4); print $4}'`
Index: eggdrop1.8/configure.ac
diff -u eggdrop1.8/configure.ac:1.2 eggdrop1.8/configure.ac:1.3
--- eggdrop1.8/configure.ac:1.2	Tue Jul 27 07:05:43 2010
+++ eggdrop1.8/configure.ac	Thu Aug  5 12:12:04 2010
@@ -1,11 +1,11 @@
 dnl configure.ac: this file is processed by autoconf to produce ./configure.
 dnl
-dnl $Id: configure.ac,v 1.2 2010/07/27 13:05:43 pseudo Exp $
+dnl $Id: configure.ac,v 1.3 2010/08/05 18:12:04 pseudo Exp $
 
 AC_PREREQ(2.60)
 AC_INIT([Eggdrop],[1.8.0],[bugs at eggheads.org])
 AC_COPYRIGHT([Copyright (C) 1999 - 2010 Eggheads Development Team])
-AC_REVISION($Revision: 1.2 $)
+AC_REVISION($Revision: 1.3 $)
 AC_CONFIG_SRCDIR(src/eggdrop.h)
 AC_CONFIG_AUX_DIR(misc)
 AC_CONFIG_HEADER(config.h)
@@ -113,7 +113,7 @@
 
 
 # Checks for functions and their arguments.
-AC_CHECK_FUNCS([clock dprintf fsync getdtablesize getrusage inet_aton isascii mbrlen memcpy memset random rand lrand48 rename setpgid sigaction sigemptyset snprintf strcasecmp strncasecmp uname vsnprintf])
+AC_CHECK_FUNCS([clock dprintf fsync getdtablesize getrusage inet_aton isascii mbrlen memcpy memset random rand lrand48 rename setpgid sigaction sigemptyset snprintf strcasecmp strncasecmp uname vsnprintf inet_ntop])
 AC_FUNC_SELECT_ARGTYPES
 EGG_FUNC_VPRINTF
 AC_FUNC_STRFTIME
@@ -186,6 +186,12 @@
 # Let the user set the handlen with a configure option
 EGG_ARG_HANDLEN
 
+# Check for IPv6
+EGG_IPV6_STATUS
+EGG_IPV6_ENABLE
+EGG_IPV6_COMPAT
+
+
 # Substitute Makefile variables.
 EGG_SUBST_EGGVERSION
 EGG_SUBST_DEST
Index: eggdrop1.8/doc/CONTENTS
diff -u eggdrop1.8/doc/CONTENTS:1.1.1.1 eggdrop1.8/doc/CONTENTS:1.2
--- eggdrop1.8/doc/CONTENTS:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/doc/CONTENTS	Thu Aug  5 12:12:04 2010
@@ -1,7 +1,7 @@
-$Id: CONTENTS,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+$Id: CONTENTS,v 1.2 2010/08/05 18:12:04 pseudo Exp $
 
 Directory Contents - doc/
-Last revised: August 04, 2004
+Last revised: July 29, 2010
     _____________________________________________________________________
 
                           Directory Contents - doc/
@@ -36,6 +36,10 @@
   FIRST-SCRIPT
     This document will help get you started with Tcl scripting for Eggdrop.
 
+  IPV6
+    This document provides information about IPv6 support which is a new
+    eggdrop feature since version 1.8.0.
+
   KNOWN-PROBLEMS
     See this file for a list of things that are broken but aren't getting
     fixed anytime soon
Index: eggdrop1.8/doc/Changes1.8
diff -u eggdrop1.8/doc/Changes1.8:1.4 eggdrop1.8/doc/Changes1.8:1.5
--- eggdrop1.8/doc/Changes1.8:1.4	Tue Jul 27 15:49:41 2010
+++ eggdrop1.8/doc/Changes1.8	Thu Aug  5 12:12:04 2010
@@ -1,4 +1,4 @@
-$Id: Changes1.8,v 1.4 2010/07/27 21:49:41 pseudo Exp $
+$Id: Changes1.8,v 1.5 2010/08/05 18:12:04 pseudo Exp $
 
 Eggdrop Changes (since version 1.8.0)
 
@@ -6,6 +6,11 @@
 
 1.8.0 (CVS):
 
+  - Added full IPv6 support. New patch, nothing in common with older ones.
+  - Changed a lot of functions and variables without breaking scripting
+    compatibility. The list of changes is too long to include here.
+    Patch by: pseudo
+
   - Updated documentation to reference 1.8 instead of 1.6.
   - Changed module dependencies to 1.8.
   - Changed default handlen to 32.
Index: eggdrop1.8/doc/IPV6
diff -u /dev/null eggdrop1.8/doc/IPV6:1.1
--- /dev/null	Thu Aug  5 12:12:15 2010
+++ eggdrop1.8/doc/IPV6	Thu Aug  5 12:12:04 2010
@@ -0,0 +1,83 @@
+$Id: IPV6,v 1.1 2010/08/05 18:12:04 pseudo Exp $
+
+IPv6 support
+Last revised: Jul 29, 2010
+    _____________________________________________________________________
+
+                         IPv6 support
+
+
+  This document provides information about IPv6 support which is a new
+  eggdrop feature since version 1.8.0.
+
+  Contents:
+    1. About
+    2. Installation
+    3. Usage
+    4. IPv6 settings
+
+
+  1. About
+
+    Eggdrop can be compiled with IPv6 support. To make use of this, you need an
+    IPv6-enabled OS and IPv6 connectivity.
+    Every possible type of TCP connection can be established over IPv6 now,
+    which includes IRC connections, DCC connections, file transfer, botnet
+    connections, Tcl script connections initiated with the listen/connect
+    commands, telnet and ident lookups.
+
+
+  2. Installation
+
+    ./configure and install as usual, the configure script will detect if your
+    system supports IPv6 and will enable it automatically. You can override this
+    behavior and manually enable or disable IPv6 with ./configure --enable-ipv6
+    or ./configure --disable-ipv6.
+    Older operating systems may have limited or no support for IPv6. Linux 2.4 &
+    2.6, FreeBSD, NetBSD, OpenBSD and Mac OS X all have full IPv6 support.
+    MS Windows has proper support beginning with Windows Vista. XP's IPv6 stack
+    has some limitations and needs to be manually installed and enabled. Cygwin
+    includes IPv6 only since version 1.7. Unofficial patches are available for
+    1.5.x.
+
+
+  3. Usage
+
+    You can use IPv6 addresses wherever you could specify IPv4 ones. IPs and
+    hostnames are interchangeable everywhere. For certain settings and
+    commands, you can use a comma ',' instead of the colon character ':' as a
+    port separator. These are documented in the help files and the html
+    documentation, so you can consult them when in doubt.
+
+  4. Settings
+ 
+    There are four new IPv6 related config variables:
+
+       vhost4
+         set this to use a specific vhost with IPv4 connections. Can contain
+         either an IP address or a hostname.
+
+       vhost6
+         set this to use a specific vhost with IPv6 connections. Can contain
+         either an IPv6 address or a hostname.
+
+       prefer-ipv6
+         when a connection can be established through both IPv4 and IPv6.
+         You can set this to 1 to prefer IPv6 or to 0 to prefer IPv4.
+
+       listen-addr
+         the address to bind to for listening (telnet/bot ports, /ctcp chat,
+         file send, script listen, etc.). Can be either an IPv4/IPv6 IP or a
+         hostname. If a hostname resolves to both type of addresses,
+         prefer-ipv6 will determine which to be used. 
+
+    Other affected variables:
+
+      my-ip and my-hostname are removed now. Their function is split between
+        vhost4 and listen-addr.
+
+      nat-ip works with IPv4 as it used to. It has no meaning for IPv6 and is
+        not queried for IPv6 connections.
+    _____________________________________________________________________
+
+  Copyright (C) 2010 Eggheads Development Team
Index: eggdrop1.8/doc/html/egg-core.html
diff -u eggdrop1.8/doc/html/egg-core.html:1.1.1.1 eggdrop1.8/doc/html/egg-core.html:1.2
--- eggdrop1.8/doc/html/egg-core.html:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/doc/html/egg-core.html	Thu Aug  5 12:12:04 2010
@@ -1,5 +1,5 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<!-- $Id: egg-core.html,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $ -->
+<!-- $Id: egg-core.html,v 1.2 2010/08/05 18:12:04 pseudo Exp $ -->
 
 <html>
   <head>
@@ -126,15 +126,25 @@
           setting.</p>
         </dd>
 
-        <dt><strong>set my-hostname &quot;virtual.host.com&quot;</strong></dt>
-        <dt><strong>set my-ip &quot;99.99.0.0&quot;</strong></dt>
+        <dt><strong>set vhost4 &quot;virtual.host.com&quot;</strong></dt>
+        <dt><strong>set vhost4 &quot;99.99.0.0&quot;</strong></dt>
 
         <dd>
           <p>If you&#39;re using virtual hosting (your machine has more
           than 1 IP), you may want to specify the particular IP to bind to.
-          You can specify either by hostname or by IP. You may also want to
-          set the hostname here if Eggdrop has trouble detecting it when it
-          starts up.</p>
+          You can specify either by hostname or by IP. Note that this is not
+          used for listening. Use the &#39;listen-addr&#39; variable to specify
+          the listening address.</p>
+        </dd>
+
+        <dt><strong>set vhost6 &quot;my.ipv6.host.com&quot;</strong></dt>
+        <dt><strong>set vhost6 &quot;2001:db8::c001:b07&quot;</strong></dt>
+
+        <dd>
+          <p>IPv6 vhost to bind to for outgoing IPv6 connections. You can
+          set it to any valid IPv6 address or hostname, resolving to an IPv6
+          address. Note that this is not used for listening. Use the
+          &#39;listen-addr&#39; variable to specify the listening address.</p>
         </dd>
 
         <dt><strong>addlang &quot;english&quot;</strong></dt>
@@ -729,8 +739,8 @@
           for your box) or you have IP masquerading between you and the
           rest of the world, and /dcc chat, /ctcp chat or userfile sharing
           aren&#39;t working, enter your outside IP here. This IP is used for
-          transfers only, and has nothing to do with the my-ip or my-hostname
-          settings. You may still need to set my-ip and/or my-hostname.</p>
+          transfers only, and has nothing to do with the vhost4/6 or
+          listen-addr settings. You may still need to set them.</p>
         </dd>
 
         <dt><strong>set reserved-portrange 2010:2020</strong></dt>
Index: eggdrop1.8/doc/html/faqs.html
diff -u eggdrop1.8/doc/html/faqs.html:1.1.1.1 eggdrop1.8/doc/html/faqs.html:1.2
--- eggdrop1.8/doc/html/faqs.html:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/doc/html/faqs.html	Thu Aug  5 12:12:04 2010
@@ -1,5 +1,5 @@
 <!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 3.2 Final//EN">
-<!-- $Id: faqs.html,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $ -->
+<!-- $Id: faqs.html,v 1.2 2010/08/05 18:12:04 pseudo Exp $ -->
 
 <html>
   <head>
@@ -19,46 +19,43 @@
         <li><a href="#sect1">What do I do if I get the Error &quot;User file
         not found&quot;?</a></li>
 
-        <li><a href="#sect2">My Eggdrop won&#39;t run; It just says
-        &quot;Can&#39;t find your hostname!&quot;</a></li>
+        <li><a href="#sect2">What the heck is Tcl?</a></li>
 
-        <li><a href="#sect3">What the heck is Tcl?</a></li>
-
-        <li><a href="#sect4">My bot dies, and the last entry in the logfile is
+        <li><a href="#sect3">My bot dies, and the last entry in the logfile is
         &quot;Received terminate signal&quot;. What does that mean, and can I
         prevent it?</a></li>
 
-        <li><a href="#sect5">Someone else set up a bot I don&#39;t like. Are
+        <li><a href="#sect4">Someone else set up a bot I don&#39;t like. Are
         there any backdoors I can use to take their bot down?</a></li>
 
-        <li><a href="#sect6">What are modules?</a></li>
+        <li><a href="#sect5">What are modules?</a></li>
 
         <li>
-          <a href="#sect7">Can I compile Eggdrop without dynamic modules?</a>
+          <a href="#sect6">Can I compile Eggdrop without dynamic modules?</a>
 
 
           <ol type="a">
-            <li><a href="#sect7a">Do I still need to &quot;loadmodule&quot;
+            <li><a href="#sect6a">Do I still need to &quot;loadmodule&quot;
             modules?</a></li>
           </ol>
         </li>
 
-        <li><a href="#sect8">Where can I get a pre-compiled Eggdrop for my
+        <li><a href="#sect7">Where can I get a pre-compiled Eggdrop for my
         computer?</a></li>
 
-        <li><a href="#sect9">I get &quot;Makefile:3 : invalid operator&quot;
+        <li><a href="#sect8">I get &quot;Makefile:3 : invalid operator&quot;
         of some such thing When I try to &quot;make&quot;</a></li>
 
-        <li><a href="#sect10">When I &quot;tclsh scripts/weed
+        <li><a href="#sect9">When I &quot;tclsh scripts/weed
         &lt;userfile&gt; c&quot; It barfs chunks at me and dies.</a></li>
 
-        <li><a href="#sect11">I get &quot;ld-elf.so.1: Shared object
+        <li><a href="#sect10">I get &quot;ld-elf.so.1: Shared object
         &quot;libtcl80.so.1&quot; not found&quot; or &quot;eggdrop: error in
         loading shared libraries / libtcl8.1.so: cannot open shared object
         file: No such file or directory&quot; when I try to start my
         bot.</a></li>
 
-        <li><a href="#sect12">I get a whole pile of &quot;unresolved symbol
+        <li><a href="#sect11">I get a whole pile of &quot;unresolved symbol
         &#39;Tcl_AppendResult&#39;&quot; (or some other symbol) when I try to
         load a module.</a></li>
       </ol>
@@ -82,16 +79,7 @@
       </ul>
     </blockquote>
 
-    <p><a name="sect2"></a>2. <strong>My Eggdrop won&#39;t run; it just says
-    &quot;can&#39;t find your hostname!&quot;</strong></p>
-
-    <blockquote>
-      Your machine is set up strangely, and Eggdrop can&#39;t figure out its
-      network hostname. You can get around this by setting the my-ip setting
-      in the config file correctly.
-    </blockquote>
-
-    <p><a name="sect3"></a>3. <strong>What the heck is Tcl?</strong></p>
+    <p><a name="sect2"></a>2. <strong>What the heck is Tcl?</strong></p>
 
     <blockquote>
       <p>Tcl is a scripting language written by John Ousterhout. It&#39;s
@@ -106,7 +94,7 @@
       typically the best way).</p>
     </blockquote>
 
-    <p><a name="sect4"></a>4. <strong>My bot dies and the last entry in the
+    <p><a name="sect3"></a>3. <strong>My bot dies and the last entry in the
     logfile is &quot;received terminate signal&quot;. What does that mean and
     can i prevent it?</strong></p>
 
@@ -120,7 +108,7 @@
       he/she doesn&#39;t want bots running on the system.</p>
     </blockquote>
 
-    <p><a name="sect5"></a>5. <strong>Someone else set up a bot I don&#39;t
+    <p><a name="sect4"></a>4. <strong>Someone else set up a bot I don&#39;t
     like. Are there any backdoors I can use to take their bot down?</strong></p>
 
     <blockquote>
@@ -131,7 +119,7 @@
       not have my/our help.</p>
     </blockquote>
 
-    <p><a name="sect6"></a>6. <strong>What are modules?</strong></p>
+    <p><a name="sect5"></a>5. <strong>What are modules?</strong></p>
 
     <blockquote>
       <p>Modules are a way of adding extra features to the bot, much like Tcl
@@ -139,7 +127,7 @@
       more info.</p>
     </blockquote>
 
-    <p><a name="sect7"></a>7. <strong>Can I compile Eggdrop without dynamic
+    <p><a name="sect6"></a>6. <strong>Can I compile Eggdrop without dynamic
     modules?</strong></p>
 
     <blockquote>
@@ -150,7 +138,7 @@
       modules on a static-only system by using &#39;make eggdrop&#39;.</p>
     </blockquote>
 
-    <p><a name="sect7a"></a>7a. <strong>Do I still need to &#39;loadmodule&#39;
+    <p><a name="sect6a"></a>6a. <strong>Do I still need to &#39;loadmodule&#39;
     modules?</strong></p>
 
     <blockquote>
@@ -160,7 +148,7 @@
       with static modules as with dynamic modules.</p>
     </blockquote>
 
-    <p><a name="sect8"></a>8. <strong>Where can i get a pre-compiled Eggdrop
+    <p><a name="sect7"></a>7. <strong>Where can i get a pre-compiled Eggdrop
     for my computer?</strong></p>
 
     <blockquote>
@@ -174,7 +162,7 @@
       either. =P</p>
     </blockquote>
 
-    <p><a name="sect9"></a>9. <strong>I get &#39;Makefile:3 :invalid
+    <p><a name="sect8"></a>8. <strong>I get &#39;Makefile:3 :invalid
     operator&#39; or some-such-thing when I try to &#39;make&#39;.</strong>
     </p>
 
@@ -182,7 +170,7 @@
       <p>Try &#39;gmake&#39;.</p>
     </blockquote>
 
-    <p><a name="sect10"></a>10. <strong>When I &#39;tclsh scripts/weed
+    <p><a name="sect9"></a>9. <strong>When I &#39;tclsh scripts/weed
     &lt;userfile&gt; c&#39; it barfs chunks at me and dies. :(</strong></p>
 
     <blockquote>
@@ -192,7 +180,7 @@
       with &#39;.&#39; generally) and accept the loss of that data.</p>
     </blockquote>
 
-    <p><a name="sect11"></a>11. <strong>I get &quot;ld-elf.so.1: Shared
+    <p><a name="sect10"></a>10. <strong>I get &quot;ld-elf.so.1: Shared
     object &quot;libtcl80.so.1&quot; not found&quot; or &quot;eggdrop: error
     in loading shared libraries / libtcl8.1.so: cannot open shared object
     file: No such file or directory&quot; when I try to start my bot.
@@ -234,12 +222,12 @@
       (Suggested by dw at Undernet, dw at lixom.nu).</p>
     </blockquote>
 
-    <p><a name="sect12"></a>12. <strong>I get a whole pile of
+    <p><a name="sect11"></a>11. <strong>I get a whole pile of
     &quot;Unresolved symbol &#39;Tcl_AppendResult&#39;&quot; (or some other
     symbol) when I try to load a modules.</strong></p>
 
     <blockquote>
-      <p>Possibility A: See section 11.</p>
+      <p>Possibility A: See section 10.</p>
 
       <p>Possibility B: Some of the standard libraries have been compiled
       for static linking only on your machine, you have 3 options:</p>
Index: eggdrop1.8/doc/settings/core.settings
diff -u eggdrop1.8/doc/settings/core.settings:1.1.1.1 eggdrop1.8/doc/settings/core.settings:1.2
--- eggdrop1.8/doc/settings/core.settings:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/doc/settings/core.settings	Thu Aug  5 12:12:04 2010
@@ -1,4 +1,4 @@
-$Id: core.settings,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+$Id: core.settings,v 1.2 2010/08/05 18:12:04 pseudo Exp $
 
 Eggdrop Core Settings
 Last revised: April 17, 2003
@@ -66,12 +66,35 @@
       only, but instead everywhere possible, then use this setting.
 
 
-    set my-hostname "virtual.host.com"
-    set my-ip "99.99.0.0"
+    set vhost4 "virtual.host.com"
+    set vhost4 "99.99.0.0"
       If you're using virtual hosting (your machine has more than 1 IP), you
       may want to specify the particular IP to bind to. You can specify either
-      by hostname or by IP. You may also want to set the hostname here if
-      Eggdrop has trouble detecting it when it starts up.
+      by hostname or by IP. Note that this is not used for listening.  Use the
+      'listen-addr' variable to specify the listening address.
+
+
+    set vhost6 "2001:db8:618:5c0:263::"
+    set vhost6 "my.ipv6.host.com"
+     IPv6 vhost to bind to for outgoing IPv6 connections. You can set it
+     to any valid IPv6 address or hostname, resolving to an IPv6 address.
+     Note that this is not used for listening. Use the 'listen-addr'
+     variable to specify the listening address.
+
+
+    set listen-addr "99.99.0.0"
+    set listen-addr "2001:db8:618:5c0:263::"
+    set listen-addr "virtual.host.com"
+      IPv4/IPv6 address (or hostname) to bind for listening.
+      If you don't set this variable, eggdrop will listen on all available
+      IPv4 or IPv6 interfaces, depending on the 'prefer-ipv6' variable.
+      Note that on most platforms, IPv6 sockets are able to accept both
+      IPv4 and IPv6 connections.
+
+    set prefer-ipv6 "1"
+      Prefer IPv6 over IPv4 for connections and dns resolution.
+      If the preferred protocol family is not suppored, other possible
+      families will be tried.
 
 
     addlang "english"
@@ -409,8 +432,8 @@
       address to a unique address for your box) or you have IP masquerading
       between you and the rest of the world, and /dcc chat, /ctcp chat or
       userfile sharing aren't working, enter your outside IP here. This IP
-      is used for transfers only, and has nothing to do with the my-ip or
-      my-hostname settings. You may still need to set my-ip and/or my-hostname.
+      is used for transfers only, and has nothing to do with the vhost4/6 or
+      listen-addr settings. You may still need to set them.
 
 
     set reserved-portrange 2010:2020
Index: eggdrop1.8/eggdrop.conf
diff -u eggdrop1.8/eggdrop.conf:1.1.1.1 eggdrop1.8/eggdrop.conf:1.2
--- eggdrop1.8/eggdrop.conf:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/eggdrop.conf	Thu Aug  5 12:12:04 2010
@@ -1,7 +1,7 @@
 #! /path/to/executable/eggdrop
 # ^- This should contain a fully qualified path to your Eggdrop executable.
 #
-# $Id: eggdrop.conf,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+# $Id: eggdrop.conf,v 1.2 2010/08/05 18:12:04 pseudo Exp $
 #
 # This is a sample Eggdrop configuration file which includes all possible
 # settings that can be used to configure your bot.
@@ -53,10 +53,30 @@
 
 # If you're using virtual hosting (your machine has more than 1 IP), you
 # may want to specify the particular IP to bind to. You can specify either
-# by hostname or by IP. You may also want to set the hostname here if
-# Eggdrop has trouble detecting it when it starts up.
-#set my-hostname "virtual.host.com"
-#set my-ip "99.99.0.0"
+# by hostname or by IP. Note that this is not used for listening. Use the
+# 'listen-addr' variable to specify the listening address.
+#set vhost4 "virtual.host.com"
+#set vhost4 "99.99.0.0"
+
+# IPv6 vhost to bind to for outgoing IPv6 connections. You can set it
+# to any valid IPv6 address or hostname, resolving to an IPv6 address.
+# Note that this is not used for listening. Use the 'listen-addr'
+# variable to specify the listening address.
+#set vhost6 "my.ipv6.host.com"
+#set vhost6 "2001:db8::c001:b07"
+
+# IPv4/IPv6 address (or hostname) to bind for listening. If you don't set
+# this variable, eggdrop will listen on all available IPv4 or IPv6 interfaces,
+# depending on the 'prefer-ipv6' variable (see below).
+# Note that eggdrop will accept IPv4 connecions with IPv6 sockets too.
+#set listen-addr "99.99.0.0"
+#set listen-addr "2001:db8:618:5c0:263::"
+#set listen-addr "virtual.host.com"
+
+# Prefer IPv6 over IPv4 for connections and dns resolution?
+# If the preferred protocol family is not supported, the other one
+# will be tried.
+set prefer-ipv6 0
 
 # If you want to have your Eggdrop messages displayed in a language other
 # than English, change this setting to match your preference. An alternative
@@ -334,8 +354,8 @@
 # address to a unique address for your box) or you have IP masquerading
 # between you and the rest of the world, and /dcc chat, /ctcp chat or
 # userfile sharing aren't working, enter your outside IP here. This IP
-# is used for transfers only, and has nothing to do with the my-ip or
-# my-hostname settings. You may still need to set my-ip and/or my-hostname.
+# is used for transfers only, and has nothing to do with the vhost4/6
+# or listen-addr settings. You may still need to set them.
 #set nat-ip "127.0.0.1"
 
 # If you want all dcc file transfers to use a particular portrange either
@@ -833,6 +853,8 @@
 #
 # The format is:
 #   server[:port[:password]]
+# If you need to specify a numeric server IPv6 address, use following format:
+#   ip,[port[:password]]
 #
 # Both the port and password fields are optional; however, if you want to set a
 # password you must also set a port. If a port isn't specified it will default to
@@ -840,6 +862,7 @@
 set servers {
   you.need.to.change.this:6667
   another.example.com:7000:password
+  2001:db8:618:5c0:263::,6669:password
 }
 
 # Number of seconds to wait between transmitting queued lines to the server.
Index: eggdrop1.8/help/cmds1.help
diff -u eggdrop1.8/help/cmds1.help:1.1.1.1 eggdrop1.8/help/cmds1.help:1.2
--- eggdrop1.8/help/cmds1.help:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/help/cmds1.help	Thu Aug  5 12:12:04 2010
@@ -1,5 +1,6 @@
 %{help=+bot}%{+t}
 ###  %b+bot%b <handle> [address[:bot port[/user port]]] [host]
+###  %b+bot%b <handle> [IPv6 address[,bot port[/user port]]] [host]
    Creates a user record for a new bot with the handle given. If no hostmask
    is specified, the bot will try to automatically add a host from the channel.
    The bot's address will be used in linking. If the bot has a separate port
@@ -151,6 +152,7 @@
 See also: bots, botinfo, vbottree
 %{help=chaddr}%{+t}
 ###  %bchaddr%b <bot> <address[:bot port[/user port]]>
+###  %bchaddr%b <bot> <IPv6 address[,bot port[/user port]]>
    Changes the address for a bot. This is the address your bot will try to
    connect to when linking. If the bot has a separate port for bots and users,
    they should be separated  by a slash (/).
@@ -271,13 +273,13 @@
    is considered a "dcc" connection.
 
    The headings of the table are:
-     %bSOCK%b  the socket number of this connection (always unique)
+     %bIDX%b   index; the socket number of this connection (always unique)
      %bADDR%b  the ip address mask of the host the bot is connected to, if
            applicable
      %bPORT%b  the port number being used for this connection
      %bNICK%b  the handle of the user or bot, if applicable
-     %bHOST%b  the hostname corresponding to the IP address, if available
      %bTYPE%b  the type of dcc connection (see below)
+     %bINFO%b  misc information, i.e. flags for certain dcc types
 
    The types of connections currently possible are as follows (but more are
    being added all the time):
Index: eggdrop1.8/help/core.help
diff -u eggdrop1.8/help/core.help:1.1.1.1 eggdrop1.8/help/core.help:1.2
--- eggdrop1.8/help/core.help:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/help/core.help	Thu Aug  5 12:12:04 2010
@@ -145,7 +145,7 @@
 userfile
 motd
 paranoid-telnet-flood
-my-ip
+vhost
 telnet-banner
 admin
 use-telnet-banner
@@ -192,7 +192,10 @@
 share-unlinks
 allow-dk-cmds
 userfile-perm
+listen-addr
 switch-logfiles-at
+vhost6
+prefer-ipv6
 %{end}
    Use %b'.help set <variable>'%b for more info on each variable.
 %{help=all}%{-}
Index: eggdrop1.8/help/set/cmds1.help
diff -u eggdrop1.8/help/set/cmds1.help:1.1.1.1 eggdrop1.8/help/set/cmds1.help:1.2
--- eggdrop1.8/help/set/cmds1.help:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/help/set/cmds1.help	Thu Aug  5 12:12:04 2010
@@ -31,10 +31,19 @@
 %{help=set my-hostname}%{+n}
 ###  %bset my-hostname%b <hostname>
    Set this if Eggdrop has trouble detecting its hostname.
-%{help=set my-ip}%{+n}
-###  %bset my-ip%b <ip-address>
+%{help=set vhost4}%{+n}
+###  %bset vhost4%b <ipv4-address|hostname>
    If you're using virtual hosting (your machine has more than 1 IP),
-   you may want to set this to a particular IP to bind to.
+   you may want to set this to a particular IP to bind to. You can
+   specify either by hostname or by IP. Note that this is not used for
+   listening. Use the listen-addr variable to specify the listening
+   address.
+%{help=set vhost6}%{+n}
+###  %bset vhost6%b <ipv6-address|hostname>
+   IPv6 vhost to bind to for outgoing IPv6 connections. You can set it
+   to any valid IPv6 address or hostname, resolving to an IPv6 address.
+   Note that this is not used for listening. Use the listen-addr
+   variable to specify the listening address.
 %{help=set nat-ip}%{+n}
 ###  %bset nat-ip%b <ip-address>
    If you have a NAT firewall (you box has an IP in one of the
@@ -44,9 +53,18 @@
    for your box) or you have IP masquerading between you and the
    rest of the world, and /dcc chat, /ctcp chat or userfile sharing
    aren't working, enter your outside IP here. This IP is used for
-   transfers only, and has nothing to do with the my-ip or
-   my-hostname settings. You may still need to set my-ip and/or
-   my-hostname.
+   transfers only, and has nothing to do with the vhost4/6 or
+   listen-addr settings. You may still need to set them.
+%{help=set listen-addr}%{+n}
+###  %bset listen-addr%b <ip-address/hostname>
+   You can specify a particular IPv4/IPv6 address (or hostname)
+   to bind for listening, e.g. for the 'listen' tcl command or
+   for file sending.
+%{help=set prefer-ipv6}%{+n}
+###  %bset prefer-ipv6%b <0/1>
+  Prefer IPv6 over IPv4 for connections and dns resolution.
+  If the preferred protocol family is not supported, the other
+  one will be tried.
 %{help=set dcc-sanitycheck}%{+n}
 ###  %bset dcc-sanitycheck%b <0/1>
    This setting will make the bot ignore DCC chat requests which
Index: eggdrop1.8/src/botnet.c
diff -u eggdrop1.8/src/botnet.c:1.1.1.1 eggdrop1.8/src/botnet.c:1.2
--- eggdrop1.8/src/botnet.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/botnet.c	Thu Aug  5 12:12:05 2010
@@ -7,7 +7,7 @@
  *   linking, unlinking, and relaying to another bot
  *   pinging the bots periodically and checking leaf status
  *
- * $Id: botnet.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: botnet.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1015,9 +1015,19 @@
       correct_handle(nick);
 
       if (idx > -2)
+#ifdef IPV6
+      {
+        if (strchr(bi->address, ':'))
+          putlog(LOG_BOTS, "*", "%s %s at [%s]:%d ...", BOT_LINKING, nick,
+                 bi->address, bi->telnet_port);
+        else
+          putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
+                 bi->address, bi->telnet_port);
+      }
+#else
         putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
                bi->address, bi->telnet_port);
-
+#endif
       i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
       dcc[i].timeval = now;
       dcc[i].port = bi->telnet_port;
@@ -1056,18 +1066,17 @@
   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);
   nfree(linker);
+  setsnport(dcc[i].sockname, dcc[i].port);
+  dcc[i].sock = getsock(dcc[i].sockname.family, SOCK_STRONGCONN);
   if (dcc[i].sock < 0 ||
-      open_telnet_raw(dcc[i].sock, iptostr(htonl(dcc[i].addr)),
-                      dcc[i].port) < 0)
+      open_telnet_raw(dcc[i].sock, &dcc[i].sockname) < 0)
     failed_link(i);
 }
 
@@ -1099,14 +1108,14 @@
     return;
   }
   killsock(dcc[idx].sock);
-  dcc[idx].sock = getsock(SOCK_STRONGCONN);
+  if (!dcc[idx].sockname.addrlen)
+    (void) setsockname(&dcc[idx].sockname, dcc[idx].host, dcc[idx].port, 0);
+  dcc[idx].sock = getsock(dcc[idx].sockname.family, SOCK_STRONGCONN);
   dcc[uidx].u.relay->sock = dcc[idx].sock;
   dcc[idx].port++;
   dcc[idx].timeval = now;
   if (dcc[idx].sock < 0 ||
-      open_telnet_raw(dcc[idx].sock, dcc[idx].addr ?
-                      iptostr(htonl(dcc[idx].addr)) :
-                      dcc[idx].host, dcc[idx].port) < 0)
+      open_telnet_raw(dcc[idx].sock, &dcc[idx].sockname) < 0)
     failed_tandem_relay(idx);
 }
 
@@ -1145,7 +1154,7 @@
     return;
   }
 
-  dcc[i].sock = getsock(SOCK_STRONGCONN | SOCK_VIRTUAL);
+  dcc[i].sock = getsock(AF_INET, SOCK_STRONGCONN | SOCK_VIRTUAL);
   if (dcc[i].sock < 0) {
     lostdcc(i);
     dprintf(idx, "%s\n", MISC_NOFREESOCK);
@@ -1157,6 +1166,12 @@
   strcpy(dcc[i].nick, nick);
   dcc[i].user = u;
   strcpy(dcc[i].host, bi->address);
+#ifdef IPV6
+  if (strchr(bi->address, ':'))
+    dprintf(idx, "%s %s @ [%s]:%d ...\n", BOT_CONNECTINGTO, nick,
+            bi->address, bi->relay_port);
+  else
+#endif
   dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick,
           bi->address, bi->relay_port);
   dprintf(idx, "%s\n", BOT_BYEINFO1);
@@ -1165,8 +1180,8 @@
   dcc[idx].u.relay = get_data_ptr(sizeof(struct relay_info));
   dcc[idx].u.relay->chat = ci;
   dcc[idx].u.relay->old_status = dcc[idx].status;
-  dcc[idx].u.relay->sock = dcc[i].sock;
   dcc[i].timeval = now;
+  dcc[idx].u.relay->sock = dcc[i].sock;
   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);
@@ -1209,7 +1224,6 @@
 {
   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));
 
@@ -1223,8 +1237,16 @@
   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(htonl(dcc[i].addr)),
-                      dcc[i].port) < 0)
+#ifdef IPV6
+  if (dcc[i].sockname.family == AF_INET6) {
+    killsock(dcc[i].sock);
+    dcc[i].sock = getsock(AF_INET6, SOCK_STRONGCONN | SOCK_VIRTUAL);
+    dcc[i].sockname.addr.s6.sin6_port = htons(dcc[i].port);
+    dcc[i].u.relay->sock = dcc[i].sock;
+  } else
+#endif
+    dcc[i].sockname.addr.s4.sin_port = htons(dcc[i].port);
+  if (open_telnet_raw(dcc[i].sock, &dcc[i].sockname) < 0)
     failed_tandem_relay(i);
 }
 
Index: eggdrop1.8/src/cmds.c
diff -u eggdrop1.8/src/cmds.c:1.1.1.1 eggdrop1.8/src/cmds.c:1.2
--- eggdrop1.8/src/cmds.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/cmds.c	Thu Aug  5 12:12:05 2010
@@ -3,7 +3,7 @@
  *   commands from a user via dcc
  *   (split in 2, this portion contains no-irc commands)
  *
- * $Id: cmds.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: cmds.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -753,6 +753,10 @@
   if (!par[0]) {
     dprintf(idx, "Usage: +bot <handle> [address[:telnet-port[/relay-port]]] "
             "[host]\n");
+#ifdef IPV6
+    dprintf(idx, "IPv6: +bot <handle> [IPv6-address,[telnet-port[/relay-port]]]"
+            " [host]\n");
+#endif
     return;
   }
 
@@ -782,6 +786,14 @@
   u1 = get_user_by_handle(userlist, handle);
   bi = user_malloc(sizeof(struct bot_addr));
 
+#ifdef IPV6
+  if ((q = strchr(addr, ','))) {
+    if (!q[1]) {
+      *q = 0;
+      q = 0;
+    }
+  } else
+#endif
   q = strchr(addr, ':');
   if (!q) {
     bi->address = user_malloc(strlen(addr) + 1);
@@ -952,6 +964,10 @@
   if (!par[0]) {
     dprintf(idx, "Usage: chaddr <botname> "
             "<address[:telnet-port[/relay-port]]>\n");
+#ifdef IPV6
+    dprintf(idx, "IPv6: chaddr <botname> "
+            "<IPv6-address,[telnet-port[/relay-port]]>\n");
+#endif
     return;
   }
   addr = newsplit(&par);
@@ -977,6 +993,14 @@
 
   bi = user_malloc(sizeof(struct bot_addr));
 
+#ifdef IPV6
+  if ((q = strchr(addr, ','))) {
+    if (!q[1]) {
+      *q = 0;
+      q = 0;
+    }
+  } else
+#endif
   q = strchr(addr, ':');
   if (!q) {
     bi->address = user_malloc(strlen(addr) + 1);
Index: eggdrop1.8/src/compat/Makefile.in
diff -u eggdrop1.8/src/compat/Makefile.in:1.1.1.1 eggdrop1.8/src/compat/Makefile.in:1.2
--- eggdrop1.8/src/compat/Makefile.in:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/compat/Makefile.in	Thu Aug  5 12:12:05 2010
@@ -1,5 +1,5 @@
 # Makefile for src/compat/
-# $Id: Makefile.in,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+# $Id: Makefile.in,v 1.2 2010/08/05 18:12:05 pseudo Exp $
 
 SHELL = @SHELL@
 top_srcdir = @top_srcdir@
@@ -18,7 +18,8 @@
 CFLAGS = @CFLAGS@ -I../.. -I$(top_srcdir) -I$(top_srcdir)/src @DEFS@ $(CFLGS)
 CPPFLAGS = @CPPFLAGS@
 
-OBJS = inet_aton.o snprintf.o memset.o memcpy.o strcasecmp.o strftime.o
+OBJS = gethostbyname2.o in6.o inet_aton.o inet_ntop.o inet_pton.o snprintf.o \
+	memset.o memcpy.o strcasecmp.o strftime.o
 
 doofus:
 	@echo ""
@@ -42,6 +43,25 @@
 
 #safety hash
 gnu_strftime.o: gnu_strftime.c ../../config.h
+gethostbyname2.o: gethostbyname2.c ../../src/main.h \
+  ../../config.h ../../lush.h \
+  ../../src/lang.h ../../src/eggdrop.h ../../src/flags.h \
+  ../../src/proto.h ../../src/misc_file.h ../../src/cmdt.h \
+  ../../src/tclegg.h ../../src/tclhash.h ../../src/chan.h \
+  ../../src/users.h ../../src/compat/compat.h \
+  ../../src/compat/inet_aton.h ../../src/main.h \
+  ../../src/compat/snprintf.h ../../src/compat/memset.h \
+  ../../src/compat/memcpy.h ../../src/compat/strcasecmp.h \
+  ../../src/compat/strftime.h in6.h gethostbyname2.h
+in6.o: in6.c ../../src/main.h ../../config.h ../../lush.h \
+  ../../src/lang.h ../../src/eggdrop.h ../../src/flags.h \
+  ../../src/proto.h ../../src/misc_file.h ../../src/cmdt.h \
+  ../../src/tclegg.h ../../src/tclhash.h ../../src/chan.h \
+  ../../src/users.h ../../src/compat/compat.h \
+  ../../src/compat/inet_aton.h ../../src/main.h \
+  ../../src/compat/snprintf.h ../../src/compat/memset.h \
+  ../../src/compat/memcpy.h ../../src/compat/strcasecmp.h \
+  ../../src/compat/strftime.h in6.h
 inet_aton.o: inet_aton.c ../../src/main.h ../../config.h ../../lush.h \
   ../../src/lang.h ../../src/eggdrop.h ../../src/flags.h \
   ../../src/proto.h ../../src/misc_file.h ../../src/cmdt.h \
@@ -51,6 +71,24 @@
   ../../src/compat/snprintf.h ../../src/compat/memset.h \
   ../../src/compat/memcpy.h ../../src/compat/strcasecmp.h \
   ../../src/compat/strftime.h inet_aton.h
+inet_ntop.o: inet_ntop.c ../../src/main.h ../../config.h ../../lush.h \
+  ../../src/lang.h ../../src/eggdrop.h ../../src/flags.h \
+  ../../src/proto.h ../../src/misc_file.h ../../src/cmdt.h \
+  ../../src/tclegg.h ../../src/tclhash.h ../../src/chan.h \
+  ../../src/users.h ../../src/compat/compat.h \
+  ../../src/compat/inet_aton.h ../../src/main.h \
+  ../../src/compat/snprintf.h ../../src/compat/memset.h \
+  ../../src/compat/memcpy.h ../../src/compat/strcasecmp.h \
+  ../../src/compat/strftime.h in6.h inet_ntop.h
+inet_pton.o: inet_pton.c ../../src/main.h ../../config.h ../../lush.h \
+  ../../src/lang.h ../../src/eggdrop.h ../../src/flags.h \
+  ../../src/proto.h ../../src/misc_file.h ../../src/cmdt.h \
+  ../../src/tclegg.h ../../src/tclhash.h ../../src/chan.h \
+  ../../src/users.h ../../src/compat/compat.h \
+  ../../src/compat/inet_aton.h ../../src/main.h \
+  ../../src/compat/snprintf.h ../../src/compat/memset.h \
+  ../../src/compat/memcpy.h ../../src/compat/strcasecmp.h \
+  ../../src/compat/strftime.h in6.h inet_pton.h
 memcpy.o: memcpy.c ../../src/main.h ../../config.h ../../lush.h \
   ../../src/lang.h ../../src/eggdrop.h ../../src/flags.h \
   ../../src/proto.h ../../src/misc_file.h ../../src/cmdt.h \
Index: eggdrop1.8/src/compat/compat.h
diff -u eggdrop1.8/src/compat/compat.h:1.1.1.1 eggdrop1.8/src/compat/compat.h:1.2
--- eggdrop1.8/src/compat/compat.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/compat/compat.h	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * compat.h
  *   wrap-around header for all compability functions.
  *
- * $Id: compat.h,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: compat.h,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 2000 - 2010 Eggheads Development Team
@@ -31,5 +31,8 @@
 #include "memcpy.h"
 #include "strcasecmp.h"
 #include "strftime.h"
+#include "inet_ntop.h"
+#include "inet_pton.h"
+#include "gethostbyname2.h"
 
 #endif /* !__EGG_COMPAT_COMPAT_H */
Index: eggdrop1.8/src/compat/gethostbyname2.c
diff -u /dev/null eggdrop1.8/src/compat/gethostbyname2.c:1.1
--- /dev/null	Thu Aug  5 12:12:15 2010
+++ eggdrop1.8/src/compat/gethostbyname2.c	Thu Aug  5 12:12:05 2010
@@ -0,0 +1,35 @@
+/*
+ * gethostbyname2.c -- provide a dummy gethostbyname2 replacement
+ *
+ * $Id: gethostbyname2.c,v 1.1 2010/08/05 18:12:05 pseudo Exp $
+ */
+/*
+ * Copyright (C) 2010 Eggheads Development Team
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "gethostbyname2.h"
+
+#ifndef HAVE_GETHOSTBYNAME2
+struct hostent *gethostbyname2(const char *name, int af)
+{
+  if(af != AF_INET) {
+    h_errno = NO_RECOVERY;
+    return 0;
+  }
+  return gethostbyname(name);
+}
+#endif
Index: eggdrop1.8/src/compat/gethostbyname2.h
diff -u /dev/null eggdrop1.8/src/compat/gethostbyname2.h:1.1
--- /dev/null	Thu Aug  5 12:12:15 2010
+++ eggdrop1.8/src/compat/gethostbyname2.h	Thu Aug  5 12:12:05 2010
@@ -0,0 +1,34 @@
+/*
+ * gethostbyname2.h
+ *   prototypes for gethostbyname2.c
+ *
+ * $Id: gethostbyname2.h,v 1.1 2010/08/05 18:12:05 pseudo Exp $
+ */
+/*
+ * Copyright (C) 2010 Eggheads Development Team
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <netdb.h>
+#include <netinet/in.h>
+
+#ifndef HAVE_GETHOSTBYNAME2
+struct hostent *gethostbyname2(const char *name, int af);
+#endif
Index: eggdrop1.8/src/compat/in6.c
diff -u /dev/null eggdrop1.8/src/compat/in6.c:1.1
--- /dev/null	Thu Aug  5 12:12:15 2010
+++ eggdrop1.8/src/compat/in6.c	Thu Aug  5 12:12:05 2010
@@ -0,0 +1,32 @@
+/*
+ * in6.c -- provide some IPv6 constants if not available
+ */
+/*
+ * Copyright (C) 2007 plazmus
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef IPV6
+
+#ifndef HAVE_IN6ADDR_ANY
+static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+#endif
+
+#ifndef HAVE_IN6ADDR_LOOPBACK
+static const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+#endif
+
+#endif /* IPV6 */
Index: eggdrop1.8/src/compat/in6.h
diff -u /dev/null eggdrop1.8/src/compat/in6.h:1.1
--- /dev/null	Thu Aug  5 12:12:15 2010
+++ eggdrop1.8/src/compat/in6.h	Thu Aug  5 12:12:05 2010
@@ -0,0 +1,110 @@
+/*
+ * in6.h -- various IPv6 related definitions and macros
+ *
+ * $Id: in6.h,v 1.1 2010/08/05 18:12:05 pseudo Exp $
+ */
+/*
+ * Copyright (C) 2010 Eggheads Development Team
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef IPV6
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+
+#ifndef PF_INET6
+#  define PF_INET6 PF_MAX
+#endif
+
+#ifndef AF_INET6
+#  define AF_INET6 PF_INET6
+#endif
+
+#ifndef HAVE_STRUCT_IN6_ADDR
+struct in6_addr {
+  union {
+    u_8bit_t	__u6_addr8[16];
+    u_16bit_t	__u6_addr16[8];
+    u_32bit_t	__u6_addr32[4];
+  } __u6_addr;
+#define	s6_addr	__u6_addr.__u6_addr8
+};
+#endif
+
+#ifndef HAVE_STRUCT_SOCKADDR_IN6
+struct sockaddr_in6 {
+  u_16bit_t 	  sin6_family;
+  u_16bit_t 	  sin6_port;
+  u_32bit_t 	  sin6_flowinfo;
+  struct in6_addr sin6_addr;
+  u_32bit_t       sin6_scope_id;
+};
+#endif
+
+#ifndef INET6_ADDRSTRLEN
+#  define INET6_ADDRSTRLEN 46
+#endif
+
+#ifndef IN6ADDR_ANY_INIT
+#  define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
+#endif
+
+#ifndef IN6ADDR_LOOPBACK_INIT
+#  define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
+#endif
+
+#ifndef HAVE_IN6ADDR_ANY
+extern const struct in6_addr in6addr_any;
+#endif
+
+#ifndef HAVE_IN6ADDR_LOOPBACK
+extern const struct in6_addr in6addr_loopback;
+#endif
+
+#ifndef IN6_IS_ADDR_UNSPECIFIED
+# define IN6_IS_ADDR_UNSPECIFIED(a) \
+  (((const u_32bit_t *) (a))[0] == 0                                   \
+   && ((const u_32bit_t *) (a))[1] == 0                                \
+   && ((const u_32bit_t *) (a))[2] == 0                                \
+   && ((const u_32bit_t *) (a))[3] == 0)
+#endif
+
+#ifndef IN6_IS_ADDR_LOOPBACK
+# define IN6_IS_ADDR_LOOPBACK(a) \
+  (((const u_32bit_t *) (a))[0] == 0                                   \
+   && ((const u_32bit_t *) (a))[1] == 0                                \
+   && ((const u_32bit_t *) (a))[2] == 0                                \
+   && ((const u_32bit_t *) (a))[3] == htonl (1))
+#endif
+
+#ifndef IN6_IS_ADDR_V4MAPPED
+# define IN6_IS_ADDR_V4MAPPED(a) \
+  ((((const u_32bit_t *) (a))[0] == 0)                                 \
+   && (((const u_32bit_t *) (a))[1] == 0)                              \
+   && (((const u_32bit_t *) (a))[2] == htonl (0xffff)))
+#endif
+
+#ifndef IN6_ARE_ADDR_EQUAL
+# define IN6_ARE_ADDR_EQUAL(a,b) \
+  ((((const u_32bit_t *) (a))[0] == ((const u_32bit_t *) (b))[0])     \
+   && (((const u_32bit_t *) (a))[1] == ((const u_32bit_t *) (b))[1])  \
+   && (((const u_32bit_t *) (a))[2] == ((const u_32bit_t *) (b))[2])  \
+   && (((const u_32bit_t *) (a))[3] == ((const u_32bit_t *) (b))[3]))
+#endif
+
+#endif /* IPV6 */
Index: eggdrop1.8/src/compat/inet_ntop.c
diff -u /dev/null eggdrop1.8/src/compat/inet_ntop.c:1.1
--- /dev/null	Thu Aug  5 12:12:15 2010
+++ eggdrop1.8/src/compat/inet_ntop.c	Thu Aug  5 12:12:05 2010
@@ -0,0 +1,222 @@
+/*
+ * inet_ntop.c -- provides inet_ntop() if necessary
+ *
+ * $Id: inet_ntop.c,v 1.1 2010/08/05 18:12:05 pseudo Exp $
+ */
+/*
+ * Portions Copyright (C) 2010 Eggheads Development Team
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "inet_ntop.h"
+
+#ifndef HAVE_INET_NTOP
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+#define NS_INADDRSZ     4       /* IPv4 T_A */
+#define NS_IN6ADDRSZ    16      /* IPv6 T_AAAA */
+#define NS_INT16SZ      2       /* #/bytes of data in a u_int16_t */
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4 (const u_char *src, char *dst, socklen_t size);
+static const char *inet_ntop6 (const u_char *src, char *dst, socklen_t size);
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ *	convert a network format address to presentation format.
+ * return:
+ *	pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ *	Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(af, src, dst, size)
+	int af;
+	const void *src;
+	char *dst;
+	socklen_t size;
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_ntop4(src, dst, size));
+#ifdef IPV6
+	case AF_INET6:
+		return (inet_ntop6(src, dst, size));
+#endif
+	default:
+		return NULL;
+	}
+	/* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ *	format an IPv4 address
+ * return:
+ *	`dst' (as a const)
+ * notes:
+ *	(1) uses no statics
+ *	(2) takes a u_char* not an in_addr as input
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static const char *inet_ntop4(src, dst, size)
+	const u_char *src;
+	char *dst;
+	socklen_t size;
+{
+	static const char fmt[] = "%u.%u.%u.%u";
+	char tmp[sizeof "255.255.255.255"];
+
+	if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
+/*		__set_errno (ENOSPC); */
+		return (NULL);
+	}
+	return strcpy(dst, tmp);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ *	convert IPv6 binary address into presentation (printable) format
+ * author:
+ *	Paul Vixie, 1996.
+ */
+#ifdef IPV6
+static const char *
+inet_ntop6(src, dst, size)
+	const u_char *src;
+	char *dst;
+	socklen_t size;
+{
+	/*
+	 * Note that int32_t and int16_t need only be "at least" large enough
+	 * to contain a value of the specified size.  On some systems, like
+	 * Crays, there is no such thing as an integer variable with 16 bits.
+	 * Keep this in mind if you think this function should have been coded
+	 * to use pointer overlays.  All the world's not a VAX.
+	 */
+	char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+	struct { int base, len; } best, cur;
+	u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+	int i;
+
+	/*
+	 * Preprocess:
+	 *	Copy the input (bytewise) array into a wordwise array.
+	 *	Find the longest run of 0x00's in src[] for :: shorthanding.
+	 */
+	memset(words, '\0', sizeof words);
+	best.len = cur.len = 0;
+	for (i = 0; i < NS_IN6ADDRSZ; i += 2)
+		words[i / 2] = (src[i] << 8) | src[i + 1];
+	best.base = -1;
+	cur.base = -1;
+	for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+		if (words[i] == 0) {
+			if (cur.base == -1)
+				cur.base = i, cur.len = 1;
+			else
+				cur.len++;
+		} else {
+			if (cur.base != -1) {
+				if (best.base == -1 || cur.len > best.len)
+					best = cur;
+				cur.base = -1;
+			}
+		}
+	}
+	if (cur.base != -1) {
+		if (best.base == -1 || cur.len > best.len)
+			best = cur;
+	}
+	if (best.base != -1 && best.len < 2)
+		best.base = -1;
+
+	/*
+	 * Format the result.
+	 */
+	tp = tmp;
+	for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+		/* Are we inside the best run of 0x00's? */
+		if (best.base != -1 && i >= best.base &&
+		    i < (best.base + best.len)) {
+			if (i == best.base)
+				*tp++ = ':';
+			continue;
+		}
+		/* Are we following an initial run of 0x00s or any real hex? */
+		if (i != 0)
+			*tp++ = ':';
+		/* Is this address an encapsulated IPv4? */
+		if (i == 6 && best.base == 0 &&
+		    (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+			if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+				return (NULL);
+			tp += strlen(tp);
+			break;
+		}
+		tp += SPRINTF((tp, "%x", words[i]));
+	}
+	/* Was it a trailing run of 0x00's? */
+	if (best.base != -1 && (best.base + best.len) ==
+	    (NS_IN6ADDRSZ / NS_INT16SZ))
+		*tp++ = ':';
+	*tp++ = '\0';
+
+	/*
+	 * Check for overflow, copy, and we're done.
+	 */
+	if ((socklen_t)(tp - tmp) > size) {
+/*		__set_errno (ENOSPC); */
+		return (NULL);
+	}
+	return strcpy(dst, tmp);
+}
+#endif /* IPV6 */
+
+#endif /* HAVE_INET_NTOP */
Index: eggdrop1.8/src/compat/inet_ntop.h
diff -u /dev/null eggdrop1.8/src/compat/inet_ntop.h:1.1
--- /dev/null	Thu Aug  5 12:12:15 2010
+++ eggdrop1.8/src/compat/inet_ntop.h	Thu Aug  5 12:12:05 2010
@@ -0,0 +1,38 @@
+/*
+ * inet_ntop.h
+ *   prototypes for inet_ntop.c
+ *
+ * $Id: inet_ntop.h,v 1.1 2010/08/05 18:12:05 pseudo Exp $
+ */
+/*
+ * Copyright (C) 2010 Eggheads Development Team
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifndef HAVE_INET_NTOP
+const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
+#endif
Index: eggdrop1.8/src/compat/inet_pton.c
diff -u /dev/null eggdrop1.8/src/compat/inet_pton.c:1.1
--- /dev/null	Thu Aug  5 12:12:15 2010
+++ eggdrop1.8/src/compat/inet_pton.c	Thu Aug  5 12:12:05 2010
@@ -0,0 +1,235 @@
+/*
+ * inet_pton.c -- provides inet_pton() if necessary
+ *
+ * $Id: inet_pton.c,v 1.1 2010/08/05 18:12:05 pseudo Exp $
+ */
+/*
+ * Portions Copyright (C) 2010 Eggheads Development Team
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "inet_pton.h"
+
+#ifndef HAVE_INET_NTOP
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+
+#define NS_INADDRSZ     4       /* IPv4 T_A */
+#define NS_IN6ADDRSZ    16      /* IPv6 T_AAAA */
+#define NS_INT16SZ      2       /* #/bytes of data in a u_int16_t */
+
+static int inet_pton4 (const char *src, u_char *dst);
+static int inet_pton6 (const char *src, u_char *dst);
+
+/* int
+ * inet_pton(af, src, dst)
+ *	convert from presentation format (which usually means ASCII printable)
+ *	to network format (which is usually some kind of binary format).
+ * return:
+ *	1 if the address was valid for the specified address family
+ *	0 if the address wasn't valid (`dst' is untouched in this case)
+ *	-1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ *	Paul Vixie, 1996.
+ */
+int inet_pton(af, src, dst)
+	int af;
+	const char *src;
+	void *dst;
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_pton4(src, dst));
+#ifdef IPV6
+	case AF_INET6:
+		return (inet_pton6(src, dst));
+#endif
+	default:
+		return -1;
+	}
+	/* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ *	like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ *	1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ *	does not touch `dst' unless it's returning 1.
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static int
+inet_pton4(src, dst)
+	const char *src;
+	u_char *dst;
+{
+	int saw_digit, octets, ch;
+	u_char tmp[NS_INADDRSZ], *tp;
+
+	saw_digit = 0;
+	octets = 0;
+	*(tp = tmp) = 0;
+	while ((ch = *src++) != '\0') {
+
+		if (ch >= '0' && ch <= '9') {
+			u_int new = *tp * 10 + (ch - '0');
+
+			if (new > 255)
+				return (0);
+			*tp = new;
+			if (! saw_digit) {
+				if (++octets > 4)
+					return (0);
+				saw_digit = 1;
+			}
+		} else if (ch == '.' && saw_digit) {
+			if (octets == 4)
+				return (0);
+			*++tp = 0;
+			saw_digit = 0;
+		} else
+			return (0);
+	}
+	if (octets < 4)
+		return (0);
+	memcpy(dst, tmp, NS_INADDRSZ);
+	return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ *	convert presentation level address to network order binary form.
+ * return:
+ *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ *	(1) does not touch `dst' unless it's returning 1.
+ *	(2) :: in a full address is silently ignored.
+ * credit:
+ *	inspired by Mark Andrews.
+ * author:
+ *	Paul Vixie, 1996.
+ */
+#ifdef IPV6
+static int
+inet_pton6(src, dst)
+	const char *src;
+	u_char *dst;
+{
+	static const char xdigits[] = "0123456789abcdef";
+	u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+	const char *curtok;
+	int ch, saw_xdigit;
+	u_int val;
+
+	tp = memset(tmp, '\0', NS_IN6ADDRSZ);
+	endp = tp + NS_IN6ADDRSZ;
+	colonp = NULL;
+	/* Leading :: requires some special handling. */
+	if (*src == ':')
+		if (*++src != ':')
+			return (0);
+	curtok = src;
+	saw_xdigit = 0;
+	val = 0;
+	while ((ch = tolower (*src++)) != '\0') {
+		const char *pch;
+
+		pch = strchr(xdigits, ch);
+		if (pch != NULL) {
+			val <<= 4;
+			val |= (pch - xdigits);
+			if (val > 0xffff)
+				return (0);
+			saw_xdigit = 1;
+			continue;
+		}
+		if (ch == ':') {
+			curtok = src;
+			if (!saw_xdigit) {
+				if (colonp)
+					return (0);
+				colonp = tp;
+				continue;
+			} else if (*src == '\0') {
+				return (0);
+			}
+			if (tp + NS_INT16SZ > endp)
+				return (0);
+			*tp++ = (u_char) (val >> 8) & 0xff;
+			*tp++ = (u_char) val & 0xff;
+			saw_xdigit = 0;
+			val = 0;
+			continue;
+		}
+		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+		    inet_pton4(curtok, tp) > 0) {
+			tp += NS_INADDRSZ;
+			saw_xdigit = 0;
+			break;	/* '\0' was seen by inet_pton4(). */
+		}
+		return (0);
+	}
+	if (saw_xdigit) {
+		if (tp + NS_INT16SZ > endp)
+			return (0);
+		*tp++ = (u_char) (val >> 8) & 0xff;
+		*tp++ = (u_char) val & 0xff;
+	}
+	if (colonp != NULL) {
+		/*
+		 * Since some memmove()'s erroneously fail to handle
+		 * overlapping regions, we'll do the shift by hand.
+		 */
+		const int n = tp - colonp;
+		int i;
+
+		if (tp == endp)
+			return (0);
+		for (i = 1; i <= n; i++) {
+			endp[- i] = colonp[n - i];
+			colonp[n - i] = 0;
+		}
+		tp = endp;
+	}
+	if (tp != endp)
+		return (0);
+	memcpy(dst, tmp, NS_IN6ADDRSZ);
+	return (1);
+}
+#endif /* IPV6 */
+
+#endif /* HAVE_INET_NTOP */
Index: eggdrop1.8/src/compat/inet_pton.h
diff -u /dev/null eggdrop1.8/src/compat/inet_pton.h:1.1
--- /dev/null	Thu Aug  5 12:12:15 2010
+++ eggdrop1.8/src/compat/inet_pton.h	Thu Aug  5 12:12:05 2010
@@ -0,0 +1,37 @@
+/*
+ * inet_pton.h
+ *   prototypes for inet_pton.c
+ *
+ * $Id: inet_pton.h,v 1.1 2010/08/05 18:12:05 pseudo Exp $
+ */
+/*
+ * Copyright (C) 2010 Eggheads Development Team
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifndef HAVE_INET_PTON
+int inet_pton(int af, const char *src, void *dst);
+#endif
Index: eggdrop1.8/src/dcc.c
diff -u eggdrop1.8/src/dcc.c:1.1.1.1 eggdrop1.8/src/dcc.c:1.2
--- eggdrop1.8/src/dcc.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/dcc.c	Thu Aug  5 12:12:05 2010
@@ -4,7 +4,7 @@
  *   disconnect on a dcc socket
  *   ...and that's it!  (but it's a LOT)
  *
- * $Id: dcc.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: dcc.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -268,15 +268,13 @@
 
   /* Try next port */
   killsock(dcc[idx].sock);
-  dcc[idx].sock = getsock(SOCK_STRONGCONN);
   dcc[idx].port++;
   dcc[idx].timeval = now;
+  dcc[idx].sock = getsock(setsockname(&dcc[idx].sockname, dcc[idx].host,
+                                      dcc[idx].port, 1), SOCK_STRONGCONN);
   if (dcc[idx].sock < 0 ||
-      open_telnet_raw(dcc[idx].sock, dcc[idx].addr ?
-                      iptostr(htonl(dcc[idx].addr)) : dcc[idx].host,
-                      dcc[idx].port) < 0) {
+      open_telnet_raw(dcc[idx].sock, &dcc[idx].sockname) < 0)
     failed_link(idx);
-  }
 }
 
 static void cont_link(int idx, char *buf, int i)
@@ -1123,25 +1121,24 @@
 
 static void dcc_telnet(int idx, char *buf, int i)
 {
-  unsigned long ip;
   unsigned short port;
   int j = 0, sock;
-  char s[UHOSTLEN + 1];
 
   if (dcc_total + 1 > max_dcc && increase_socks_max()) {
-    j = answer(dcc[idx].sock, s, &ip, &port, 0);
+    sockname_t name;
+    j = answer(dcc[idx].sock, &name, &port, 0);
     if (j != -1) {
       dprintf(-j, "Sorry, too many connections already.\r\n");
       killsock(j);
     }
     return;
   }
-  sock = answer(dcc[idx].sock, s, &ip, &port, 0);
+  i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
+  sock = answer(dcc[idx].sock, &dcc[i].sockname, &port, 0);
   while ((sock == -1) && (errno == EAGAIN))
-    sock = answer(sock, s, &ip, &port, 0);
+    sock = answer(dcc[idx].sock, &dcc[i].sockname, &port, 0);
   if (sock < 0) {
-    neterror(s);
-    putlog(LOG_MISC, "*", DCC_FAILED, s);
+    putlog(LOG_MISC, "*", DCC_FAILED, strerror(errno));
     return;
   }
   /* Buffer data received on this socket.  */
@@ -1152,31 +1149,30 @@
 #else
   if (port < 1024 || port > 65535) {
 #endif
-    putlog(LOG_BOTS, "*", DCC_BADSRC, s, port);
+    putlog(LOG_BOTS, "*", DCC_BADSRC, iptostr(&dcc[i].sockname.addr.sa), port);
     killsock(sock);
+    lostdcc(i);
     return;
   }
 
-  i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
+  dcc[i].u.dns->ip = &dcc[i].sockname;
   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 = dcc_telnet_hostresolved;
   dcc[i].u.dns->dns_failure = dcc_telnet_hostresolved;
   dcc[i].u.dns->dns_type = RES_HOSTBYIP;
   dcc[i].u.dns->ibuf = dcc[idx].sock;
   dcc[i].u.dns->type = &DCC_IDENTWAIT;
-  dcc_dnshostbyip(ip);
+  dcc_dnshostbyip(&dcc[i].sockname);
 }
 
 static void dcc_telnet_hostresolved(int i)
 {
   int idx;
   int j = 0, sock;
-  char s[UHOSTLEN], s2[UHOSTLEN + 20];
+  char s[UHOSTLEN + 20];
 
   strncpyz(dcc[i].host, dcc[i].u.dns->host, UHOSTLEN);
 
@@ -1201,8 +1197,8 @@
       return;
     }
   }
-  sprintf(s2, "-telnet!telnet@%s", dcc[i].host);
-  if (match_ignore(s2) || detect_telnet_flood(s2)) {
+  sprintf(s, "-telnet!telnet@%s", dcc[i].host);
+  if (match_ignore(s) || detect_telnet_flood(s)) {
     killsock(dcc[i].sock);
     lostdcc(i);
     return;
@@ -1211,23 +1207,30 @@
   changeover_dcc(i, &DCC_IDENTWAIT, 0);
   dcc[i].timeval = now;
   dcc[i].u.ident_sock = dcc[idx].sock;
-  sock = open_telnet(iptostr(htonl(dcc[i].addr)), 113);
-  putlog(LOG_MISC, "*", DCC_TELCONN, dcc[i].host, dcc[i].port);
-  s[0] = 0;
-  if (sock < 0) {
-    if (sock == -2)
-      strcpy(s, "DNS lookup failed for ident");
-    else
-      neterror(s);
-  } else {
-    j = new_dcc(&DCC_IDENT, 0);
-    if (j < 0) {
-      killsock(sock);
-      strcpy(s, "No Free DCC's");
+  sock = -1;
+  j = new_dcc(&DCC_IDENT, 0);
+  if (j < 0)
+    putlog(LOG_MISC, "*", DCC_IDENTFAIL, dcc[i].host, strerror(errno));
+  else {
+    egg_memcpy(&dcc[j].sockname, &dcc[i].sockname, sizeof(sockname_t));
+    dcc[j].sock = getsock(dcc[j].sockname.family, 0);
+    if (dcc[j].sock >= 0) {
+      sockname_t name;
+      name.addrlen = sizeof(name.addr);
+      getsockname(dcc[i].sock, &name.addr.sa, &name.addrlen);
+      bind(dcc[j].sock, &name.addr.sa, name.addrlen);
+      setsnport(dcc[j].sockname, 113);
+      if (connect(dcc[j].sock, &dcc[j].sockname.addr.sa,
+          dcc[j].sockname.addrlen) < 0 && (errno != EINPROGRESS)) {
+        killsock(dcc[j].sock);
+        lostdcc(j);
+        putlog(LOG_MISC, "*", DCC_IDENTFAIL, dcc[i].host, strerror(errno));
+        j = 0;
+      }
+      sock = dcc[j].sock;
     }
   }
-  if (s[0]) {
-    putlog(LOG_MISC, "*", DCC_IDENTFAIL, dcc[i].host, s);
+  if (j < 0) {
     sprintf(s, "telnet@%s", dcc[i].host);
     dcc_telnet_got_ident(i, s);
     return;
Index: eggdrop1.8/src/dccutil.c
diff -u eggdrop1.8/src/dccutil.c:1.1.1.1 eggdrop1.8/src/dccutil.c:1.2
--- eggdrop1.8/src/dccutil.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/dccutil.c	Thu Aug  5 12:12:05 2010
@@ -6,7 +6,7 @@
  *   memory management for dcc structures
  *   timeout checking for dcc connections
  *
- * $Id: dccutil.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: dccutil.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -386,13 +386,11 @@
  */
 void tell_dcc(int zidx)
 {
-  int i, j;
+  int i, j, nicklen = 0;
   char other[160];
   char format[81];
-  int nicklen;
 
   /* calculate max nicklen */
-  nicklen = 0;
   for (i = 0; i < dcc_total; i++) {
     if (strlen(dcc[i].nick) > nicklen)
       nicklen = strlen(dcc[i].nick);
@@ -400,29 +398,31 @@
   if (nicklen < 9)
     nicklen = 9;
 
-  egg_snprintf(format, sizeof format, "%%-4s %%-8s %%-5s %%-%us %%-17s %%s\n",
-               nicklen);
-  dprintf(zidx, format, "SOCK", "ADDR", "PORT", "NICK", "HOST", "TYPE");
-  dprintf(zidx, format, "----", "--------", "-----", "---------",
-          "-----------------", "----");
+  j = 60 - nicklen;
+  if (j < 15)
+    j = 15;
+  if (j > 40)
+    j = 40;
+    
+  egg_snprintf(format, sizeof format, "%%-3s %%-%u.%us %%-5s %%-%u.%us %%s\n",
+               j, j, nicklen, nicklen);
+  dprintf(zidx, format, "IDX", "ADDR", "PORT", "NICK", "TYPE  INFO");
+  dprintf(zidx, format, "---",
+          "------------------------------------------------------", "-----",
+          "--------------------------------", "----- ---------");
+  egg_snprintf(format, sizeof format, "%%-3d %%-%u.%us %%5d %%-%u.%us %%s\n",
+               j, j, nicklen, nicklen);
 
-  egg_snprintf(format, sizeof format, "%%-4d %%08X %%5d %%-%us %%-17s %%s\n",
-               nicklen);
   /* Show server */
   for (i = 0; i < dcc_total; i++) {
-    j = strlen(dcc[i].host);
-    if (j > 17)
-      j -= 17;
-    else
-      j = 0;
     if (dcc[i].type && dcc[i].type->display)
       dcc[i].type->display(i, other);
     else {
       sprintf(other, "?:%lX  !! ERROR !!", (long) dcc[i].type);
       break;
     }
-    dprintf(zidx, format, dcc[i].sock, dcc[i].addr, dcc[i].port, dcc[i].nick,
-            dcc[i].host + j, other);
+      dprintf(zidx, format, dcc[i].sock, iptostr(&dcc[i].sockname.addr.sa), dcc[i].port,
+              dcc[i].nick, other);
   }
 }
 
Index: eggdrop1.8/src/dns.c
diff -u eggdrop1.8/src/dns.c:1.1.1.1 eggdrop1.8/src/dns.c:1.2
--- eggdrop1.8/src/dns.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/dns.c	Thu Aug  5 12:12:05 2010
@@ -4,7 +4,7 @@
  *   provides the code used by the bot if the DNS module is not loaded
  *   DNS Tcl commands
  *
- * $Id: dns.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: dns.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Written by Fabian Knittel <fknittel at gmx.de>
@@ -57,7 +57,7 @@
 void eof_dcc_dnswait(int idx)
 {
   putlog(LOG_MISC, "*", "Lost connection while resolving hostname [%s/%d]",
-         iptostr(htonl(dcc[idx].addr)), dcc[idx].port);
+         iptostr(&dcc[idx].sockname.addr.sa), dcc[idx].port);
   killsock(dcc[idx].sock);
   lostdcc(idx);
 }
@@ -116,14 +116,20 @@
 /* Walk through every dcc entry and look for waiting DNS requests
  * of RES_HOSTBYIP for our IP address.
  */
-static void dns_dcchostbyip(IP ip, char *hostn, int ok, void *other)
+static void dns_dcchostbyip(sockname_t *ip, char *hostn, int ok, void *other)
 {
   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)) {
+        (dcc[idx].u.dns->dns_type == RES_HOSTBYIP) && (
+#ifdef IPV6
+        (ip->family == AF_INET6 &&
+          IN6_ARE_ADDR_EQUAL(&dcc[idx].u.dns->ip->addr.s6.sin6_addr,
+                             &ip->addr.s6.sin6_addr)) ||
+#endif
+          (dcc[idx].u.dns->ip->addr.s4.sin_addr.s_addr ==
+                              ip->addr.s4.sin_addr.s_addr))) {
       if (dcc[idx].u.dns->host)
         nfree(dcc[idx].u.dns->host);
       dcc[idx].u.dns->host = get_data_ptr(strlen(hostn) + 1);
@@ -139,7 +145,7 @@
 /* Walk through every dcc entry and look for waiting DNS requests
  * of RES_IPBYHOST for our hostname.
  */
-static void dns_dccipbyhost(IP ip, char *hostn, int ok, void *other)
+static void dns_dccipbyhost(sockname_t *ip, char *hostn, int ok, void *other)
 {
   int idx;
 
@@ -147,10 +153,13 @@
     if ((dcc[idx].type == &DCC_DNSWAIT) &&
         (dcc[idx].u.dns->dns_type == RES_IPBYHOST) &&
         !egg_strcasecmp(dcc[idx].u.dns->host, hostn)) {
-      dcc[idx].u.dns->ip = ip;
-      if (ok)
+      if (ok) {
+        if (dcc[idx].u.dns->ip)
+          egg_memcpy(dcc[idx].u.dns->ip, ip, sizeof(sockname_t));
+        else
+          egg_memcpy(&dcc[idx].sockname, ip, sizeof(sockname_t));
         dcc[idx].u.dns->dns_success(idx);
-      else
+      } else
         dcc[idx].u.dns->dns_failure(idx);
     }
   }
@@ -203,7 +212,7 @@
   dns_ipbyhost(hostn);
 }
 
-void dcc_dnshostbyip(IP ip)
+void dcc_dnshostbyip(sockname_t *ip)
 {
   devent_t *de;
 
@@ -236,14 +245,14 @@
  *   Tcl events
  */
 
-static void dns_tcl_iporhostres(IP ip, char *hostn, int ok, void *other)
+static void dns_tcl_iporhostres(sockname_t *ip, char *hostn, int ok, void *other)
 {
   devent_tclinfo_t *tclinfo = (devent_tclinfo_t *) other;
   Tcl_DString list;
 
   Tcl_DStringInit(&list);
   Tcl_DStringAppendElement(&list, tclinfo->proc);
-  Tcl_DStringAppendElement(&list, iptostr(htonl(ip)));
+  Tcl_DStringAppendElement(&list, iptostr(&ip->addr.sa));
   Tcl_DStringAppendElement(&list, hostn);
   Tcl_DStringAppendElement(&list, ok ? "1" : "0");
 
@@ -328,7 +337,7 @@
   dns_ipbyhost(hostn);
 }
 
-static void tcl_dnshostbyip(IP ip, char *proc, char *paras)
+static void tcl_dnshostbyip(sockname_t *ip, char *proc, char *paras)
 {
   devent_t *de;
   devent_tclinfo_t *tclinfo;
@@ -348,6 +357,8 @@
   tclinfo = nmalloc(sizeof(devent_tclinfo_t));
   tclinfo->proc = nmalloc(strlen(proc) + 1);
   strcpy(tclinfo->proc, proc);
+  memcpy(&tclinfo->sockname, ip, sizeof(sockname_t));
+  de->res_data.ip_addr = &tclinfo->sockname;
   if (paras) {
     tclinfo->paras = nmalloc(strlen(paras) + 1);
     strcpy(tclinfo->paras, paras);
@@ -379,14 +390,21 @@
   return tot;
 }
 
-void call_hostbyip(IP ip, char *hostn, int ok)
+void call_hostbyip(sockname_t *ip, char *hostn, int ok)
 {
   devent_t *de = dns_events, *ode = NULL, *nde = NULL;
 
   while (de) {
     nde = de->next;
-    if ((de->lookup == RES_HOSTBYIP) &&
-        (!de->res_data.ip_addr || (de->res_data.ip_addr == ip))) {
+    if ((de->lookup == RES_HOSTBYIP) && (
+#ifdef IPV6
+        (ip->family == AF_INET6 &&
+          IN6_ARE_ADDR_EQUAL(&de->res_data.ip_addr->addr.s6.sin6_addr,
+                             &ip->addr.s6.sin6_addr)) ||
+#endif
+          (de->res_data.ip_addr->addr.s4.sin_addr.s_addr ==
+                              ip->addr.s4.sin_addr.s_addr))) {
+        /* A memcmp() could have perfectly done it .. */
       /* Remove the event from the list here, to avoid conflicts if one of
        * the event handlers re-adds another event. */
       if (ode)
@@ -407,7 +425,7 @@
   }
 }
 
-void call_ipbyhost(char *hostn, IP ip, int ok)
+void call_ipbyhost(char *hostn, sockname_t *ip, int ok)
 {
   devent_t *de = dns_events, *ode = NULL, *nde = NULL;
 
@@ -442,60 +460,50 @@
 /*
  *    Async DNS emulation functions
  */
-
-void block_dns_hostbyip(IP ip)
+void block_dns_hostbyip(sockname_t *addr)
 {
-  struct hostent *hp;
-  unsigned long addr = htonl(ip);
+  struct hostent *hp = 0;
   static char s[UHOSTLEN];
+  const char *r = 0;
 
-  if (!sigsetjmp(alarmret, 1)) {
-    alarm(resolve_timeout);
-    hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
-    alarm(0);
-    if (hp)
-      strncpyz(s, hp->h_name, sizeof s);
-    else
-      strcpy(s, iptostr(addr));
+  if (addr->family == AF_INET) {
+    if (!sigsetjmp(alarmret, 1)) {
+      alarm(resolve_timeout);
+      hp = gethostbyaddr(&addr->addr.s4.sin_addr,
+                         sizeof (struct in_addr), AF_INET);
+      alarm(0);
+    }
+    if (!hp)
+      r = inet_ntop(AF_INET, &addr->addr.s4.sin_addr.s_addr, s, sizeof s);
+#ifdef IPV6
   } else {
-    hp = NULL;
-    strcpy(s, iptostr(addr));
+    if (!sigsetjmp(alarmret, 1)) {
+      alarm(resolve_timeout);
+      hp = gethostbyaddr((char *) &addr->addr.s6.sin6_addr,
+                         sizeof (struct in6_addr), AF_INET6);
+      alarm(0);
+    }
+    if (!hp)
+      r = inet_ntop(AF_INET6, &addr->addr.s6.sin6_addr, s, sizeof s);
   }
-  /* Call hooks. */
-  call_hostbyip(ip, s, hp ? 1 : 0);
-}
+#else
+  }
+#endif
+  if (hp)
+    strncpyz(s, hp->h_name, sizeof s);
+  call_hostbyip(addr, s, hp ? 1 : 0);
+}    
 
 void block_dns_ipbyhost(char *host)
 {
-  struct in_addr inaddr;
+  sockname_t name;
 
-  /* Check if someone passed us an IP address as hostname
-   * and return it straight away */
-  if (egg_inet_aton(host, &inaddr)) {
-    call_ipbyhost(host, ntohl(inaddr.s_addr), 1);
-    return;
-  }
-  if (!sigsetjmp(alarmret, 1)) {
-    struct hostent *hp;
-    struct in_addr *in;
-    IP ip = 0;
-
-    alarm(resolve_timeout);
-    hp = gethostbyname(host);
-    alarm(0);
-
-    if (hp) {
-      in = (struct in_addr *) (hp->h_addr_list[0]);
-      ip = (IP) (in->s_addr);
-      call_ipbyhost(host, ntohl(ip), 1);
-      return;
-    }
-    /* Fall through. */
-  }
-  call_ipbyhost(host, 0, 0);
+  if (setsockname(&name, host, 0, 1) == AF_UNSPEC)
+    call_ipbyhost(host, &name, 0);
+  else
+    call_ipbyhost(host, &name, 1);
 }
 
-
 /*
  *   Misc functions
  */
@@ -513,7 +521,7 @@
 /* dnslookup <ip-address> <proc> */
 static int tcl_dnslookup STDVAR
 {
-  struct in_addr inaddr;
+  sockname_t addr;
   Tcl_DString paras;
 
   if (argc < 3) {
@@ -530,8 +538,8 @@
       Tcl_DStringAppendElement(&paras, argv[p]);
   }
 
-  if (egg_inet_aton(argv[1], &inaddr))
-    tcl_dnshostbyip(ntohl(inaddr.s_addr), argv[2], Tcl_DStringValue(&paras));
+  if (setsockname(&addr, argv[1], 0, 0) != AF_UNSPEC)
+    tcl_dnshostbyip(&addr, argv[2], Tcl_DStringValue(&paras));
   else
     tcl_dnsipbyhost(argv[1], argv[2], Tcl_DStringValue(&paras));
 
Index: eggdrop1.8/src/dns.h
diff -u eggdrop1.8/src/dns.h:1.1.1.1 eggdrop1.8/src/dns.h:1.2
--- eggdrop1.8/src/dns.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/dns.h	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * dns.h
  *   stuff used by dns.c
  *
- * $Id: dns.h,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: dns.h,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Written by Fabian Knittel <fknittel at gmx.de>
@@ -30,12 +30,13 @@
 typedef struct {
   char *name;
   int (*expmem) (void *);
-  void (*event) (IP, char *, int, void *);
+  void (*event) (sockname_t *, char *, int, void *);
 } devent_type;
 
 typedef struct {
   char *proc;                   /* Tcl proc                       */
   char *paras;                  /* Additional parameters          */
+  sockname_t sockname;
 } devent_tclinfo_t;
 
 typedef struct devent_str {
@@ -43,7 +44,7 @@
   devent_type *type;
   u_8bit_t lookup;              /* RES_IPBYHOST or RES_HOSTBYIP   */
   union {
-    IP ip_addr;                 /* IP address                     */
+    sockname_t *ip_addr;	/* Pointer to address placeholder */
     char *hostname;             /* Hostname                       */
   } res_data;
   void *other;                  /* Data specific to the event type */
Index: eggdrop1.8/src/eggdrop.h
diff -u eggdrop1.8/src/eggdrop.h:1.2 eggdrop1.8/src/eggdrop.h:1.3
--- eggdrop1.8/src/eggdrop.h:1.2	Tue Jul 27 15:49:41 2010
+++ eggdrop1.8/src/eggdrop.h	Thu Aug  5 12:12:05 2010
@@ -4,7 +4,7 @@
  *
  *   IF YOU ALTER THIS FILE, YOU NEED TO RECOMPILE THE BOT.
  *
- * $Id: eggdrop.h,v 1.2 2010/07/27 21:49:41 pseudo Exp $
+ * $Id: eggdrop.h,v 1.3 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -335,6 +335,25 @@
 typedef intptr_t (*Function) ();
 typedef int (*IntFunc) ();
 
+#ifdef IPV6
+#include "compat/in6.h"
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+typedef struct {
+  int family;
+  socklen_t addrlen;
+  union {
+    struct sockaddr sa;
+    struct sockaddr_in s4;
+#ifdef IPV6
+    struct sockaddr_in6 s6;
+#endif
+  } addr;
+} sockname_t;
+
 /* Public structure for the listening port map */
 struct portmap {
   int realport;
@@ -362,6 +381,7 @@
 struct dcc_t {
   long sock;                    /* This should be a long to keep 64-bit machines sane. */
   IP addr;                      /* IP address in host network byte order. */
+  sockname_t sockname;		/* IPv4/IPv6 sockaddr placeholder */ 
   unsigned int port;
   struct userrec *user;
   char nick[NICKLEN];
@@ -471,7 +491,7 @@
   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                              */
+  sockname_t *ip;		/* pointer to sockname with ipv4/6 address */
   int ibuf;                     /* temporary buffer for one integer        */
   char dns_type;                /* lookup type, e.g. RES_HOSTBYIP          */
   struct dcc_table *type;       /* type of the dcc table we are making the
Index: eggdrop1.8/src/main.c
diff -u eggdrop1.8/src/main.c:1.1.1.1 eggdrop1.8/src/main.c:1.2
--- eggdrop1.8/src/main.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/main.c	Thu Aug  5 12:12:05 2010
@@ -5,7 +5,7 @@
  *   command line arguments
  *   context and assert debugging
  *
- * $Id: main.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: main.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1115,7 +1115,7 @@
   if (!backgrd && term_z) {
     int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info));
 
-    dcc[n].addr = iptolong(getmyip());
+    getvhost(&dcc[n].sockname, AF_INET);
     dcc[n].sock = STDOUT;
     dcc[n].timeval = now;
     dcc[n].u.chat->con_flags = conmask;
Index: eggdrop1.8/src/main.h
diff -u eggdrop1.8/src/main.h:1.1.1.1 eggdrop1.8/src/main.h:1.2
--- eggdrop1.8/src/main.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/main.h	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * main.h
  *   include file to include most other include files
  *
- * $Id: main.h,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: main.h,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -133,6 +133,18 @@
 #endif
 
 #define iptolong(a) (0xffffffff & (long) (htonl((unsigned long) a)))
+
+#ifdef IPV6
+# define setsnport(s, p) do {                                           \
+  if ((s).family == AF_INET6)                                           \
+    (s).addr.s6.sin6_port = htons((p));                                 \
+  else                                                                  \
+    (s).addr.s4.sin_port = htons((p));                                  \
+} while (0)
+#else
+# define setsnport(s, p) (s.addr.s4.sin_port = htons(p))
+#endif
+
 #define fixcolon(x) do {                                                \
         if ((x)[0] == ':')                                              \
           (x)++;                                                        \
Index: eggdrop1.8/src/mod/channels.mod/cmdschan.c
diff -u eggdrop1.8/src/mod/channels.mod/cmdschan.c:1.1.1.1 eggdrop1.8/src/mod/channels.mod/cmdschan.c:1.2
--- eggdrop1.8/src/mod/channels.mod/cmdschan.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/channels.mod/cmdschan.c	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * cmdschan.c -- part of channels.mod
  *   commands from a user via dcc that cause server interaction
  *
- * $Id: cmdschan.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: cmdschan.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -109,15 +109,15 @@
       egg_snprintf(s, sizeof s, "%s@*", who);   /* brain-dead? */
     else
       strncpyz(s, who, sizeof s);
-    if ((me = module_find("server", 0, 0)) && me->funcs)
+    if ((me = module_find("server", 0, 0)) && me->funcs) {
       egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
                    me->funcs[SERVER_BOTUSERHOST]);
-    else
-      egg_snprintf(s1, sizeof s1, "%s!%s@%s", origbotname, botuser, hostname);
-    if (match_addr(s, s1)) {
-      dprintf(idx, "I'm not going to ban myself.\n");
-      putlog(LOG_CMDS, "*", "#%s# attempted +ban %s", dcc[idx].nick, s);
-    } else {
+      if (match_addr(s, s1)) {
+        dprintf(idx, "I'm not going to ban myself.\n");
+        putlog(LOG_CMDS, "*", "#%s# attempted +ban %s", dcc[idx].nick, s);
+        return;
+      }
+    }
       /* IRC can't understand bans longer than 70 characters */
       if (strlen(s) > 70) {
         s[69] = '*';
@@ -160,16 +160,14 @@
           for (chan = chanset; chan != NULL; chan = chan->next)
             (me->funcs[IRC_CHECK_THIS_BAN]) (chan, s, sticky);
       }
-    }
   }
 }
 
 static void cmd_pls_exempt(struct userrec *u, int idx, char *par)
 {
-  char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire;
+  char *chname, *who, s[UHOSTLEN], *p, *p_expire;
   unsigned long int expire_time = 0, expire_foo;
   struct chanset_t *chan = NULL;
-  module_entry *me;
 
   if (!use_exempts) {
     dprintf(idx, "This command can only be used with use-exempts enabled.\n");
@@ -247,11 +245,6 @@
       egg_snprintf(s, sizeof s, "%s@*", who);   /* brain-dead? */
     else
       strncpyz(s, who, sizeof s);
-    if ((me = module_find("server", 0, 0)) && me->funcs)
-      egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
-                   me->funcs[SERVER_BOTUSERHOST]);
-    else
-      egg_snprintf(s1, sizeof s1, "%s!%s@%s", origbotname, botuser, hostname);
 
     /* IRC can't understand exempts longer than 70 characters */
     if (strlen(s) > 70) {
@@ -293,10 +286,9 @@
 
 static void cmd_pls_invite(struct userrec *u, int idx, char *par)
 {
-  char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire;
+  char *chname, *who, s[UHOSTLEN], *p, *p_expire;
   unsigned long int expire_time = 0, expire_foo;
   struct chanset_t *chan = NULL;
-  module_entry *me;
 
   if (!use_invites) {
     dprintf(idx, "This command can only be used with use-invites enabled.\n");
@@ -375,11 +367,6 @@
       egg_snprintf(s, sizeof s, "%s@*", who);   /* brain-dead? */
     else
       strncpyz(s, who, sizeof s);
-    if ((me = module_find("server", 0, 0)) && me->funcs)
-      egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
-                   me->funcs[SERVER_BOTUSERHOST]);
-    else
-      egg_snprintf(s1, sizeof s1, "%s!%s@%s", origbotname, botuser, hostname);
 
     /* IRC can't understand invites longer than 70 characters */
     if (strlen(s) > 70) {
Index: eggdrop1.8/src/mod/channels.mod/userchan.c
diff -u eggdrop1.8/src/mod/channels.mod/userchan.c:1.1.1.1 eggdrop1.8/src/mod/channels.mod/userchan.c:1.2
--- eggdrop1.8/src/mod/channels.mod/userchan.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/channels.mod/userchan.c	Thu Aug  5 12:12:05 2010
@@ -1,7 +1,7 @@
 /*
  * userchan.c -- part of channels.mod
  *
- * $Id: userchan.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: userchan.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -423,14 +423,13 @@
     strcat(host, "!*");
     strcat(host, s);
   }
-  if ((me = module_find("server", 0, 0)) && me->funcs)
+  if ((me = module_find("server", 0, 0)) && me->funcs) {
     simple_sprintf(s, "%s!%s", me->funcs[SERVER_BOTNAME],
                    me->funcs[SERVER_BOTUSERHOST]);
-  else
-    simple_sprintf(s, "%s!%s@%s", origbotname, botuser, hostname);
-  if (match_addr(host, s)) {
-    putlog(LOG_MISC, "*", IRC_IBANNEDME);
-    return 0;
+    if (match_addr(host, s)) {
+      putlog(LOG_MISC, "*", IRC_IBANNEDME);
+      return 0;
+    }
   }
   if (expire_time == now)
     return 1;
@@ -495,7 +494,6 @@
 {
   char host[1024], s[1024];
   maskrec *p = NULL, *l, **u = chan ? &chan->invites : &global_invites;
-  module_entry *me;
 
   strcpy(host, invite);
   /* Choke check: fix broken invites (must have '!' and '@') */
@@ -511,11 +509,6 @@
     strcat(host, "!*");
     strcat(host, s);
   }
-  if ((me = module_find("server", 0, 0)) && me->funcs)
-    simple_sprintf(s, "%s!%s", me->funcs[SERVER_BOTNAME],
-                   me->funcs[SERVER_BOTUSERHOST]);
-  else
-    simple_sprintf(s, "%s!%s@%s", origbotname, botuser, hostname);
 
   for (l = *u; l; l = l->next)
     if (!rfc_casecmp(l->mask, host)) {
@@ -577,7 +570,6 @@
 {
   char host[1024], s[1024];
   maskrec *p = NULL, *l, **u = chan ? &chan->exempts : &global_exempts;
-  module_entry *me;
 
   strcpy(host, exempt);
   /* Choke check: fix broken exempts (must have '!' and '@') */
@@ -593,11 +585,6 @@
     strcat(host, "!*");
     strcat(host, s);
   }
-  if ((me = module_find("server", 0, 0)) && me->funcs)
-    simple_sprintf(s, "%s!%s", me->funcs[SERVER_BOTNAME],
-                   me->funcs[SERVER_BOTUSERHOST]);
-  else
-    simple_sprintf(s, "%s!%s@%s", origbotname, botuser, hostname);
 
   for (l = *u; l; l = l->next)
     if (!rfc_casecmp(l->mask, host)) {
Index: eggdrop1.8/src/mod/ctcp.mod/ctcp.c
diff -u eggdrop1.8/src/mod/ctcp.mod/ctcp.c:1.2 eggdrop1.8/src/mod/ctcp.mod/ctcp.c:1.3
--- eggdrop1.8/src/mod/ctcp.mod/ctcp.c:1.2	Tue Jul 27 15:49:42 2010
+++ eggdrop1.8/src/mod/ctcp.mod/ctcp.c	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * ctcp.c -- part of ctcp.mod
  *   all the ctcp handling (except DCC, it's special ;)
  *
- * $Id: ctcp.c,v 1.2 2010/07/27 21:49:42 pseudo Exp $
+ * $Id: ctcp.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -145,6 +145,7 @@
 {
   struct userrec *u = get_user_by_handle(userlist, handle);
   int atr = u ? u->flags : 0, i;
+  char s[INET6_ADDRSTRLEN];
 
   if ((atr & (USER_PARTY | USER_XFER)) || ((atr & USER_OP) && !require_p)) {
 
@@ -157,13 +158,13 @@
     for (i = 0; i < dcc_total; i++) {
       if ((dcc[i].type->flags & DCT_LISTEN) &&
           (!strcmp(dcc[i].nick, "(telnet)") ||
-           !strcmp(dcc[i].nick, "(users)"))) {
+           !strcmp(dcc[i].nick, "(users)")) &&
+          getdccaddr(&dcc[i].sockname, s, sizeof s)) {
         /* Do me a favour and don't change this back to a CTCP reply,
          * CTCP replies are NOTICE's this has to be a PRIVMSG
          * -poptix 5/1/1997 */
-        dprintf(DP_SERVER, "PRIVMSG %s :\001DCC CHAT chat %lu %u\001\n",
-                nick, iptolong(natip[0] ? (IP) inet_addr(natip) : getmyip()),
-                dcc[i].port);
+          dprintf(DP_SERVER, "PRIVMSG %s :\001DCC CHAT chat %s %u\001\n",
+                  nick, s, dcc[i].port);
         return 1;
       }
     }
Index: eggdrop1.8/src/mod/dns.mod/coredns.c
diff -u eggdrop1.8/src/mod/dns.mod/coredns.c:1.1.1.1 eggdrop1.8/src/mod/dns.mod/coredns.c:1.2
--- eggdrop1.8/src/mod/dns.mod/coredns.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/dns.mod/coredns.c	Thu Aug  5 12:12:05 2010
@@ -1,11 +1,12 @@
 /*
- * dnscore.c -- part of dns.mod
+ * coredns.c -- part of dns.mod
  *   This file contains all core functions needed for the eggdrop dns module.
  *   Many of them are only minimaly modified from the original source.
  *
  * Modified/written by Fabian Knittel <fknittel at gmx.de>
+ * IPv6 support added by pseudo <pseudo at egg6.net>
  *
- * $Id: coredns.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: coredns.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Portions Copyright (C) 1999 - 2010 Eggheads Development Team
@@ -77,10 +78,12 @@
   "refused by name server",
   "unknown error",
 };
-#endif /* DEBUG_DNS */
 
-#ifdef DEBUG_DNS
-#  define RESOURCETYPES_COUNT 17
+#  ifdef IPV6
+#    define RESOURCETYPES_COUNT 29
+#  else
+#    define RESOURCETYPES_COUNT 17
+#  endif
 static const char *resourcetypes[RESOURCETYPES_COUNT + 1] = {
   "unknown type",
   "A: host address",
@@ -99,20 +102,33 @@
   "MINFO: mailbox or mail list information",
   "MX: mail exchange",
   "TXT: text string",
+#  ifdef IPV6
+  "RP: responsible person",
+  "AFSDB: AFS cell database",
+  "X25: X_25 calling address",
+  "ISDN: ISDN calling address",
+  "RT: router",
+  "NSAP: NSAP address",
+  "NSAP_PTR: reverse NSAP lookup (deprecated)",
+  "SIG: security signature",
+  "KEY: security key",
+  "PX: X.400 mail mapping",
+  "GPOS: geographical position (withdrawn)",
+  "AAAA: IP6 Address",
+#  endif /* IPV6 */
   "unknown type",
 };
-#endif /* DEBUG_DNS */
 
-#ifdef DEBUG_DNS
 #  define CLASSTYPES_COUNT 5
 static const char *classtypes[CLASSTYPES_COUNT + 1] = {
   "unknown class",
   "IN: the Internet",
   "CS: CSNET (OBSOLETE)",
   "CH: CHAOS",
-  "HS: Hesoid [Dyer 87]",
+  "HS: Hesiod [Dyer 87]",
   "unknown class"
 };
+
 #endif /* DEBUG_DNS */
 
 typedef struct {
@@ -136,6 +152,14 @@
   u_16bit_t arcount;            /* Resource reference record count */
 } packetheader;
 
+typedef struct {
+  u_16bit_t datatype;
+  u_16bit_t class;
+  u_32bit_t ttl;
+  u_16bit_t datalength;
+  u_8bit_t data[];
+} res_record;
+
 #ifndef HFIXEDSZ
 #define HFIXEDSZ (sizeof(packetheader))
 #endif
@@ -159,11 +183,13 @@
 #define sucknetlong(x)  ((x)+=4,((long)  (((x)[-4] << 24) | ((x)[-3] << 16) | \
                                           ((x)[-2] <<  8) | ((x)[-1] <<  0))))
 
-
 static u_32bit_t resrecvbuf[(MAX_PACKETSIZE + 7) >> 2]; /* MUST BE DWORD ALIGNED */
 
 static struct resolve *idbash[BASH_SIZE];
 static struct resolve *ipbash[BASH_SIZE];
+#ifdef IPV6
+static struct resolve *ip6bash[BASH_SIZE];
+#endif
 static struct resolve *hostbash[BASH_SIZE];
 static struct resolve *expireresolves = NULL;
 
@@ -232,7 +258,6 @@
   return rp;
 }
 
-
 /*
  *    Hash and linked-list related functions
  */
@@ -251,6 +276,15 @@
   return (u_32bit_t) BASH_MODULO(ip);
 }
 
+#ifdef IPV6
+static unsigned long getip6bash(struct in6_addr *ip6) {
+  u_int32_t x;
+  egg_memcpy(&x, &ip6->s6_addr, sizeof x);
+  x ^= *(u_int32_t *)&ip6->s6_addr[12];
+  return (unsigned long) BASH_MODULO(x);
+}
+#endif
+
 /* Return the hash bucket number for host.
  */
 static u_32bit_t gethostbash(char *host)
@@ -406,6 +440,58 @@
   ipbash[bashnum] = addrp;
 }
 
+#ifdef IPV6
+static void linkresolveip6(struct resolve *addrp){
+  struct resolve *rp;
+  unsigned long bashnum;
+  bashnum = getip6bash(&addrp->sockname.addr.s6.sin6_addr);
+  rp = ip6bash[bashnum];
+  if (rp){
+    while ((rp->nextip) &&
+           (addrp->sockname.addr.s6.sin6_addr.s6_addr[15] >
+            rp->nextip->sockname.addr.s6.sin6_addr.s6_addr[15]))
+      rp = rp->nextip;
+    while ((rp->previousip) &&
+           (addrp->sockname.addr.s6.sin6_addr.s6_addr[15] <
+            rp->previousip->sockname.addr.s6.sin6_addr.s6_addr[15]))
+      rp = rp->previousip;
+    if (rp->sockname.addr.s6.sin6_addr.s6_addr[15] <
+        addrp->sockname.addr.s6.sin6_addr.s6_addr[15]) {
+      addrp->previousip = rp;
+      addrp->nextip = rp->nextip;
+      if (rp->nextip)
+        rp->nextip->previousip = addrp;
+      rp->nextip = addrp;
+    } else {
+      addrp->previousip = rp->previousip;
+      addrp->nextip = rp;
+      if (rp->previousip)
+        rp->previousip->nextip = addrp;
+      rp->previousip = addrp;
+    }
+  } else
+    addrp->nextip = addrp->previousip = NULL;
+  ip6bash[bashnum] = addrp;
+}
+
+static void unlinkresolveip6(struct resolve *rp)
+{
+  u_32bit_t bashnum;
+
+  bashnum = getip6bash(&rp->sockname.addr.s6.sin6_addr);
+  if (ip6bash[bashnum] == rp) {
+    if (rp->previousip)
+      ip6bash[bashnum] = rp->previousip;
+    else
+      ip6bash[bashnum] = rp->nextip;
+  }
+  if (rp->nextip)
+    rp->nextip->previousip = rp->previousip;
+  if (rp->previousip)
+    rp->previousip->nextip = rp->nextip;
+}
+#endif
+
 /* Remove request structure rp from the ip hash table.
  */
 static void unlinkresolveip(struct resolve *rp)
@@ -477,6 +563,11 @@
   untieresolve(rp);             /* Not really needed. Left in to be on the
                                  * safe side. */
   unlinkresolveid(rp);
+#ifdef IPV6
+  if (rp->sockname.family == AF_INET6)
+    unlinkresolveip6(rp);
+  else
+#endif
   unlinkresolveip(rp);
   if (rp->hostn)
     unlinkresolvehost(rp);
@@ -534,11 +625,33 @@
 
 /* Find request structure using the ip.
  */
+#ifdef IPV6
+static struct resolve *findip6(struct in6_addr *ip6)
+{
+  struct resolve *rp;
+  unsigned long bashnum;
+  bashnum = getip6bash(ip6);
+  rp = ip6bash[bashnum];
+  if (rp){
+    while ((rp->nextip) && (ip6->s6_addr[15] >=
+           (rp->nextip->sockname.addr.s6.sin6_addr.s6_addr[15])))
+      rp = rp->nextip;
+    while ((rp->previousip) && (ip6->s6_addr[15] <=
+           (rp->previousip->sockname.addr.s6.sin6_addr.s6_addr[15])))
+      rp = rp->previousip;
+    if (IN6_ARE_ADDR_EQUAL(ip6, &rp->sockname.addr.s6.sin6_addr)) {
+      ip6bash[bashnum] = rp;
+      return rp;
+    } else return NULL;
+  }
+  return rp; /* NULL */
+}
+#endif
+
 static struct resolve *findip(IP ip)
 {
   struct resolve *rp;
   u_32bit_t bashnum;
-
   bashnum = getipbash(ip);
   rp = ipbash[bashnum];
   if (rp) {
@@ -555,6 +668,47 @@
   return rp;                    /* NULL */
 }
 
+void ptrstring4(IP *ip, char *buf, size_t sz)
+{
+  snprintf(buf, sz, "%u.%u.%u.%u.in-addr.arpa",
+           ((u_8bit_t *) ip)[3],
+           ((u_8bit_t *) ip)[2],
+           ((u_8bit_t *) ip)[1],
+           ((u_8bit_t *) ip)[0]);
+}
+
+#ifdef IPV6
+void ptrstring6(struct in6_addr *ip6, char *buf, size_t sz)
+{
+  int i;
+  char *p, *q;
+  const char *hex = "0123456789abcdef";
+
+  p = buf;
+  q = buf + sz;
+  for (i = sizeof(struct in6_addr) - 1; i >= 0 && p < q; i--) {
+     *p++ = hex[ip6->s6_addr[i] & 0x0f];
+     *p++ = '.';
+     *p++ = hex[(ip6->s6_addr[i] >> 4) & 0x0f];
+     *p++ = '.';
+     *p = '\0';
+  }
+  strcpy(p, "ip6.arpa"); /* ip6.int is deprecated */
+}
+#endif
+
+void ptrstring(struct sockaddr *addr, char *buf, size_t sz)
+{
+  if (addr->sa_family == AF_INET)
+    ptrstring4((IP *) &((struct sockaddr_in *)addr)->sin_addr.s_addr,
+               buf, sz);
+#ifdef IPV6
+  else if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)addr)->sin6_addr))
+    ptrstring4((IP *) &((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr[12],
+               buf, sz);
+  else ptrstring6(&((struct sockaddr_in6 *)addr)->sin6_addr, buf, sz);
+#endif
+}
 
 /*
  *    Network and resolver related functions
@@ -600,15 +754,16 @@
   linkresolve(rp);
 
   if (type == T_A) {
+#ifdef IPV6
+    dorequest(rp->hostn, T_AAAA, rp->id);
+#endif
     dorequest(rp->hostn, type, rp->id);
     ddebug1(RES_MSG "Sent domain lookup request for \"%s\".", rp->hostn);
   } else if (type == T_PTR) {
-    sprintf(tempstring, "%u.%u.%u.%u.in-addr.arpa",
-            ((u_8bit_t *) & rp->ip)[3],
-            ((u_8bit_t *) & rp->ip)[2],
-            ((u_8bit_t *) & rp->ip)[1], ((u_8bit_t *) & rp->ip)[0]);
+    ptrstring(&rp->sockname.addr.sa, tempstring, sizeof tempstring);
     dorequest(tempstring, type, rp->id);
-    ddebug1(RES_MSG "Sent domain lookup request for \"%s\".", iptostr(rp->ip));
+    ddebug1(RES_MSG "Sent domain lookup request for \"%s\".",
+            iptostr(&rp->sockname.addr.sa));
   }
 }
 
@@ -628,8 +783,7 @@
 }
 
 /* Gets called as soon as the request turns out to have failed. Calls
- * the eggdrop hook.
- */
+ * the eggdrop hook */
 static void failrp(struct resolve *rp, int type)
 {
   if (rp->state == STATE_FINISHED)
@@ -668,258 +822,260 @@
 
 /* Parses the response packets received.
  */
-static void parserespacket(u_8bit_t *s, int l)
+void parserespacket(u_8bit_t *response, int len)
 {
+#ifdef IPV6
+  int ready = 0;
+#endif
+  int r, rcount;
+  res_record *rr;
+  packetheader *hdr;
   struct resolve *rp;
-  packetheader *hp;
-  u_8bit_t *eob;
-  u_8bit_t *c;
-  long ttl;
-  int r, usefulanswer;
-  u_16bit_t rr, datatype, class, qdatatype, qclass;
-  u_8bit_t rdatalength;
-
-  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.");
+  u_8bit_t rc, *c = response;
+  u_16bit_t qdatatype, qclass;
+  if (len < sizeof(packetheader)) {
+    debug1(RES_ERR "Packet smaller than standard header size: %d bytes.", len);
     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))
+  hdr = ((packetheader *) response);
+  rp = findid(hdr->id);
+  if (!rp || (rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED))
     return;
-  hp->qdcount = ntohs(hp->qdcount);
-  hp->ancount = ntohs(hp->ancount);
-  hp->nscount = ntohs(hp->nscount);
-  hp->arcount = ntohs(hp->arcount);
-  if (getheader_tc(hp)) {       /* Packet truncated */
+  if (getheader_tc(hdr)) {
     ddebug0(RES_ERR "Nameserver packet truncated.");
     return;
   }
-  if (!getheader_qr(hp)) {      /* Not a reply */
+  if (!getheader_qr(hdr)) {
     ddebug0(RES_ERR "Query packet received on nameserver communication "
             "socket.");
     return;
   }
-  if (getheader_opcode(hp)) {   /* Not opcode 0 (standard query) */
+  if (getheader_opcode(hdr)) {
     ddebug0(RES_ERR "Invalid opcode in response packet.");
     return;
   }
-  eob = s + l;
-  c = s + HFIXEDSZ;
-  switch (getheader_rcode(hp)) {
-  case NOERROR:
-    if (hp->ancount) {
-      ddebug4(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) {
-        ddebug0(RES_ERR "Reply does not contain one query.");
-        return;
-      }
-      if (c > eob) {
-        ddebug0(RES_ERR "Reply too short.");
+  rc = getheader_rcode(hdr);
+  switch (rc) {
+    case NOERROR:
+      break;
+    case NXDOMAIN:
+      ddebug0(RES_MSG "Domain does not exist.");
+      failrp(rp, IS_A(rp) ? T_A : T_PTR);
+      return;
+    default:
+      ddebug2(RES_ERR "Received error response %u. (%s)",
+              rc, rc < RESPONSECODES_COUNT ?
+              responsecodes[rc] : responsecodes[RESPONSECODES_COUNT]);
+      return;
+  }
+  hdr->qdcount = ntohs(hdr->qdcount);
+  hdr->ancount = ntohs(hdr->ancount);
+  hdr->nscount = ntohs(hdr->nscount);
+  hdr->arcount = ntohs(hdr->arcount);
+  ddebug4(RES_MSG "Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)",
+          hdr->qdcount, hdr->ancount, hdr->nscount, hdr->arcount);
+  if (hdr->qdcount != 1) {
+    ddebug0(RES_ERR "Reply does not contain one query.");
+    return;
+  }
+  switch (rp->state) {
+    case STATE_PTRREQ:
+      if (!hdr->ancount) {
+        ddebug0(RES_ERR "No error returned but no answers given.");
         return;
       }
-      switch (rp->state) {      /* Construct expected query reply */
-      case STATE_PTRREQ:
-        sprintf(stackstring,
-                "%u.%u.%u.%u.in-addr.arpa",
-                ((u_8bit_t *) & rp->ip)[3],
-                ((u_8bit_t *) & rp->ip)[2],
-                ((u_8bit_t *) & rp->ip)[1], ((u_8bit_t *) & 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) {
-        ddebug0(RES_ERR "dn_expand() failed while expanding query domain.");
+      ptrstring(&rp->sockname.addr.sa, stackstring, sizeof stackstring);
+      break;
+    case STATE_AREQ:
+      strncpy(stackstring, rp->hostn, 1024);
+  }
+  c = response + HFIXEDSZ;
+  r = dn_expand(response, response + len, c, namestring, MAXDNAME);
+  if (r == -1) {
+    ddebug0(RES_ERR "dn_expand() failed while expanding query domain.");
+    return;
+  }
+  if (egg_strcasecmp(stackstring, namestring)) {
+    ddebug2(RES_MSG "Unknown query packet dropped. (\"%s\" does not "
+            "match \"%s\")", stackstring, namestring);
+    return;
+  }
+  c += r;
+  if (c + 4 > response + len) {
+    ddebug0(RES_ERR "Query resource record truncated.");
+    return;
+  }
+  qdatatype = sucknetword(c);
+  qclass = sucknetword(c);
+  if (qclass != C_IN) {
+    ddebug2(RES_ERR "Received unsupported query class: %u (%s)",
+            qclass, (qclass < CLASSTYPES_COUNT) ?
+            classtypes[qclass] : classtypes[CLASSTYPES_COUNT]);
+    return;
+  }
+  switch (qdatatype) {
+    case T_A:
+      if (!IS_A(rp)) {
+        ddebug0(RES_WRN "Ignoring response with unexpected query type \"A\".");
         return;
       }
-      namestring[strlen(stackstring)] = '\0';
-      if (egg_strcasecmp(stackstring, namestring)) {
-        ddebug2(RES_MSG "Unknown query packet dropped. (\"%s\" does not "
-                "match \"%s\")", stackstring, namestring);
+      rp->sockname.family = AF_INET;
+#ifndef IPV6
+      break;
+#else
+      if (rp->sockname.family == AF_INET6)
+        ready = 1;
+      break;
+    case T_AAAA:
+      if (!IS_A(rp)) {
+        ddebug0(RES_WRN "Ignoring response with unexpected query type "
+                "\"AAAA\".");
         return;
       }
-      ddebug1(RES_MSG "Queried domain name: \"%s\"", namestring);
-      c += r;
-      if (c + 4 > eob) {
-        ddebug0(RES_ERR "Query resource record truncated.");
+      if (rp->sockname.family == AF_INET)
+        ready = 1;
+      rp->sockname.family = AF_INET6;
+      break;
+#endif
+    case T_PTR:
+      if (!IS_PTR(rp)) {
+        ddebug0(RES_WRN "Ignoring response with unexpected query type "
+                "\"PTR\".");
         return;
       }
-      qdatatype = sucknetword(c);
-      qclass = sucknetword(c);
-      if (qclass != C_IN) {
-        ddebug2(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)) {
-          ddebug0(RES_WRN "Ignoring response with unexpected query type "
-                  "\"PTR\".");
+      break;
+    default:
+      ddebug2(RES_ERR "Received unimplemented query type: %u (%s)",
+              qdatatype, (qdatatype < RESOURCETYPES_COUNT) ?
+              resourcetypes[qdatatype] : resourcetypes[RESOURCETYPES_COUNT]);
+      return;
+  }
+  for (rcount = hdr->ancount + hdr->nscount + hdr->arcount; rcount; rcount--) {
+    r = dn_expand(response, response + len, c, namestring, MAXDNAME);
+    if (r == -1) {
+      ddebug0(RES_ERR "dn_expand() failed while expanding answer domain.");
+      return;
+    }    
+    ddebug1(RES_MSG "answered domain query: \"%s\"", namestring);
+    c += r;
+    if (c + 10 > response + len) {
+      ddebug0(RES_ERR "Resource record truncated.");
+      return;
+    }
+    rr = ((res_record *) c);
+    rr->datatype = ntohs(rr->datatype);
+    rr->class = ntohs(rr->class);
+    rr->ttl = ntohl(rr->ttl);
+    rr->datalength = ntohs(rr->datalength);
+    if (rr->class != qclass) {
+      ddebug2(RES_ERR "Answered class (%s) does not match queried class (%s).",
+              (rr->class < CLASSTYPES_COUNT) ?
+              classtypes[rr->class] : classtypes[CLASSTYPES_COUNT],
+              (qclass < CLASSTYPES_COUNT) ?
+              classtypes[qclass] : classtypes[CLASSTYPES_COUNT]);
+      return;
+    }
+    c += 10 + rr->datalength;
+    if (0 > response + len) {
+      ddebug0(RES_ERR "Specified rdata length exceeds packet size.");
+      return;
+    }
+    if (egg_strcasecmp(stackstring, namestring))
+      continue;
+    if (rr->datatype != qdatatype && rr->datatype != T_CNAME) {
+      ddebug2(RES_MSG "Ignoring resource type %u. (%s)",
+              rr->datatype, (rr->datatype < RESOURCETYPES_COUNT) ?
+              resourcetypes[rr->datatype] :
+              resourcetypes[RESOURCETYPES_COUNT]);
+      continue;
+    }
+    ddebug1(RES_MSG "TTL: %s", strtdiff(sendstring, rr->ttl));
+    ddebug1(RES_MSG "TYPE: %s", (rr->datatype < RESOURCETYPES_COUNT) ?
+            resourcetypes[rr->datatype] : resourcetypes[RESOURCETYPES_COUNT]);
+    switch (rr->datatype) {
+      case T_A:
+        if (rr->datalength != 4) {
+          ddebug1(RES_ERR "Unsupported rdata format for \"A\" type. "
+                  "(%u bytes)", rr->datalength);
           return;
         }
-        break;
-      case T_A:
-        if (!IS_A(rp)) {
-          ddebug0(RES_WRN "Ignoring response with unexpected query type "
-                  "\"PTR\".");
+        rp->ttl = rr->ttl;
+        rp->sockname.addrlen = sizeof(struct sockaddr_in);
+        rp->sockname.addr.sa.sa_family = AF_INET;
+        egg_memcpy(&rp->sockname.addr.s4.sin_addr, rr->data, 4);
+#ifndef IPV6
+        passrp(rp, rr->ttl, T_A);
+        return;
+#else
+        if (ready || !pref_af) {
+          passrp(rp, rr->ttl, T_A);
           return;
         }
         break;
-      default:
-        ddebug2(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--) {
-        if (c > eob) {
-          ddebug0(RES_ERR "Packet does not contain all specified resouce "
-                  "records.");
+      case T_AAAA:
+        if (rr->datalength != 16) {
+          ddebug1(RES_ERR "Unsupported rdata format for \"AAAA\" type. "
+                  "(%u bytes)", rr->datalength);
           return;
         }
-        *namestring = '\0';
-        r = dn_expand(s, s + l, c, namestring, MAXDNAME);
-        if (r == -1) {
-          ddebug0(RES_ERR "dn_expand() failed while expanding answer domain.");
+        rp->ttl = rr->ttl;
+        rp->sockname.addrlen = sizeof(struct sockaddr_in6);
+        rp->sockname.addr.sa.sa_family = AF_INET6;
+        egg_memcpy(&rp->sockname.addr.s6.sin6_addr, rr->data, 16);
+        if (ready || pref_af) {
+          passrp(rp, rr->ttl, T_A); 
           return;
         }
-        namestring[strlen(stackstring)] = '\0';
-        if (egg_strcasecmp(stackstring, namestring))
-          usefulanswer = 0;
-        else
-          usefulanswer = 1;
-        ddebug1(RES_MSG "answered domain query: \"%s\"", namestring);
-        c += r;
-        if (c + 10 > eob) {
-          ddebug0(RES_ERR "Resource record truncated.");
+        break;
+#endif
+      case T_PTR:
+        r = dn_expand(response, response + len, rr->data, namestring, MAXDNAME);
+        if (r == -1) {
+          ddebug0(RES_ERR "dn_expand() failed while expanding domain in "
+                  "rdata.");
           return;
         }
-        datatype = sucknetword(c);
-        class = sucknetword(c);
-        ttl = sucknetlong(c);
-        rdatalength = sucknetword(c);
-        if (class != qclass) {
-          ddebug2(RES_MSG "query class: %u (%s)",
-                  qclass, (qclass < CLASSTYPES_COUNT) ?
-                  classtypes[qclass] : classtypes[CLASSTYPES_COUNT]);
-          ddebug2(RES_MSG "rr class: %u (%s)", class,
-                  (class < CLASSTYPES_COUNT) ?
-                  classtypes[class] : classtypes[CLASSTYPES_COUNT]);
-          ddebug0(RES_ERR "Answered class does not match queried class.");
+        ddebug1(RES_MSG "Answered domain: \"%s\"", namestring);
+        if (r > HOSTNAMELEN) {
+          ddebug0(RES_ERR "Domain name too long.");
+          failrp(rp, T_PTR);
           return;
         }
-        if (!rdatalength) {
-          ddebug0(RES_ERR "Zero size rdata.");
+        if (!rp->hostn) {
+          rp->hostn = nmalloc(strlen(namestring) + 1);
+          strcpy(rp->hostn, namestring);
+          linkresolvehost(rp);
+          passrp(rp, rr->ttl, T_PTR);
           return;
         }
-        if (c + rdatalength > eob) {
-          ddebug0(RES_ERR "Specified rdata length exceeds packet size.");
+        break;
+      case T_CNAME:
+        r = dn_expand(response, response + len, rr->data, namestring, MAXDNAME);
+        if (r == -1) {
+          ddebug0(RES_ERR "dn_expand() failed while expanding domain in "
+                  "rdata.");
           return;
         }
-        if (datatype == qdatatype) {
-          ddebug1(RES_MSG "TTL: %s", strtdiff(sendstring, ttl));
-          ddebug1(RES_MSG "TYPE: %s", (datatype < RESOURCETYPES_COUNT) ?
-                  resourcetypes[datatype] :
-                  resourcetypes[RESOURCETYPES_COUNT]);
-          if (usefulanswer)
-            switch (datatype) {
-            case T_A:
-              if (rdatalength != 4) {
-                ddebug1(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) {
-                ddebug0(RES_ERR "dn_expand() failed while expanding domain in "
-                        "rdata.");
-                return;
-              }
-              ddebug1(RES_MSG "Answered domain: \"%s\"", namestring);
-              if (r > HOSTNAMELEN) {
-                ddebug0(RES_ERR "Domain name too long.");
-                failrp(rp, T_PTR);
-                return;
-              }
-              if (!rp->hostn) {
-                rp->hostn = nmalloc(strlen(namestring) + 1);
-                strcpy(rp->hostn, namestring);
-                linkresolvehost(rp);
-                passrp(rp, ttl, T_PTR);
-                return;
-              }
-              break;
-            default:
-              ddebug2(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) {
-            ddebug0(RES_ERR "dn_expand() failed while expanding domain in "
-                    "rdata.");
-            return;
-          }
-          ddebug1(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 {
-          ddebug2(RES_MSG "Ignoring resource type %u. (%s)",
-                  datatype, (datatype < RESOURCETYPES_COUNT) ?
-                  resourcetypes[datatype] :
-                  resourcetypes[RESOURCETYPES_COUNT]);
-        }
-        c += rdatalength;
-      }
-    } else
-      ddebug0(RES_ERR "No error returned but no answers given.");
-    break;
-  case NXDOMAIN:
-    ddebug0(RES_MSG "Host not found.");
-    switch (rp->state) {
-    case STATE_PTRREQ:
-      failrp(rp, T_PTR);
-      break;
-    case STATE_AREQ:
-      failrp(rp, T_A);
-      break;
-    default:
-      failrp(rp, 0);
-      break;
+        ddebug1(RES_MSG "answered domain is CNAME for: %s", namestring);
+        strncpy(stackstring, namestring, 1024);
+        break;
+      default:
+        ddebug2(RES_ERR "Received unimplemented data type: %u (%s)",
+                rr->datatype, (rr->datatype < RESOURCETYPES_COUNT) ?
+                resourcetypes[rr->datatype] :
+                resourcetypes[RESOURCETYPES_COUNT]);
     }
-    break;
-  default:
-    ddebug2(RES_MSG "Received error response %u. (%s)",
-            getheader_rcode(hp), (getheader_rcode(hp) < RESPONSECODES_COUNT) ?
-            responsecodes[getheader_rcode(hp)] :
-            responsecodes[RESPONSECODES_COUNT]);
+  }
+#ifdef IPV6
+  if (IS_A(rp) && ready) {
+#else
+  if (IS_A(rp)) {
+#endif
+    rp->sockname.family = rp->sockname.addr.sa.sa_family;
+    if (rp->sockname.addrlen)
+      passrp(rp, rp->ttl, T_A);
+    else
+      failrp(rp, T_A);
   }
 }
 
@@ -950,10 +1106,10 @@
       if (_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr)
         break;
   }
-  if (i == _res.nscount) {
+  if (i == _res.nscount)
     ddebug1(RES_ERR "Received reply from unknown source: %s",
-            iptostr(from.sin_addr.s_addr));
-  } else
+                iptostr((struct sockaddr *) &from));
+  else
     parserespacket((u_8bit_t *) resrecvbuf, r);
 }
 
@@ -970,9 +1126,9 @@
     switch (rp->state) {
     case STATE_FINISHED:       /* TTL has expired */
     case STATE_FAILED:         /* Fake TTL has expired */
-      ddebug4(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);
+      ddebug4(RES_MSG "Cache record for \"%s\" (%s) has expired. (state: %u) "
+              "Marked for expire at: %ld.", nonull(rp->hostn),
+              iptostr(&rp->sockname.addr.sa), rp->state, rp->expiretime);
       unlinkresolve(rp);
       break;
     case STATE_PTRREQ:         /* T_PTR send timed out */
@@ -1002,31 +1158,45 @@
 
 /* Start searching for a host-name, using it's ip-address.
  */
-static void dns_lookup(IP ip)
+static void dns_lookup(sockname_t *addr)
 {
-  struct resolve *rp;
+  struct resolve *rp = NULL;
 
-  ip = htonl(ip);
-  if ((rp = findip(ip))) {
+  if (addr->family == AF_INET)
+    rp = findip((IP)addr->addr.s4.sin_addr.s_addr);
+#ifdef IPV6
+  else
+    rp = findip6(&addr->addr.s6.sin6_addr);
+#endif
+  if (rp) {
     if (rp->state == STATE_FINISHED || rp->state == STATE_FAILED) {
       if (rp->state == STATE_FINISHED && rp->hostn) {
         ddebug2(RES_MSG "Used cached record: %s == \"%s\".",
-                iptostr(ip), rp->hostn);
+                iptostr(&addr->addr.sa), rp->hostn);
         dns_event_success(rp, T_PTR);
       } else {
-        ddebug1(RES_MSG "Used failed record: %s == ???", iptostr(ip));
+        ddebug1(RES_MSG "Used failed record: %s == ???",
+                iptostr(&addr->addr.sa));
         dns_event_failure(rp, T_PTR);
       }
     }
     return;
   }
-
+  
   ddebug0(RES_MSG "Creating new record");
   rp = allocresolve();
   rp->state = STATE_PTRREQ;
   rp->sends = 1;
-  rp->ip = ip;
-  linkresolveip(rp);
+  rp->type = T_PTR;
+  egg_memcpy(&rp->sockname, addr, sizeof(sockname_t));
+  if (addr->family == AF_INET) {
+    rp->ip = addr->addr.s4.sin_addr.s_addr;
+    linkresolveip(rp);
+  }
+#ifdef IPV6
+  else
+    linkresolveip6(rp);
+#endif
   sendrequest(rp, T_PTR);
 }
 
@@ -1035,20 +1205,17 @@
 static void dns_forward(char *hostn)
 {
   struct resolve *rp;
-  struct in_addr inaddr;
+  sockname_t name;
 
-  /* Check if someone passed us an IP address as hostname
-   * and return it straight away.
-   */
-  if (egg_inet_aton(hostn, &inaddr)) {
-    call_ipbyhost(hostn, ntohl(inaddr.s_addr), 1);
+  if (setsockname(&name, hostn, 0, 0) != AF_UNSPEC) {
+    call_ipbyhost(hostn, &name, 1);
     return;
   }
   if ((rp = findhost(hostn))) {
     if (rp->state == STATE_FINISHED || rp->state == STATE_FAILED) {
-      if (rp->state == STATE_FINISHED && rp->ip) {
+      if (rp->state == STATE_FINISHED) {
         ddebug2(RES_MSG "Used cached record: %s == \"%s\".", hostn,
-                iptostr(rp->ip));
+                iptostr(&rp->sockname.addr.sa));
         dns_event_success(rp, T_A);
       } else {
         ddebug1(RES_MSG "Used failed record: %s == ???", hostn);
@@ -1063,6 +1230,7 @@
   rp->sends = 1;
   rp->hostn = nmalloc(strlen(hostn) + 1);
   strcpy(rp->hostn, hostn);
+  rp->type = T_A;
   linkresolvehost(rp);
   sendrequest(rp, T_A);
 }
Index: eggdrop1.8/src/mod/dns.mod/dns.c
diff -u eggdrop1.8/src/mod/dns.mod/dns.c:1.2 eggdrop1.8/src/mod/dns.mod/dns.c:1.3
--- eggdrop1.8/src/mod/dns.mod/dns.c:1.2	Tue Jul 27 15:49:42 2010
+++ eggdrop1.8/src/mod/dns.mod/dns.c	Thu Aug  5 12:12:05 2010
@@ -4,7 +4,7 @@
  *
  * Written by Fabian Knittel <fknittel at gmx.de>
  *
- * $Id: dns.c,v 1.2 2010/07/27 21:49:42 pseudo Exp $
+ * $Id: dns.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1999 - 2010 Eggheads Development Team
@@ -46,11 +46,13 @@
     return;
 
   if (type == T_PTR) {
-    debug2("DNS resolved %s to %s", iptostr(rp->ip), rp->hostn);
-    call_hostbyip(ntohl(rp->ip), rp->hostn, 1);
+    debug2("DNS resolved %s to %s", iptostr(&rp->sockname.addr.sa),
+           rp->hostn);
+    call_hostbyip(&rp->sockname, 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);
+    debug2("DNS resolved %s to %s", rp->hostn,
+           iptostr(&rp->sockname.addr.sa));
+    call_ipbyhost(rp->hostn, &rp->sockname, 1);
   }
 }
 
@@ -62,15 +64,15 @@
   if (type == T_PTR) {
     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);
+    strcpy(s, iptostr(&rp->sockname.addr.sa));
+    debug1("DNS resolve failed for %s", s);
+    call_hostbyip(&rp->sockname, s, 0);
   } else if (type == T_A) {
     debug1("DNS resolve failed for %s", rp->hostn);
-    call_ipbyhost(rp->hostn, 0, 0);
+    call_ipbyhost(rp->hostn, &rp->sockname, 0);
   } else
-    debug2("DNS resolve failed for unknown %s / %s", iptostr(rp->ip),
-           nonull(rp->hostn));
+    debug2("DNS resolve failed for unknown %s / %s",
+           iptostr(&rp->sockname.addr.sa), nonull(rp->hostn));
   return;
 }
 
@@ -217,6 +219,9 @@
   dcc[idx].sock = resfd;
   dcc[idx].timeval = now;
   strcpy(dcc[idx].nick, "(dns)");
+  egg_memcpy(&dcc[idx].sockname.addr.sa, &_res.nsaddr_list[0],
+             sizeof(_res.nsaddr_list[0]));
+  dcc[idx].sockname.addrlen = sizeof(_res.nsaddr_list[0]);
 
   add_hook(HOOK_SECONDLY, (Function) dns_check_expires);
   add_hook(HOOK_DNS_HOSTBYIP, (Function) dns_lookup);
Index: eggdrop1.8/src/mod/dns.mod/dns.h
diff -u eggdrop1.8/src/mod/dns.mod/dns.h:1.1.1.1 eggdrop1.8/src/mod/dns.mod/dns.h:1.2
--- eggdrop1.8/src/mod/dns.mod/dns.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/dns.mod/dns.h	Thu Aug  5 12:12:05 2010
@@ -4,7 +4,7 @@
  *
  * Written by Fabian Knittel <fknittel at gmx.de>
  *
- * $Id: dns.h,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: dns.h,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1999 - 2010 Eggheads Development Team
@@ -49,6 +49,9 @@
   time_t expiretime;
   char *hostn;
   IP ip;
+  u_32bit_t ttl;
+  u_16bit_t type;
+  sockname_t sockname;
   u_16bit_t id;
   u_8bit_t state;
   u_8bit_t sends;
Index: eggdrop1.8/src/mod/filesys.mod/filedb3.c
diff -u eggdrop1.8/src/mod/filesys.mod/filedb3.c:1.1.1.1 eggdrop1.8/src/mod/filesys.mod/filedb3.c:1.2
--- eggdrop1.8/src/mod/filesys.mod/filedb3.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/filesys.mod/filedb3.c	Thu Aug  5 12:12:05 2010
@@ -4,7 +4,7 @@
  *
  * Rewritten by Fabian Knittel <fknittel at gmx.de>
  *
- * $Id: filedb3.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: filedb3.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1081,9 +1081,10 @@
   }
   /* Grab info from dcc struct and bounce real request across net */
   i = dcc_total - 1;
-  s = nmalloc(40);              /* Enough? */
-  simple_sprintf(s, "%d %u %d", iptolong(getmyip()), dcc[i].port,
-                 dcc[i].u.xfer->length);
+  s = nmalloc(46);              /* Enough? */
+  /* Indeed, no more, no less ^^ */
+  getdccaddr(&dcc[i].sockname, s, 46);
+  simple_sprintf(s, "%s %u %d", s, dcc[i].port, dcc[i].u.xfer->length);
   botnet_send_filesend(idx, s1, from, s);
   putlog(LOG_FILES, "*", FILES_REMOTEREQ, dir, dir[0] ? "/" : "", what);
   my_free(s1);
Index: eggdrop1.8/src/mod/filesys.mod/filesys.c
diff -u eggdrop1.8/src/mod/filesys.mod/filesys.c:1.2 eggdrop1.8/src/mod/filesys.mod/filesys.c:1.3
--- eggdrop1.8/src/mod/filesys.mod/filesys.c:1.2	Tue Jul 27 15:49:42 2010
+++ eggdrop1.8/src/mod/filesys.mod/filesys.c	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * filesys.c -- part of filesys.mod
  *   main file of the filesys eggdrop module
  *
- * $Id: filesys.c,v 1.2 2010/07/27 21:49:42 pseudo Exp $
+ * $Id: filesys.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -29,6 +29,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/file.h>
+#include <errno.h>
 
 #include "src/mod/module.h"
 
@@ -696,8 +697,9 @@
                nick, from);
         return;
       }
-      dcc[i].addr = my_atoul(ip);
       dcc[i].port = atoi(prt);
+      (void) setsockname(&dcc[i].sockname, ip, dcc[i].port, 0);
+      dcc[i].u.dns->ip = &dcc[i].sockname;
       dcc[i].sock = -1;
       dcc[i].user = u;
       strcpy(dcc[i].nick, nick);
@@ -705,12 +707,11 @@
       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 = filesys_dcc_send_hostresolved;
       dcc[i].u.dns->dns_failure = filesys_dcc_send_hostresolved;
       dcc[i].u.dns->type = &DCC_FORK_SEND;
-      dcc_dnshostbyip(dcc[i].addr);
+      dcc_dnshostbyip(&dcc[i].sockname);
     }
   }
   my_free(buf);
@@ -753,7 +754,7 @@
 
   sprintf(prt, "%d", dcc[i].port);
   sprintf(ip, "%lu", iptolong(htonl(dcc[i].addr)));
-  if (!hostsanitycheck_dcc(dcc[i].nick, dcc[i].u.dns->host, dcc[i].addr,
+  if (!hostsanitycheck_dcc(dcc[i].nick, dcc[i].u.dns->host, &dcc[i].sockname,
                            dcc[i].u.dns->host, prt)) {
     lostdcc(i);
     return;
@@ -820,8 +821,9 @@
       lostdcc(i);
     } else {
       dcc[i].timeval = now;
-      dcc[i].sock = getsock(SOCK_BINARY);
-      if (dcc[i].sock < 0 || open_telnet_dcc(dcc[i].sock, ip, prt) < 0)
+      dcc[i].sock = getsock(dcc[i].sockname.family, SOCK_BINARY);
+      if (dcc[i].sock < 0 ||
+      open_telnet_raw(dcc[i].sock, &dcc[i].sockname) < 0)
         dcc[i].type->eof(i);
     }
   }
@@ -865,14 +867,17 @@
   } else {
     ip = newsplit(&msg);
     prt = newsplit(&msg);
-    sock = getsock(0);
-    if (sock < 0 || open_telnet_dcc(sock, ip, prt) < 0) {
-      neterror(buf);
+    i = new_dcc(&DCC_FILES_PASS, sizeof(struct file_info));
+    dcc[i].port = atoi(prt);
+    (void) setsockname(&dcc[i].sockname, ip, dcc[i].port, 0);
+    sock = getsock(dcc[i].sockname.family, 0);
+    if (sock < 0 || open_telnet_raw(sock, &dcc[i].sockname) < 0) {
+      lostdcc(i);
       if (!quiet_reject)
-        dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", nick, DCC_CONNECTFAILED1, buf);
+        dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", nick, DCC_CONNECTFAILED1, strerror(errno));
       putlog(LOG_MISC, "*", "%s: CHAT(file) (%s!%s)", DCC_CONNECTFAILED2, nick,
              from);
-      putlog(LOG_MISC, "*", "    (%s)", buf);
+      putlog(LOG_MISC, "*", "    (%s)", strerror(errno));
       killsock(sock);
     } else if (atoi(prt) < 1024 || atoi(prt) > 65535) {
       /* Invalid port */
@@ -882,9 +887,6 @@
       putlog(LOG_FILES, "*", "%s: %s!%s", DCC_REFUSED7, nick, from);
 
     } else {
-      i = new_dcc(&DCC_FILES_PASS, sizeof(struct file_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);
Index: eggdrop1.8/src/mod/module.h
diff -u eggdrop1.8/src/mod/module.h:1.1.1.1 eggdrop1.8/src/mod/module.h:1.2
--- eggdrop1.8/src/mod/module.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/module.h	Thu Aug  5 12:12:05 2010
@@ -1,7 +1,7 @@
 /*
  * module.h
  *
- * $Id: module.h,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: module.h,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -192,18 +192,18 @@
 #define egg_list_append ((int (*) ( struct list_type **, struct list_type *))global[74])
 #define egg_list_contains ((int (*) (struct list_type *, struct list_type *))global[75])
 /* 76 - 79 */
-#define answer ((int (*) (int,char *,unsigned long *,unsigned short *,int))global[76])
-#define getmyip ((IP (*) (void))global[77])
-#define neterror ((void (*) (char *))global[78])
+#define answer ((int (*) (int, sockname_t *, unsigned short *, int))global[76])
+#define getvhost ((void (*) (sockname_t *, int))global[77])
+/* was neterror() */
 #define tputs ((void (*) (int, char *,unsigned int))global[79])
 /* 80 - 83 */
 #define new_dcc ((int (*) (struct dcc_table *, int))global[80])
 #define lostdcc ((void (*) (int))global[81])
-#define getsock ((int (*) (int))global[82])
+#define getsock ((int (*) (int, int))global[82])
 #define killsock ((void (*) (int))global[83])
 /* 84 - 87 */
 #define open_listen ((int (*) (int *))global[84])
-#define open_telnet_dcc ((int (*) (int,char *,char *))global[85])
+#define getdccaddr ((int (*) (sockname_t *, char *, socklen_t))global[85])
 #define get_data_ptr(x) ((void *(*)(int,char*,int))global[86])(x,__FILE__,__LINE__)
 #define open_telnet ((int (*) (char *, int))global[87])
 /* 88 - 91 */
@@ -239,7 +239,8 @@
 /* 112 - 115 */
 #define tempdir ((char *)(global[112]))
 #define natip ((char *)(global[113]))
-#define hostname ((char *)(global[114]))
+/* was natip -- UNUSED */
+/* was hostname -- UNUSED */
 #define origbotname ((char *)(global[115]))
 /* 116 - 119 */
 #define botuser ((char *)(global[116]))
@@ -400,16 +401,16 @@
 #else
 #  define Assert(expr) do {} while (0)
 #endif
-#define allocsock ((int(*)(int sock,int options))global[234])
-#define call_hostbyip ((void(*)(IP, char *, int))global[235])
+#define allocsock ((int(*)(int sock, int options))global[234])
+#define call_hostbyip ((void(*)(sockname_t *, char *, int))global[235])
 /* 236 - 239 */
-#define call_ipbyhost ((void(*)(char *, IP, int))global[236])
-#define iptostr ((char *(*)(IP))global[237])
+#define call_ipbyhost ((void(*)(char *, sockname_t *, int))global[236])
+#define iptostr ((char *(*)(struct sockaddr *))global[237])
 #define DCC_DNSWAIT (*(struct dcc_table *)(global[238]))
-#define hostsanitycheck_dcc ((int(*)(char *, char *, IP, char *, char *))global[239])
+#define hostsanitycheck_dcc ((int(*)(char *, char *, sockname_t *, char *, char *))global[239])
 /* 240 - 243 */
 #define dcc_dnsipbyhost ((void (*)(char *))global[240])
-#define dcc_dnshostbyip ((void (*)(IP))global[241])
+#define dcc_dnshostbyip ((void (*)(sockname_t *))global[241])
 #define changeover_dcc ((void (*)(int, struct dcc_table *, int))global[242])
 #define make_rand_str ((void (*) (char *, int))global[243])
 /* 244 - 247 */
@@ -434,7 +435,7 @@
 #define tandbot (*(tand_t **)(global[259]))
 /* 260 - 263 */
 #define party (*(party_t **)(global[260]))
-#define open_address_listen ((int (*)(IP addr, int *port))global[261])
+#define open_address_listen ((int (*)(sockname_t *, int *))global[261])
 #define str_escape ((char *(*)(const char *, const char, const char))global[262])
 #define strchr_unescape ((char *(*)(char *, const char, register const char))global[263])
 /* 264 - 267 */
@@ -469,10 +470,12 @@
 /* 284 - 287 */
 #define quiet_reject (*(int *)(global[284]))
 #define file_readable ((int (*) (char *))global[285])
-/* IPv6 leftovers: 286 */
-/* IPv6 leftovers: 287 */
+#define setsockname ((int (*)(sockname_t *, char *, int, int))global[286])
+#define open_telnet_raw ((int (*)(int, sockname_t *))global[287])
 /* 288 - 291 */
-/* IPv6 leftovers: 288 */
+#ifdef IPV6
+# define pref_af (*(int *)(global[288]))
+#endif
 #define strip_mirc_codes ((void (*)(int, char *))global[289])
 #define check_ansi ((int (*) (char *))global[290])
 #define oatoi ((int (*) (const char *))global[291])
Index: eggdrop1.8/src/mod/server.mod/server.c
diff -u eggdrop1.8/src/mod/server.mod/server.c:1.2 eggdrop1.8/src/mod/server.mod/server.c:1.3
--- eggdrop1.8/src/mod/server.mod/server.c:1.2	Tue Jul 27 15:49:42 2010
+++ eggdrop1.8/src/mod/server.mod/server.c	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * server.c -- part of server.mod
  *   basic irc server support
  *
- * $Id: server.c,v 1.2 2010/07/27 21:49:42 pseudo Exp $
+ * $Id: server.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -26,6 +26,7 @@
 #define MODULE_NAME "server"
 #define MAKING_SERVER
 
+#include <errno.h>
 #include "src/mod/module.h"
 #include "server.h"
 
@@ -970,6 +971,15 @@
     else
       serverlist = x;
     z = x;
+#ifdef IPV6
+    p = 0;
+    if ((q = strchr(ss, ','))) {
+      if (!q[1]) {
+        *q = 0;
+        q = 0;
+      }
+    } else
+#endif
     q = strchr(ss, ':');
     if (!q) {
       x->port = default_port;
@@ -1509,44 +1519,42 @@
       putlog(LOG_MISC, "*", "DCC connection: CHAT (%s!%s)", nick, ip);
       return 1;
     }
-    dcc[i].addr = my_atoul(ip);
     dcc[i].port = atoi(prt);
+    (void) setsockname(&dcc[i].sockname, ip, dcc[i].port, 0);
+    dcc[i].u.dns->ip = &dcc[i].sockname;
     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 = dcc_chat_hostresolved;
     dcc[i].u.dns->dns_failure = dcc_chat_hostresolved;
     dcc[i].u.dns->type = &DCC_CHAT_PASS;
-    dcc_dnshostbyip(dcc[i].addr);
+    dcc_dnshostbyip(&dcc[i].sockname);
   }
   return 1;
 }
 
 static void dcc_chat_hostresolved(int i)
 {
-  char buf[512], ip[512];
+  char buf[512];
   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
 
   egg_snprintf(buf, sizeof buf, "%d", dcc[i].port);
-  if (!hostsanitycheck_dcc(dcc[i].nick, dcc[i].host, dcc[i].addr,
-                           dcc[i].u.dns->host, buf)) {
+  if (!hostsanitycheck_dcc(dcc[i].nick, dcc[i].host, &dcc[i].sockname,
+      dcc[i].u.dns->host, buf)) {
     lostdcc(i);
     return;
   }
-  egg_snprintf(ip, sizeof ip, "%lu", iptolong(htonl(dcc[i].addr)));
-  dcc[i].sock = getsock(0);
-  if (dcc[i].sock < 0 || open_telnet_dcc(dcc[i].sock, ip, buf) < 0) {
-    neterror(buf);
+  dcc[i].sock = getsock(dcc[i].sockname.family, 0);
+  if (dcc[i].sock < 0 || open_telnet_raw(dcc[i].sock, &dcc[i].sockname) < 0) {
     if (!quiet_reject)
       dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", dcc[i].nick,
-              DCC_CONNECTFAILED1, buf);
+              DCC_CONNECTFAILED1, strerror(errno));
     putlog(LOG_MISC, "*", "%s: CHAT (%s!%s)", DCC_CONNECTFAILED2,
            dcc[i].nick, dcc[i].host);
-    putlog(LOG_MISC, "*", "    (%s)", buf);
+    putlog(LOG_MISC, "*", "    (%s)", strerror(errno));
     killsock(dcc[i].sock);
     lostdcc(i);
   } else {
Index: eggdrop1.8/src/mod/server.mod/servmsg.c
diff -u eggdrop1.8/src/mod/server.mod/servmsg.c:1.1.1.1 eggdrop1.8/src/mod/server.mod/servmsg.c:1.2
--- eggdrop1.8/src/mod/server.mod/servmsg.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/mod/server.mod/servmsg.c	Thu Aug  5 12:12:05 2010
@@ -1,7 +1,7 @@
 /*
  * servmsg.c -- part of server.mod
  *
- * $Id: servmsg.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: servmsg.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1294,8 +1294,13 @@
       do_tcl("connect-server", connectserver);
     check_tcl_event("connect-server");
     next_server(&curserv, botserver, &botserverport, pass);
+#ifdef IPV6
+    if (strchr(botserver, ':'))
+      putlog(LOG_SERV, "*", "%s [%s]:%d", IRC_SERVERTRY, botserver,
+             botserverport);
+    else
+#endif
     putlog(LOG_SERV, "*", "%s %s:%d", IRC_SERVERTRY, botserver, botserverport);
-
     dcc[servidx].port = botserverport;
     strcpy(dcc[servidx].nick, "(server)");
     strncpyz(dcc[servidx].host, botserver, UHOSTLEN);
@@ -1344,17 +1349,17 @@
 static void server_resolve_success(int servidx)
 {
   int oldserv = dcc[servidx].u.dns->ibuf;
-  char s[121], pass[121];
+  char 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(htonl(dcc[servidx].addr)), dcc[servidx].port);
+  dcc[servidx].sock = getsock(dcc[servidx].sockname.family, 0);
+  setsnport(dcc[servidx].sockname, dcc[servidx].port);
+  serv = open_telnet_raw(dcc[servidx].sock, &dcc[servidx].sockname);
   if (serv < 0) {
-    neterror(s);
     putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, dcc[servidx].host,
-           s);
+           strerror(errno));
     lostdcc(servidx);
     if (oldserv == curserv && !never_give_up)
       fatal("NO SERVERS WILL ACCEPT MY CONNECTION.", 0);
Index: eggdrop1.8/src/mod/share.mod/share.c
diff -u eggdrop1.8/src/mod/share.mod/share.c:1.2 eggdrop1.8/src/mod/share.mod/share.c:1.3
--- eggdrop1.8/src/mod/share.mod/share.c:1.2	Tue Jul 27 15:49:42 2010
+++ eggdrop1.8/src/mod/share.mod/share.c	Thu Aug  5 12:12:05 2010
@@ -1,7 +1,7 @@
 /*
  * share.c -- part of share.mod
  *
- * $Id: share.c,v 1.2 2010/07/27 21:49:42 pseudo Exp $
+ * $Id: share.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1137,16 +1137,18 @@
   } else {
     ip = newsplit(&par);
     port = newsplit(&par);
-    sock = getsock(SOCK_BINARY); /* Don't buffer this -> mark binary. */
-    if (sock < 0 || open_telnet_dcc(sock, ip, port) < 0) {
+    i = new_dcc(&DCC_FORK_SEND, sizeof(struct xfer_info));
+    dcc[i].port = atoi(port);
+    (void) setsockname(&dcc[i].sockname, ip, dcc[i].port, 0);
+    /* Don't buffer this -> mark binary. */
+    sock = getsock(dcc[i].sockname.family, SOCK_BINARY);
+    if (sock < 0 || open_telnet_raw(sock, &dcc[i].sockname) < 0) {
+      lostdcc(i);
       killsock(sock);
       putlog(LOG_BOTS, "*", "Asynchronous connection failed!");
       dprintf(idx, "s e Can't connect to you!\n");
       zapfbot(idx);
     } else {
-      i = new_dcc(&DCC_FORK_SEND, sizeof(struct xfer_info));
-      dcc[i].addr = my_atoul(ip);
-      dcc[i].port = atoi(port);
       strcpy(dcc[i].nick, "*users");
       dcc[i].u.xfer->filename = nmalloc(strlen(s) + 1);
       strcpy(dcc[i].u.xfer->filename, s);
@@ -1890,6 +1892,11 @@
   int i = 1;
   struct chanuserrec *ch;
   struct chanset_t *cst;
+#ifdef IPV6
+  char s[INET6_ADDRSTRLEN];
+#else
+  char s[sizeof "255.255.255.255"];
+#endif
 
   egg_snprintf(share_file, sizeof share_file, ".share.%s.%lu", dcc[idx].nick,
                now);
@@ -1924,8 +1931,8 @@
     dcc[idx].status |= STAT_SENDING;
     i = dcc_total - 1;
     strcpy(dcc[i].host, dcc[idx].nick); /* Store bot's nick */
-    dprintf(idx, "s us %lu %d %lu\n",
-            iptolong(natip[0] ? (IP) inet_addr(natip) : getmyip()),
+    getdccaddr(&dcc[i].sockname, s, sizeof s);
+    dprintf(idx, "s us %s %d %lu\n", s,
             dcc[i].port, dcc[i].u.xfer->length);
     /* Start up a tbuf to queue outgoing changes for this bot until the
      * userlist is done transferring.
Index: eggdrop1.8/src/mod/transfer.mod/transfer.c
diff -u eggdrop1.8/src/mod/transfer.mod/transfer.c:1.2 eggdrop1.8/src/mod/transfer.mod/transfer.c:1.3
--- eggdrop1.8/src/mod/transfer.mod/transfer.c:1.2	Tue Jul 27 15:49:42 2010
+++ eggdrop1.8/src/mod/transfer.mod/transfer.c	Thu Aug  5 12:12:05 2010
@@ -1,7 +1,7 @@
 /*
  * transfer.c -- part of transfer.mod
  *
- * $Id: transfer.c,v 1.2 2010/07/27 21:49:42 pseudo Exp $
+ * $Id: transfer.c,v 1.3 2010/08/05 18:12:05 pseudo Exp $
  *
  * Copyright (C) 1997 Robey Pointer
  * Copyright (C) 1999 - 2010 Eggheads Development Team
@@ -30,6 +30,7 @@
 /* sigh sunos */
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/errno.h>
 #include "src/mod/module.h"
 #include "src/tandem.h"
 
@@ -257,8 +258,7 @@
 
 static void eof_dcc_fork_send(int idx)
 {
-  char s1[121];
-  char *s2;
+  char *s;
 
   fclose(dcc[idx].u.xfer->f);
   if (!strcmp(dcc[idx].nick, "*users")) {
@@ -277,17 +277,16 @@
     putlog(LOG_BOTS, "*", USERF_FAILEDXFER);
     unlink(dcc[idx].u.xfer->filename);
   } else {
-    neterror(s1);
     if (!quiet_reject)
       dprintf(DP_HELP, "NOTICE %s :%s (%s)\n", dcc[idx].nick,
-              DCC_CONNECTFAILED1, s1);
+              DCC_CONNECTFAILED1, strerror(errno));
     putlog(LOG_MISC, "*", "%s: SEND %s (%s!%s)", DCC_CONNECTFAILED2,
            dcc[idx].u.xfer->origname, dcc[idx].nick, dcc[idx].host);
-    putlog(LOG_MISC, "*", "    (%s)", s1);
-    s2 = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
-    sprintf(s2, "%s%s", tempdir, dcc[idx].u.xfer->filename);
-    unlink(s2);
-    nfree(s2);
+    putlog(LOG_MISC, "*", "    (%s)", strerror(errno));
+    s = nmalloc(strlen(tempdir) + strlen(dcc[idx].u.xfer->filename) + 1);
+    sprintf(s, "%s%s", tempdir, dcc[idx].u.xfer->filename);
+    unlink(s);
+    nfree(s);
   }
   killsock(dcc[idx].sock);
   lostdcc(idx);
@@ -906,19 +905,16 @@
 
 static void dcc_get_pending(int idx, char *buf, int len)
 {
-  unsigned long ip;
   unsigned short port;
   int i;
-  char s[UHOSTLEN];
 
-  i = answer(dcc[idx].sock, s, &ip, &port, 1);
+  i = answer(dcc[idx].sock, &dcc[idx].sockname, &port, 1);
   killsock(dcc[idx].sock);
   dcc[idx].sock = i;
-  dcc[idx].addr = ip;
+  dcc[idx].addr = 0;
   dcc[idx].port = (int) port;
   if (dcc[idx].sock == -1) {
-    neterror(s);
-    dprintf(DP_HELP, TRANSFER_NOTICE_BAD_CONN, dcc[idx].nick, s);
+    dprintf(DP_HELP, TRANSFER_NOTICE_BAD_CONN, dcc[idx].nick, strerror(errno));
     putlog(LOG_FILES, "*", TRANSFER_LOG_BAD_CONN, dcc[idx].u.xfer->origname,
            dcc[idx].nick, dcc[idx].host);
     fclose(dcc[idx].u.xfer->f);
@@ -1024,7 +1020,10 @@
     return DCCSEND_FULL;
 
   dcc[i].sock = zz;
-  dcc[i].addr = (IP) (-559026163);
+  dcc[i].sockname.addrlen = sizeof(dcc[i].sockname.addr);
+  getsockname(dcc[i].sock, &dcc[i].sockname.addr.sa,
+              &dcc[i].sockname.addrlen);
+  dcc[i].sockname.family = dcc[i].sockname.addr.sa.sa_family;
   dcc[i].port = port;
   strcpy(dcc[i].nick, nick);
   strcpy(dcc[i].host, "irc");
@@ -1042,11 +1041,17 @@
   dcc[i].u.xfer->type = resend ? XFER_RESEND_PEND : XFER_SEND;
 
   if (nick[0] != '*') {
-    dprintf(DP_SERVER, "PRIVMSG %s :\001DCC %sSEND %s %lu %d %lu\001\n", nick,
-            resend ? "RE" : "", nfn, iptolong(natip[0] ?
-            (IP) inet_addr(natip) : getmyip()), port, dccfilesize);
-    putlog(LOG_FILES, "*", TRANSFER_BEGIN_DCC, resend ? TRANSFER_RE : "", nfn,
-           nick);
+#ifdef IPV6
+    char s[INET6_ADDRSTRLEN];
+#else
+    char s[INET_ADDRSTRLEN];
+#endif
+    if (getdccaddr(&dcc[i].sockname, s, sizeof s)) {
+      dprintf(DP_SERVER, "PRIVMSG %s :\001DCC %sSEND %s %s %d %lu\001\n", nick,
+              resend ? "RE" : "", nfn, s, port, dccfilesize);
+      putlog(LOG_FILES, "*", TRANSFER_BEGIN_DCC, resend ? TRANSFER_RE : "", nfn,
+             nick);
+    }
   }
 
   if (buf)
Index: eggdrop1.8/src/modules.c
diff -u eggdrop1.8/src/modules.c:1.1.1.1 eggdrop1.8/src/modules.c:1.2
--- eggdrop1.8/src/modules.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/modules.c	Thu Aug  5 12:12:05 2010
@@ -4,7 +4,7 @@
  *
  * by Darrin Smith (beldin at light.iinet.net.au)
  *
- * $Id: modules.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: modules.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -84,9 +84,9 @@
 extern struct userrec *userlist, *lastuser;
 extern struct chanset_t *chanset;
 
-extern char tempdir[], botnetnick[], botname[], natip[], hostname[],
-            origbotname[], botuser[], admin[], userfile[], ver[], notify_new[],
-            helpdir[], version[], quit_msg[], log_ts[];
+extern char tempdir[], botnetnick[], botname[], origbotname[], botuser[],
+            admin[], userfile[], ver[], notify_new[], helpdir[], version[],
+            quit_msg[], log_ts[];
 
 extern int parties, noshare, dcc_total, egg_numver, userfile_perm, do_restart,
            ignore_time, must_be_owner, raw_log, max_dcc, make_userfile,
@@ -94,6 +94,10 @@
            password_timeout, force_expire, protect_readonly, reserved_port_min,
            reserved_port_max, copy_to_tmp, quiet_reject;
 
+#ifdef IPV6
+extern int pref_af;
+#endif
+
 extern party_t *party;
 extern time_t now, online_since;
 extern tand_t *tandbot;
@@ -180,7 +184,7 @@
 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_hostbyip) (sockname_t *) = block_dns_hostbyip;
 void (*dns_ipbyhost) (char *) = block_dns_ipbyhost;
 
 module_entry *module_list;
@@ -292,8 +296,8 @@
   (Function) egg_list_contains,
   /* 76 - 79 */
   (Function) answer,
-  (Function) getmyip,
-  (Function) neterror,
+  (Function) getvhost,
+  (Function) 0,                   /* was neterror() -- UNUSED            */
   (Function) tputs,
   /* 80 - 83 */
   (Function) new_dcc,
@@ -302,7 +306,7 @@
   (Function) killsock,
   /* 84 - 87 */
   (Function) open_listen,
-  (Function) open_telnet_dcc,
+  (Function) getdccaddr,
   (Function) _get_data_ptr,
   (Function) open_telnet,
   /* 88 - 91 */
@@ -337,8 +341,8 @@
   (Function) & dcc_total,         /* int                                 */
   /* 112 - 115 */
   (Function) tempdir,             /* char *                              */
-  (Function) natip,               /* char *                              */
-  (Function) hostname,            /* char *                              */
+  (Function) 0,                   /* was natip -- use getmyip() instead  */
+  (Function) 0,                   /* was myip -- use getvhost() instead  */
   (Function) origbotname,         /* char *                              */
   /* 116 - 119 */
   (Function) botuser,             /* char *                              */
@@ -561,10 +565,14 @@
   /* 284 - 287 */
   (Function) & quiet_reject,      /* int                                 */
   (Function) file_readable,
-  (Function) 0,                   /* IPv6 leftovers: 286                 */
-  (Function) 0,                   /* IPv6 leftovers: 287                 */
+  (Function) setsockname,
+  (Function) open_telnet_raw,
   /* 288 - 291 */
+#ifdef IPV6
+  (Function) & pref_af,		  /* int                                 */
+#else
   (Function) 0,                   /* IPv6 leftovers: 288                 */
+#endif
   (Function) strip_mirc_codes,
   (Function) check_ansi,
   (Function) oatoi,
@@ -1041,7 +1049,7 @@
       break;
     case HOOK_DNS_HOSTBYIP:
       if (dns_hostbyip == block_dns_hostbyip)
-        dns_hostbyip = (void (*)(IP)) func;
+        dns_hostbyip = (void (*)(sockname_t *)) func;
       break;
     case HOOK_DNS_IPBYHOST:
       if (dns_ipbyhost == block_dns_ipbyhost)
@@ -1102,7 +1110,7 @@
         match_noterej = false_func;
       break;
     case HOOK_DNS_HOSTBYIP:
-      if (dns_hostbyip == (void (*)(IP)) func)
+      if (dns_hostbyip == (void (*)(sockname_t *)) func)
         dns_hostbyip = block_dns_hostbyip;
       break;
     case HOOK_DNS_IPBYHOST:
Index: eggdrop1.8/src/net.c
diff -u eggdrop1.8/src/net.c:1.1.1.1 eggdrop1.8/src/net.c:1.2
--- eggdrop1.8/src/net.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/net.c	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * net.c -- handles:
  *   all raw network i/o
  *
- * $Id: net.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: net.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * This is hereby released into the public domain.
@@ -58,8 +58,13 @@
                      otraffic_filesys_today, otraffic_trans_today,
                      otraffic_unknown_today;
 
-char hostname[121] = "";      /* Hostname can be specified in the config file.*/
-char myip[121] = "";          /* IP can be specified in the config file.      */
+char natip[121] = "";         /* Public IPv4 to report for systems behind NAT */
+char listen_ip[121] = "";     /* IP (or hostname) for listening sockets       */
+char vhost[121] = "";          /* IPv4 vhost for outgoing connections         */
+#ifdef IPV6
+char vhost6[121] = "";         /* IPv6 vhost for outgoing connections         */
+int pref_af = 0;              /* Prefer IPv6 over IPv4?                       */
+#endif
 char firewall[121] = "";      /* Socks server for firewall.                   */
 int firewallport = 1080;      /* Default port of socks 4/5 firewalls.         */
 char botuser[21] = "eggdrop"; /* Username of the user running the bot.        */
@@ -103,109 +108,125 @@
   return tot;
 }
 
-/* Get my ip number
+/* Extract the IP address from a sockaddr struct and convert it
+ * to presentation format.
  */
-IP getmyip()
+char *iptostr(struct sockaddr *sa)
 {
-  struct hostent *hp;
-  char s[121];
-  IP ip;
-  struct in_addr *in;
-  if (myip[0]) {
-    if ((myip[strlen(myip) - 1] >= '0') && (myip[strlen(myip) - 1] <= '9'))
-      return (IP) inet_addr(myip);
-  }
-  /* Also could be pre-defined */
-  if (hostname[0])
-    hp = gethostbyname(hostname);
-  else {
-    gethostname(s, 120);
-    hp = gethostbyname(s);
-  }
-  if (hp == NULL)
-    fatal("Hostname self-lookup failed. Please set 'my-ip' in the config "
-          "file.", 0);
-  in = (struct in_addr *) (hp->h_addr_list[0]);
-  ip = (IP) (in->s_addr);
-  return ip;
-}
-
-void neterror(char *s)
-{
-  switch (errno) {
-  case EADDRINUSE:
-    strcpy(s, "Address already in use");
-    break;
-  case EADDRNOTAVAIL:
-    strcpy(s, "Cannot assign requested address");
-    break;
-  case EAFNOSUPPORT:
-    strcpy(s, "Address family not supported");
-    break;
-  case EALREADY:
-    strcpy(s, "Socket already in use");
-    break;
-  case EBADF:
-    strcpy(s, "Socket descriptor is bad");
-    break;
-  case ECONNREFUSED:
-    strcpy(s, "Connection refused");
-    break;
-  case EFAULT:
-    strcpy(s, "Bad address");
-    break;
-  case EINPROGRESS:
-    strcpy(s, "Operation in progress");
-    break;
-  case EINTR:
-    strcpy(s, "Timeout");
-    break;
-  case EINVAL:
-    strcpy(s, "Invalid argument");
-    break;
-  case EISCONN:
-    strcpy(s, "Socket already connected");
-    break;
-  case ENETUNREACH:
-    strcpy(s, "Network unreachable");
-    break;
-  case ENOTSOCK:
-    strcpy(s, "Socket operation on non-socket");
-    break;
-  case ETIMEDOUT:
-    strcpy(s, "Connection timed out");
-    break;
-  case ENOTCONN:
-    strcpy(s, "Socket is not connected");
-    break;
-  case EHOSTUNREACH:
-    strcpy(s, "No route to host");
-    break;
-  case EPIPE:
-    strcpy(s, "Broken pipe");
-    break;
-#ifdef ECONNRESET
-  case ECONNRESET:
-    strcpy(s, "Connection reset by peer");
-    break;
+#ifdef IPV6
+  static char s[INET6_ADDRSTRLEN] = "";
+  if (sa->sa_family == AF_INET6)
+    inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr,
+              s, sizeof s);
+  else
+#else
+  static char s[sizeof "255.255.255.255"] = "";
 #endif
-#ifdef EACCES
-  case EACCES:
-    strcpy(s, "Permission denied");
-    break;
+    inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr.s_addr, s,
+              sizeof s);
+  return s;
+}
+
+/* Fills in a sockname struct with the given server and port. If the string
+ * pointed by src isn't an IP address and allowres is not null, the function
+ * will assume it's a hostname and will attempt to resolve it. This is
+ * convenient, but you should use the async dns functions where possible, to
+ * avoid blocking the bot while the lookup is performed.
+ */
+int setsockname(sockname_t *addr, char *src, int port, int allowres)
+{
+  struct hostent *hp;
+  int af = AF_UNSPEC;
+#ifdef IPV6
+  int pref;
+
+  /* Clean start */
+  egg_bzero(addr, sizeof(sockname_t));
+  af = pref = pref_af ? AF_INET6 : AF_INET;
+  if (pref == AF_INET) {
+    if (!egg_inet_aton(src, &addr->addr.s4.sin_addr))
+      af = AF_INET6;
+  } else {
+    if (inet_pton(af, src, &addr->addr.s6.sin6_addr) != 1)
+      af = AF_INET;
+  }
+  if (af != pref)
+    if (((af == AF_INET6) &&
+         (inet_pton(af, src, &addr->addr.s6.sin6_addr) != 1)) ||
+        ((af == AF_INET)  &&
+         !egg_inet_aton(src, &addr->addr.s4.sin_addr)))
+      af = AF_UNSPEC;
+
+  if (af == AF_UNSPEC && allowres) {
+    /* src is a hostname. Attempt to resolve it.. */
+    if (!sigsetjmp(alarmret, 1)) {
+      alarm(resolve_timeout);
+      hp = gethostbyname2(src, pref_af ? AF_INET6 : AF_INET);
+      if (!hp)
+        hp = gethostbyname2(src, pref_af ? AF_INET : AF_INET6);
+      alarm(0);
+    } else
+      hp = NULL;
+    if (hp) {
+      if (hp->h_addrtype == AF_INET)
+        egg_memcpy(&addr->addr.s4.sin_addr, hp->h_addr, hp->h_length);
+      else
+        egg_memcpy(&addr->addr.s6.sin6_addr, hp->h_addr, hp->h_length);
+      af = hp->h_addrtype;
+    }
+  }
+  
+  addr->family = (af == AF_UNSPEC) ? pref : af;
+  addr->addr.sa.sa_family = addr->family;
+  if (addr->family == AF_INET6) {
+    addr->addrlen = sizeof(struct sockaddr_in6);
+    addr->addr.s6.sin6_port = htons(port);
+    addr->addr.s6.sin6_family = AF_INET6;
+  } else {
+    addr->addrlen = sizeof(struct sockaddr_in);
+    addr->addr.s4.sin_port = htons(port);
+    addr->addr.s4.sin_family = AF_INET;
+  }
+#else
+  egg_bzero(addr, sizeof(sockname_t));
+  if (!egg_inet_aton(src, &addr->addr.s4.sin_addr) && allowres) {
+    /* src is a hostname. Attempt to resolve it.. */
+    if (!sigsetjmp(alarmret, 1)) {
+      alarm(resolve_timeout);
+      hp = gethostbyname(src);
+      alarm(0);
+    } else
+      hp = NULL;
+    if (hp) {
+      egg_memcpy(&addr->addr.s4.sin_addr, hp->h_addr, hp->h_length);
+      af = hp->h_addrtype;
+    }
+  }
+  
+  addr->family = addr->addr.s4.sin_family = AF_INET;
+  addr->addr.sa.sa_family = addr->family;
+  addr->addrlen = sizeof(struct sockaddr_in);
+  addr->addr.s4.sin_port = htons(port);
 #endif
-#ifdef EMFILE
-  case EMFILE:
-    strcpy(s, "Too many open files");
-    break;
+  return af;
+}
+
+/* Get socket address to bind to for outbound connections
+ */
+void getvhost(sockname_t *addr, int af)
+{
+  char *h;
+  
+  if (af == AF_INET)
+    h = vhost;
+#ifdef IPV6
+  else
+    h = vhost6;
 #endif
-  case 0:
-    strcpy(s, "Error 0");
-    break;
-  default:
-    sprintf(s, "Unforseen error %d", errno);
-    break;
-  }
+  if (setsockname(addr, h, 0, 1) != af)
+    setsockname(addr, (af == AF_INET ? "0" : "::"), 0, 0);
+  /* Remember this 'self-lookup failed' thingie?
+     I have good news - you won't see it again ;) */
 }
 
 /* Sets/Unsets options for a specific socket.
@@ -321,14 +342,15 @@
   fcntl(sock, F_SETFL, O_NONBLOCK);
 }
 
-int getsock(int options)
+int getsock(int af, int options)
 {
-  int sock = socket(AF_INET, SOCK_STREAM, 0);
-
+  int sock = socket(af, SOCK_STREAM, 0);
+  
   if (sock >= 0)
     setsock(sock, options);
   else
-    putlog(LOG_MISC, "*", "Warning: Can't create new socket!");
+    putlog(LOG_MISC, "*", "Warning: Can't create new socket: %s!",
+           strerror(errno));
   return sock;
 }
 
@@ -386,176 +408,133 @@
 
 /* Send connection request to proxy
  */
-static int proxy_connect(int sock, char *host, int port, int proxy)
+static int proxy_connect(int sock, sockname_t *addr)
 {
-  unsigned char x[10];
-  struct hostent *hp;
-  char s[256];
-  int i;
-
-  /* socks proxy */
+  sockname_t name;
+  char host[121], s[256];
+  int i, port, proxy;
+  
+  if (!firewall[0])
+    return -2;
+#ifdef IPV6
+  if (addr->family == AF_INET6) {
+    putlog(LOG_MISC, "*", "Eggdrop doesn't support IPv6 connections "
+           "through proxies yet.");
+    return -1;
+  }
+#endif
+  if (firewall[0] == '!') {
+    proxy = PROXY_SUN;
+    strcpy(host, &firewall[1]);
+  } else {
+    proxy = PROXY_SOCKS;
+    strcpy(host, firewall);
+  }
+  port = addr->addr.s4.sin_port;
+  setsockname(&name, host, firewallport, 1);
+  if (connect(sock, &name.addr.sa, name.addrlen) < 0 && errno != EINPROGRESS)
+    return -1;
   if (proxy == PROXY_SOCKS) {
-    /* numeric IP? */
-    if (host[strlen(host) - 1] >= '0' && host[strlen(host) - 1] <= '9') {
-      IP ip = ((IP) inet_addr(host));
-      egg_memcpy(x, &ip, 4);
-    } else {
-      /* no, must be host.domain */
-      if (!sigsetjmp(alarmret, 1)) {
-        alarm(resolve_timeout);
-        hp = gethostbyname(host);
-        alarm(0);
-      } else
-        hp = NULL;
-      if (hp == NULL) {
-        killsock(sock);
-        return -2;
-      }
-      egg_memcpy(x, hp->h_addr, hp->h_length);
-    }
-    for (i = 0; i < threaddata()->MAXSOCKS; i++)
+    for (i = 0; i < threaddata()->MAXSOCKS; i++) 
       if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
         socklist[i].flags |= SOCK_PROXYWAIT;    /* drummer */
-      egg_snprintf(s, sizeof s, "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256,
-                   (port % 256), x[0], x[1], x[2], x[3], botuser);
+    egg_memcpy(host, &addr->addr.s4.sin_addr.s_addr, 4);
+    egg_snprintf(s, sizeof s, "\004\001%c%c%c%c%c%c%s", port % 256,
+                 (port >> 8) % 256, host[0], host[1], host[2], host[3], botuser);
     tputs(sock, s, strlen(botuser) + 9);        /* drummer */
   } else if (proxy == PROXY_SUN) {
+    inet_ntop(AF_INET, &addr->addr.s4.sin_addr, host, sizeof host);
     egg_snprintf(s, sizeof s, "%s %d\n", host, port);
     tputs(sock, s, strlen(s));  /* drummer */
   }
   return sock;
 }
 
-/* Starts a connection attempt to a socket
+/* Starts a connection attempt through 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.
+ * The server address should be filled in addr by setsockname() or by the
+ * non-blocking dns functions and setsnport().
  *
- * returns <0 if connection refused:
- *   -1  neterror() type error
- *   -2  can't resolve hostname
+ * returns < 0 if connection refused:
+ *   -1  strerror() type error
  */
-int open_telnet_raw(int sock, char *server, int sport)
+int open_telnet_raw(int sock, sockname_t *addr)
 {
-  struct sockaddr_in name;
-  struct hostent *hp;
-  char host[121];
-  int i, port, rc;
-  volatile int proxy;
-
-  /* firewall?  use socks */
-  if (firewall[0]) {
-    if (firewall[0] == '!') {
-      proxy = PROXY_SUN;
-      strcpy(host, &firewall[1]);
-    } else {
-      proxy = PROXY_SOCKS;
-      strcpy(host, firewall);
-    }
-    port = firewallport;
-  } else {
-    proxy = 0;
-    strcpy(host, server);
-    port = sport;
-  }
-  egg_bzero((char *) &name, sizeof(struct sockaddr_in));
-
-  name.sin_family = AF_INET;
-  name.sin_addr.s_addr = (myip[0] ? getmyip() : INADDR_ANY);
-  if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) {
-    killsock(sock);
-    return -1;
-  }
-  egg_bzero((char *) &name, sizeof(struct sockaddr_in));
+  sockname_t name;
+  int i, rc;
 
-  name.sin_family = AF_INET;
-  name.sin_port = htons(port);
-  /* Numeric IP? */
-  if ((host[strlen(host) - 1] >= '0') && (host[strlen(host) - 1] <= '9'))
-    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 (!sigsetjmp(alarmret, 1)) {
-      alarm(resolve_timeout);
-      hp = gethostbyname(host);
-      alarm(0);
-    } else
-      hp = NULL;
-    if (hp == NULL)
-      return -2;
-    egg_memcpy(&name.sin_addr, hp->h_addr, hp->h_length);
-    name.sin_family = hp->h_addrtype;
+  getvhost(&name, addr->family);
+  if (bind(sock, &name.addr.sa, name.addrlen) < 0) {
+    return -1;
   }
   for (i = 0; i < threaddata()->MAXSOCKS; i++) {
     if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock))
       socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;
   }
-  rc = connect(sock, (struct sockaddr *) &name, sizeof(struct sockaddr_in));
+  if (addr->family == AF_INET && firewall[0])
+    return proxy_connect(sock, addr);
+  rc = connect(sock, &addr->addr.sa, addr->addrlen);
   if (rc < 0) {
-    if (errno == EINPROGRESS) {
-      /* Firewall?  announce connect attempt to proxy */
-      if (firewall[0])
-        return proxy_connect(sock, server, sport, proxy);
+    if (errno == EINPROGRESS)
       return sock; /* async success! */
-    } else
+    else
       return -1;
   }
-  /* Synchronous? :/ */
-  if (firewall[0])
-    return proxy_connect(sock, server, sport, proxy);
   return sock;
 }
 
-/* Ordinary non-binary connection attempt */
+/* Ordinary non-binary connection attempt
+ * Return values:
+ *   >=0: connect successful, returned is the socket number
+ *    -1: look at errno or use strerror()
+ *    -2: lookup failed or server is not a valid IP string
+ */
 int open_telnet(char *server, int port)
 {
-  int sock = getsock(0), ret = open_telnet_raw(sock, server, port);
-
+  int ret, sock;
+  sockname_t name;
+  
+  ret = setsockname(&name, server, port, 1);
+  if (ret == AF_UNSPEC)
+    return -2;
+  sock = getsock(ret, 0);
+  if (sock < 0)
+    return -1;
+  ret = open_telnet_raw(sock, &name);
+  if (ret < 0)
+    killsock(sock);
   return ret;
 }
 
 /* Returns a socket number for a listening socket that will accept any
- * connection on a certain address -- port # is returned in port
+ * connection on the given address. The address can be filled in by
+ * setsockname().
  */
-int open_address_listen(IP addr, int *port)
- {
+int open_address_listen(sockname_t *addr)
+{
   int sock = 0;
-  socklen_t addrlen;
-  struct sockaddr_in name;
 
-  if (firewall[0]) {
-    /* FIXME: can't do listen port thru firewall yet */
-    putlog(LOG_MISC, "*", "Can't open a listen port (you are using a "
-           "firewall).");
+  sock = getsock(addr->family, SOCK_LISTEN);
+  if (sock < 0)
     return -1;
+#if defined IPV6 && IPV6_V6ONLY
+  if (addr->family == AF_INET6) {
+    int on = 0;
+    setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on, sizeof(on));
+  }
+#endif
+  if (bind(sock, &addr->addr.sa, addr->addrlen) < 0) {
+    killsock(sock);
+    return -2;
   }
 
-  if (getmyip() > 0) {
-    sock = getsock(SOCK_LISTEN);
-    if (sock < 1)
-      return -1;
-
-    egg_bzero((char *) &name, sizeof(struct sockaddr_in));
-    name.sin_family = AF_INET;
-    name.sin_port = htons(*port); /* 0 = just assign us a port */
-    name.sin_addr.s_addr = addr;
-    if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) {
-      killsock(sock);
-      return -1;
-    }
-    /* what port are we on? */
-    addrlen = sizeof(name);
-    if (getsockname(sock, (struct sockaddr *) &name, &addrlen) < 0) {
-      killsock(sock);
-      return -1;
-    }
-    *port = ntohs(name.sin_port);
-    if (listen(sock, 1) < 0) {
-      killsock(sock);
-      return -1;
-    }
+  if (getsockname(sock, &addr->addr.sa, &addr->addrlen) < 0) {
+    killsock(sock);
+    return -1;
+  }
+  if (listen(sock, 1) < 0) {
+    killsock(sock);
+    return -1;
   }
 
   return sock;
@@ -566,75 +545,96 @@
  */
 inline int open_listen(int *port)
 {
-  return open_address_listen(myip[0] ? getmyip() : INADDR_ANY, port);
-}
-
-/* Returns the given network byte order IP address in the
- * dotted format - "##.##.##.##"
- */
-char *iptostr(IP ip)
-{
-  struct in_addr a;
+  int sock;
+  sockname_t name;
 
-  a.s_addr = ip;
-  return inet_ntoa(a);
+  (void) setsockname(&name, listen_ip, *port, 1);
+  sock = open_address_listen(&name);
+  if (name.addr.sa.sa_family == AF_INET)
+    *port = ntohs(name.addr.s4.sin_port);
+#ifdef IPV6
+  else
+    *port = ntohs(name.addr.s6.sin6_port);
+#endif
+  return sock;
 }
 
-/* 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!
+/* Short routine to answer a connect received on a listening socket.
+ * Returned is the new socket.
+ * If port is not NULL, it points to an integer to hold the port number
+ * of the caller.
  */
-int answer(int sock, char *caller, unsigned long *ip, unsigned short *port,
-           int binary)
+int answer(int sock, sockname_t *caller, unsigned short *port, int binary)
 {
   int new_sock;
-  socklen_t addrlen;
-  struct sockaddr_in from;
-
-  addrlen = sizeof(struct sockaddr);
-  new_sock = accept(sock, (struct sockaddr *) &from, &addrlen);
-
+  caller->addrlen = sizeof(caller->addr);
+  new_sock = accept(sock, &caller->addr.sa, &caller->addrlen);
+  
   if (new_sock < 0)
     return -1;
-  if (ip != NULL) {
-    *ip = from.sin_addr.s_addr;
-    /* DNS is now done asynchronously. We now only provide the IP address. */
-    strncpyz(caller, iptostr(*ip), 121);
-    *ip = ntohl(*ip);
-  }
-  if (port != NULL)
-    *port = ntohs(from.sin_port);
-  /* Set up all the normal socket crap */
+
+  caller->family = caller->addr.sa.sa_family;
+  if (port) {
+    if (caller->family == AF_INET)
+      *port = ntohs(caller->addr.s4.sin_port);
+#ifdef IPV6
+    else
+      *port = ntohs(caller->addr.s6.sin6_port);
+#endif
+  }
   setsock(new_sock, (binary ? SOCK_BINARY : 0));
   return new_sock;
 }
 
-/* Like open_telnet, but uses server & port specifications of dcc
+/* Get DCC compatible address for a client to connect (e.g. 1660944385)
+ * If addr is not NULL, it should point to the listening socket's address.
+ * Otherwise, this function will try to figure out the public address of the
+ * machine, using listen_ip and natip.
+ * The result is a string useable for DCC requests
  */
-int open_telnet_dcc(int sock, char *server, char *port)
+int getdccaddr(sockname_t *addr, char *s, size_t l)
 {
-  int p;
-  unsigned long addr;
-  char sv[500];
-  unsigned char c[4];
+  char h[121];
+  sockname_t name, *r = &name;
 
-  if (port != NULL)
-    p = atoi(port);
+  if (addr)
+    r = addr;
   else
-    p = 2000;
-  if (server != NULL)
-    addr = my_atoul(server);
-  else
-    addr = 0L;
-  if (addr < (1 << 24))
-    return -3;                  /* fake address */
-  c[0] = (addr >> 24) & 0xff;
-  c[1] = (addr >> 16) & 0xff;
-  c[2] = (addr >> 8) & 0xff;
-  c[3] = addr & 0xff;
-  sprintf(sv, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]);
-  p = open_telnet_raw(sock, sv, p);
-  return p;
+    setsockname(r, listen_ip, 0, 1);
+  if (
+#ifdef IPV6
+      ((r->family == AF_INET6) &&
+      IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr)) ||
+#endif
+      (r->family == AF_INET && !r->addr.s4.sin_addr.s_addr)) {
+      /* We can't send :: or 0.0.0.0 for dcc, so try
+         to figure out some real address */
+    r = &name;
+    gethostname(h, sizeof h);
+    setsockname(r, h, 0, 1);
+  }
+
+  if (
+#ifdef IPV6
+      ((r->family == AF_INET6) &&
+      IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr)) ||
+#endif
+      (!natip[0] && (r->family == AF_INET) && !r->addr.s4.sin_addr.s_addr))
+    return 0;
+
+#ifdef IPV6
+  if (r->family == AF_INET6) {
+    if (IN6_IS_ADDR_V4MAPPED(&r->addr.s6.sin6_addr) ||
+        IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr))
+      snprintf(s, l, "%lu", natip[0] ? iptolong(inet_addr(natip)) :
+               ntohl((IP) &r->addr.s6.sin6_addr.s6_addr[12]));
+    else
+      inet_ntop(AF_INET6, &r->addr.s6.sin6_addr, s, l);
+  } else
+#endif
+  snprintf(s, l, "%lu", natip[0] ? iptolong(inet_addr(natip)) :
+             ntohl(r->addr.s4.sin_addr.s_addr));
+  return 1;
 }
 
 /* Builds the fd_sets for select(). Eggdrop only cares about readable
@@ -1212,8 +1212,14 @@
    * DNS names that are up to 255 characters long.  This is not broken.
    */
 
-  char badaddress[16];
+#ifdef IPV6
+  char badaddress[INET6_ADDRSTRLEN];
+  sockname_t name;
+  IP ip = 0;
+#else
+  char badaddress[sizeof "255.255.255.255"];
   IP ip = my_atoul(ipaddy);
+#endif
   int prt = atoi(port);
 
   /* It is disabled HERE so we only have to check in *one* spot! */
@@ -1225,9 +1231,19 @@
            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)) {
+#ifdef IPV6
+  if (strchr(ipaddy, ':')) {
+    if (inet_pton(AF_INET6, ipaddy, &name.addr.s6.sin6_addr) != 1) {
+      putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an invalid IPv6 "
+             "address of %s!", nick, from, ipaddy);
+      return 0;
+    }
+    if (IN6_IS_ADDR_V4MAPPED(&name.addr.s6.sin6_addr))
+      ip = ntohl(*(IP *) &name.addr.s6.sin6_addr.s6_addr[12]);
+  }
+#endif
+  if (ip && inet_ntop(AF_INET, &ip, badaddress, sizeof badaddress) &&
+      (ip < (1 << 24))) {
     putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!",
            nick, from, badaddress);
     return 0;
@@ -1235,19 +1251,20 @@
   return 1;
 }
 
-int hostsanitycheck_dcc(char *nick, char *from, IP ip, char *dnsname,
+int hostsanitycheck_dcc(char *nick, char *from, sockname_t *ip, char *dnsname,
                         char *prt)
 {
+  char badaddress[INET6_ADDRSTRLEN];
+
   /* 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 hostn[256], badaddress[16];
+  char hostn[256];
 
   /* It is disabled HERE so we only have to check in *one* spot! */
   if (!dcc_sanitycheck)
     return 1;
-  sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
-          (ip >> 8) & 0xff, ip & 0xff);
+  strcpy(badaddress, iptostr(&ip->addr.sa));
   /* 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...
Index: eggdrop1.8/src/patch.h
diff -u eggdrop1.8/src/patch.h:1.2 eggdrop1.8/src/patch.h:1.3
--- eggdrop1.8/src/patch.h:1.2	Tue Jul 27 15:49:41 2010
+++ eggdrop1.8/src/patch.h	Thu Aug  5 12:12:05 2010
@@ -10,7 +10,7 @@
  * statement, leave the rest of the file alone, this allows better
  * overlapping patches.
  *
- * $Id: patch.h,v 1.2 2010/07/27 21:49:41 pseudo Exp $
+ * $Id: patch.h,v 1.3 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -41,12 +41,12 @@
  *
  *
  */
-patch("1280266983");            /* current unixtime */
+patch("1281021853");            /* current unixtime */
 /*
  *
  *
  */
-patch("highhopes");
+patch("ipv6-full");
 /*
  *
  *
Index: eggdrop1.8/src/proto.h
diff -u eggdrop1.8/src/proto.h:1.1.1.1 eggdrop1.8/src/proto.h:1.2
--- eggdrop1.8/src/proto.h:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/proto.h	Thu Aug  5 12:12:05 2010
@@ -7,7 +7,7 @@
  * because they use structures in those
  * (saves including those .h files EVERY time) - Beldin
  *
- * $Id: proto.h,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: proto.h,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -158,13 +158,13 @@
 void changeover_dcc(int, struct dcc_table *, int);
 
 /* dns.c */
-extern void (*dns_hostbyip) (IP);
+extern void (*dns_hostbyip) (sockname_t *);
+void block_dns_hostbyip(sockname_t *);
+void call_hostbyip(sockname_t *, char *, int);
+void call_ipbyhost(char *, sockname_t *, int);
+void dcc_dnshostbyip(sockname_t *);
 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);
-void dcc_dnshostbyip(IP);
 void dcc_dnsipbyhost(char *);
 
 /* language.c */
@@ -261,20 +261,20 @@
 /* net.c */
 IP my_atoul(char *);
 unsigned long iptolong(IP);
-IP getmyip();
-void neterror(char *);
 void setsock(int, int);
 int allocsock(int, int);
 int alloctclsock(int, int, Tcl_FileProc *, ClientData);
-int getsock(int);
+int getsock(int, int);
 void killsock(int);
 void killtclsock(int);
-int answer(int, char *, unsigned long *, unsigned short *, int);
 inline int open_listen(int *);
-int open_address_listen(IP addr, int *);
+void getvhost(sockname_t *, int);
+int setsockname(sockname_t *, char *, int, int);
+int open_address_listen(sockname_t *);
+int open_telnet_raw(int, sockname_t *);
 int open_telnet(char *, int);
-int open_telnet_dcc(int, char *, char *);
-int open_telnet_raw(int, char *, int);
+int answer(int, sockname_t *, unsigned short *, int);
+int getdccaddr(sockname_t *, char *, size_t);
 void tputs(int, char *, unsigned int);
 void dequeue_sockets();
 int preparefdset(fd_set *, sock_list *, int, int, int);
@@ -282,8 +282,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);
+int hostsanitycheck_dcc(char *, char *, sockname_t *, char *, char *);
+char *iptostr(struct sockaddr *);
 int sock_has_data(int, int);
 int sockoptions(int sock, int operation, int sock_options);
 int flush_inbuf(int idx);
Index: eggdrop1.8/src/tcl.c
diff -u eggdrop1.8/src/tcl.c:1.1.1.1 eggdrop1.8/src/tcl.c:1.2
--- eggdrop1.8/src/tcl.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/tcl.c	Thu Aug  5 12:12:05 2010
@@ -4,7 +4,7 @@
  *   Tcl initialization
  *   getting and setting Tcl/eggdrop variables
  *
- * $Id: tcl.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: tcl.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -46,10 +46,11 @@
 extern time_t online_since;
 
 extern char origbotname[], botuser[], motdfile[], admin[], userfile[],
-            firewall[], helpdir[], notify_new[], hostname[], myip[], moddir[],
+            firewall[], helpdir[], notify_new[], vhost[], moddir[],
             tempdir[], owner[], network[], botnetnick[], bannerfile[],
             egg_version[], natip[], configfile[], logfile_suffix[], log_ts[],
-            textdir[], pid_file[];
+            textdir[], pid_file[], listen_ip[];
+
 
 extern int flood_telnet_thr, flood_telnet_time, shtime, share_greet,
            require_p, keep_all_logs, allow_new_telnets, stealth_telnets,
@@ -61,6 +62,11 @@
            share_unlinks, protect_telnet, sort_users, strict_host,
            resolve_timeout, default_uflags, userfile_perm, cidr_support;
 
+#ifdef IPV6
+extern char vhost6[];
+extern int pref_af;
+#endif
+
 extern struct dcc_t *dcc;
 extern tcl_timer_t *timer, *utimer;
 
@@ -488,8 +494,11 @@
 #endif
   {"notify-newusers", notify_new,     120,                     0},
   {"owner",           owner,          120,           STR_PROTECT},
-  {"my-ip",           myip,           120,                     0},
-  {"my-hostname",     hostname,       120,                     0},
+  {"vhost4",          vhost,          120,                     0},
+#ifdef IPV6
+  {"vhost6",          vhost6,         120,                     0},
+#endif
+  {"listen-addr",     listen_ip,      120,                     0},
   {"network",         network,        40,                      0},
   {"whois-fields",    whois_fields,   1024,                    0},
   {"nat-ip",          natip,          120,                     0},
@@ -553,6 +562,9 @@
   {"enable-simul",          &enable_simul,         0}, /* compat */
   {"debug-output",          &debug_output,         0}, /* compat */
   {"use-console-r",         &use_console_r,        0}, /* compat */
+#ifdef IPV6
+  {"prefer-ipv6",	    &pref_af,		   0},
+#endif
   {NULL,                    NULL,                  0}
 };
 
Index: eggdrop1.8/src/tcldcc.c
diff -u eggdrop1.8/src/tcldcc.c:1.1.1.1 eggdrop1.8/src/tcldcc.c:1.2
--- eggdrop1.8/src/tcldcc.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/tcldcc.c	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * tcldcc.c -- handles:
  *   Tcl stubs for the dcc commands
  *
- * $Id: tcldcc.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: tcldcc.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -26,6 +26,7 @@
 #include "main.h"
 #include "tandem.h"
 #include "modules.h"
+#include <errno.h>
 
 extern Tcl_Interp *interp;
 extern tcl_timer_t *timer, *utimer;
@@ -863,22 +864,20 @@
     Tcl_AppendResult(irp, "out of dcc table space", NULL);
     return TCL_ERROR;
   }
-  sock = getsock(0);
-
+  sock = z = open_telnet(argv[1], atoi(argv[2]));
   if (sock < 0) {
-    Tcl_AppendResult(irp, MISC_NOFREESOCK, NULL);
-    return TCL_ERROR;
-  }
-  z = open_telnet_raw(sock, argv[1], atoi(argv[2]));
-  if (z < 0) {
-    killsock(sock);
-    if (z == -2)
-      strncpyz(s, "DNS lookup failed", sizeof s);
-    else
-      neterror(s);
-    Tcl_AppendResult(irp, s, NULL);
+    switch (sock) {
+      case -3:
+        Tcl_AppendResult(irp, MISC_NOFREESOCK, NULL);
+        break;
+      case -2:
+        Tcl_AppendResult(irp, "DNS lookup failed", NULL);
+        break;
+      default:
+        Tcl_AppendResult(irp, strerror(errno), NULL);
+    }
     return TCL_ERROR;
-  }
+  }            
   i = new_dcc(&DCC_SOCKET, 0);
   dcc[i].sock = sock;
   dcc[i].port = atoi(argv[2]);
@@ -937,27 +936,31 @@
     }
     /* Try to grab port */
     j = port + 20;
-    i = -1;
+    i = -2;
     while (port < j && i < 0) {
       i = open_listen(&port);
       if (i == -1)
-        port++;
-      else if (i == -2)
         break;
-    }
+      else if (i == -2)
+        port++;
+    } 
+
     if (i == -1) {
-      egg_snprintf(msg, sizeof msg, "Couldn't listen on port '%d' on the "
-                   "given address. Please make sure 'my-ip' is set correctly, "
-                   "or try a different port.", realport);
+      egg_snprintf(msg, sizeof msg, "Couldn't listen on port '%d' on the given "
+                   "address: %s", realport, strerror(errno));
       Tcl_AppendResult(irp, msg, NULL);
       return TCL_ERROR;
     } else if (i == -2) {
-      Tcl_AppendResult(irp, "Couldn't assign the requested IP. Please make "
-                       "sure 'my-ip' is set properly.", NULL);
+      egg_snprintf(msg, sizeof msg, "Couldn't listen on port '%d' on the given "
+                   "address. Please make sure 'listen-addr' is set properly"
+                   " or try choosing a different port.", realport);
+      Tcl_AppendResult(irp, msg, NULL);
       return TCL_ERROR;
     }
     idx = new_dcc(&DCC_TELNET, 0);
-    dcc[idx].addr = iptolong(getmyip());
+    dcc[idx].sockname.addrlen = sizeof(dcc[idx].sockname.addr);
+    getsockname(i, &dcc[idx].sockname.addr.sa, &dcc[idx].sockname.addrlen);
+    dcc[idx].sockname.family = dcc[idx].sockname.addr.sa.sa_family;
     dcc[idx].port = port;
     dcc[idx].sock = i;
     dcc[idx].timeval = now;
Index: eggdrop1.8/src/tclmisc.c
diff -u eggdrop1.8/src/tclmisc.c:1.1.1.1 eggdrop1.8/src/tclmisc.c:1.2
--- eggdrop1.8/src/tclmisc.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/tclmisc.c	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * tclmisc.c -- handles:
  *   Tcl stubs for everything else
  *
- * $Id: tclmisc.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: tclmisc.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -434,7 +434,7 @@
 
   BADARGS(1, 1, "");
 
-  egg_snprintf(s, sizeof s, "%lu", iptolong(getmyip()));
+  getdccaddr(NULL, s, sizeof s);
   Tcl_AppendResult(irp, s, NULL);
   return TCL_OK;
 }
Index: eggdrop1.8/src/tcluser.c
diff -u eggdrop1.8/src/tcluser.c:1.1.1.1 eggdrop1.8/src/tcluser.c:1.2
--- eggdrop1.8/src/tcluser.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/tcluser.c	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * tcluser.c -- handles:
  *   Tcl stubs for the user-record-oriented commands
  *
- * $Id: tcluser.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: tcluser.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -311,6 +311,14 @@
   else {
     userlist = adduser(userlist, argv[1], "none", "-", USER_BOT);
     bi = user_malloc(sizeof(struct bot_addr));
+#ifdef IPV6
+  if ((q = strchr(argv[2], '/'))) {
+    if (!q[1]) {
+      *q = 0;
+      q = 0;
+    }
+  } else
+#endif
     q = strchr(argv[2], ':');
     if (!q) {
       bi->address = user_malloc(strlen(argv[2]) + 1);
Index: eggdrop1.8/src/userent.c
diff -u eggdrop1.8/src/userent.c:1.1.1.1 eggdrop1.8/src/userent.c:1.2
--- eggdrop1.8/src/userent.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/userent.c	Thu Aug  5 12:12:05 2010
@@ -2,7 +2,7 @@
  * userent.c -- handles:
  *   user-entry handling, new style more versatile.
  *
- * $Id: userent.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: userent.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -477,6 +477,11 @@
     if ((q = strchr(q, '/')))
       bi->relay_port = atoi(q + 1);
   }
+#ifdef IPV6
+  for (p = bi->address; *p; p++)
+    if (*p == ';')
+      *p = ':';
+#endif
   if (!bi->telnet_port)
     bi->telnet_port = 3333;
   if (!bi->relay_port)
@@ -493,8 +498,19 @@
   int l;
 
   bi = (struct bot_addr *) e->u.extra;
+#ifdef IPV6
+  char *p, *addr = user_malloc(strlen(bi->address) + 1);
+  strcpy(addr, bi->address);
+  for (p = addr; *p; p++)
+    if (*p == ':')
+      *p = ';';
+  l = simple_sprintf(work, "%s:%u/%u", p, bi->telnet_port,
+                       bi->relay_port);
+  nfree(addr);
+#else
   l = simple_sprintf(work, "%s:%u/%u", bi->address, bi->telnet_port,
                      bi->relay_port);
+#endif
   e->u.list = user_malloc(sizeof(struct list_type));
   e->u.list->next = NULL;
   e->u.list->extra = user_malloc(l + 1);
@@ -517,10 +533,25 @@
 {
   register struct bot_addr *bi = (struct bot_addr *) e->u.extra;
 
+#ifdef IPV6
+  char *p, *addr = user_malloc(strlen(bi->address) + 1);
+  strcpy(addr, bi->address);
+  for (p = addr; *p; p++)
+    if (*p == ':')
+      *p = ';';
+  if (fprintf(f, "--%s %s:%u/%u\n", e->type->name, addr,
+      bi->telnet_port, bi->relay_port) == EOF) {
+    nfree(addr);
+    return 0;
+  }
+  nfree(addr);
+  return 1;
+#else
   if (fprintf(f, "--%s %s:%u/%u\n", e->type->name, bi->address,
               bi->telnet_port, bi->relay_port) == EOF)
     return 0;
   return 1;
+#endif
 }
 
 static int botaddr_set(struct userrec *u, struct user_entry *e, void *buf)
Index: eggdrop1.8/src/users.c
diff -u eggdrop1.8/src/users.c:1.1.1.1 eggdrop1.8/src/users.c:1.2
--- eggdrop1.8/src/users.c:1.1.1.1	Mon Jul 26 15:11:06 2010
+++ eggdrop1.8/src/users.c	Thu Aug  5 12:12:05 2010
@@ -10,7 +10,7 @@
  *
  * dprintf'ized, 9nov1995
  *
- * $Id: users.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
+ * $Id: users.c,v 1.2 2010/08/05 18:12:05 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -36,7 +36,6 @@
 #include "chan.h"
 #include "modules.h"
 #include "tandem.h"
-char natip[121] = "";
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
----------------------- End of diff -----------------------


More information about the Changes mailing list