* <http://www.OpenLDAP.org/license.html>.
*/
+==============================================================================
+
+helpers/log_daemon/DB/doc/:
+helpers/log_daemon/DB/log_db_daemon.pl.in:
+
+ Copyright (C) 2008 by Marcello Romani
+
+ This library is free software; you can redistribute it and/or modify
+ it under the same terms as Perl itself, either Perl version 5.8.8 or,
+ at your option, any later version of Perl 5 you may have available.
+Changes to squid-3.2.0.4 (22 Dec 2010):
+
+ - Port 2.x: cache_dir min-size setting
+ - Bug 3059: Crash on digest auth headers with unknown nonce
+ - Fix cachemgr reported HTTP/ICP requests/messages per minute when multiple workers used
+ - Fix cachemgr mem-pools reporting
+ - Add Dynamic SSL certificate generation
+ - Add useragent, referer, combined built-in log formats
+ - Obsolete log_fqdn directive
+ - Obsolete useragent/referer/forward_log directives
+ - HTTP/1.1: Send 1.1 on CONNECT responses
+ - Updated Kerberos support for newer GSSAPI releases
+ - Improve handling of adapted body delivery failures in REQMOD request satisfaction mode
+ - Improve handling of early eCAP transaction failures
+ - Various ext_edirectory_acl fixes
+ - ... all bug and feature fixes included in 3.1.10 release
+ - ... and a lot of code and documentation polishing
+
Changes to squid-3.2.0.3 (07 Nov 2010):
- Regression fix: SMP broke ICP outgoing IP lookup if no udp_outgoing_addr set
- ... and a great many testing improvements
- ... and many documentation updates
+Changes to squid-3.1.10 (22 Dec 2010):
+
+ - Bug 3121: memory leak in DigestAuth: AuthUser object is locked twice
+ - Bug 3113: Consuming too much memory when uploading files
+ - Bug 3110: 'reply_body_max_size none' does not work with x-forwarded-for
+ - Bug 3096: Consuming too much memory when delaying traffic
+ - Bug 3091: Bypassed ICAP errors are not counted as service failures
+ - Bug 3090: Polish FTP login error handing
+ - Bug 3068: cache_dir capacity and usage overflows
+ - Bug 3028: Permit wbinfo_group.pl to authenticate Kerberos users with NT domain
+ - Bug 427: HTTP Compliance: Support If-Match and If-None-Match requests
+ - Fix memory leak in adaptation_access
+ - Fix /dev/poll and poll() selection priority
+ - Fix PREFIX/var/run creation during install
+ - Fix cachemgr http_port config report display
+ - Add upgrade help process for obsolete options
+ - Accept RFC 2965 Set-Cookie2 / Cookie2 headers as 'known'
+ - HTTP/1.1: entry is stale if request has max-age=0
+ - HTTP/1.1: do not forward TRACE with Max-Forwards: 0 after REQMOD
+ - Toolchain update to support newer auto-tools
+ - ... and updated error page translations
+ - ... and updated documentation
+ - ... and some code optimization/simplification polish
+
Changes to squid-3.1.9 (25 Oct 2010):
- Bug 3088: dnsserver is segfaulting
Provided developement and testing resources for Solaris /dev/poll
support.
+
+Yahoo! Inc. - http://www.yahoo.com/
+
+ Yahoo! Inc. supported the development of improved refresh
+ logics. Many thanks to Yahoo! Inc. for supporting the development
+ of these features.
#endif
]])],[squid_cv_compiler="sunstudio"],[])
fi
+ dnl Intel CC
+ if test -z "$squid_cv_compiler" ; then
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+#if !defined(__ICC)
+#error "not Intel(R) C++ Compiler"
+#endif
+ ]])],[squid_cv_compiler="icc"],[])
+ fi
dnl end of block to be repeated
if test -z "$squid_cv_compiler" ; then
squid_cv_compiler="none"
squid_cv_cc_option_optimize="-fast"
squid_cv_cc_arg_pipe=""
;;
+ icc)
+ squid_cv_cxx_option_werror="-Werror"
+ squid_cv_cc_option_werror="$squid_cv_cxx_option_werror"
+ squid_cv_cc_option_wall="-Wall"
+ squid_cv_cc_option_optimize="-O2"
+ squid_cv_cc_arg_pipe=""
+ ;;
*)
squid_cv_cxx_option_werror=""
squid_cv_cc_option_werror=""
dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
dnl these checks must be performed in the same order as here defined,
-dnl and have mostly been lifted out of an inlined configure.in.
+dnl and have mostly been lifted out of an inlined configure.ac.
dnl checks for a broken solaris header file, and sets squid_cv_broken_krb5_h
dnl to yes if that's the case
]) dnl SQUID_CHECK_KRB5_SOLARIS_BROKEN_KRB5_H
+AC_DEFUN([SQUID_CHECK_KRB5_HEIMDAL_BROKEN_KRB5_H], [
+ AC_CACHE_CHECK([for broken Heimdal krb5.h],squid_cv_broken_heimdal_krb5_h, [
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <krb5.h>
+int
+main(void)
+{
+ krb5_context context;
+
+ krb5_init_context(&context);
+
+ return 0;
+}
+]])], [ squid_cv_broken_heimdal_krb5_h=no ], [
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#include <krb5.h>
+#if defined(__cplusplus)
+}
+#endif
+int
+main(void)
+{
+ krb5_context context;
+
+ krb5_init_context(&context);
+
+ return 0;
+}
+]])], [ squid_cv_broken_heimdal_krb5_h=yes ], [ squid_cv_broken_heimdal_krb5_h=no ])
+ ])
+ ])
+]) dnl SQUID_CHECK_KRB5_HEIMDAL_BROKEN_KRB5_H
+
dnl check the max skew in the krb5 context, and sets squid_cv_max_skew_context
AC_DEFUN([SQUID_CHECK_MAX_SKEW_IN_KRB5_CONTEXT],[
AC_CACHE_CHECK([for max_skew in struct krb5_context],
KRB5INT_BEGIN_DECLS
#endif
#endif
+#if HAVE_BROKEN_HEIMDAL_KRB5_H
+extern "C" {
#include <krb5.h>
+}
+#else
+#include <krb5.h>
+#endif
#endif
int
squid_cv_resuid_works="no" ],[:])
)
])
+
+dnl check that we have functional CPU clock access for the profiler
+dnl sets squid_cv_profiler_works to "yes" or "no"
+
+AC_DEFUN([SQUID_CHECK_FUNCTIONAL_CPU_PROFILER],[
+ AC_CACHE_CHECK([for operational CPU clock access],
+ squid_cv_cpu_profiler_works,
+ AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
+#if defined(__GNUC__) && ( defined(__i386) || defined(__i386__) )
+// okay
+#elif defined(__GNUC__) && ( defined(__x86_64) || defined(__x86_64__) )
+// okay
+#elif defined(__GNUC__) && defined(__alpha)
+// okay
+#elif defined(_M_IX86) && defined(_MSC_VER) /* x86 platform on Microsoft C Compiler ONLY */
+// okay
+#else
+#error This CPU is unsupported. No profiling available here.
+#endif
+ ]])],[
+ squid_cv_cpu_profiler_works=yes],[
+ squid_cv_cpu_profiler_works=no])
+ )
+])
#!/bin/sh
-# Used to setup the configure.in, autoheader and Makefile.in's if configure
+# Used to setup the configure.ac, autoheader and Makefile.in's if configure
# has not been generated. This script is only needed for developers when
# configure has not been run, or if a Makefile.am in a non-configured directory
# has been updated
# Autotool versions preferred. To override either edit the script
# to match the versions you want to use, or set the variables on
# the command line like "env acver=.. amver=... ./bootstrap.sh"
-acversions="${acver:-2.64 2.63 2.62 2.61}"
-amversions="${amver:-1.11 1.10 1.9}"
-ltversions="${ltver:-2.2}"
+acversions="${acver:-.}" # 2.68 2.67 2.66 2.65 2.64 2.63 2.62 2.61}"
+amversions="${amver:-.}" # 1.11 1.10 1.9}"
+ltversions="${ltver:-.}" # 2.2}"
check_version()
{
show_version()
{
tool=$1
- found="NOT_FOUND"
- shift
- versions="$*"
- for version in $versions; do
- for variant in "" "${version}" "-${version}" "`echo $version | sed -e 's/\.//g'`"; do
- if check_version $tool ${tool}${variant} $version; then
- found="${version}"
- break
- fi
- done
- if [ "x$found" != "xNOT_FOUND" ]; then
- break
- fi
- done
- if [ "x$found" = "xNOT_FOUND" ]; then
- found="??"
- fi
- echo $found
+ variant=$2
+ ${tool}${variant} --version 2>/dev/null | head -1 | sed -e 's/.*) //'
}
find_variant()
# TODO: when we have libtool2, tell libtoolize where to put its files
# instead of manualy moving files from ltdl to lib/libLtdl
- if egrep -q '^[[:space:]]*AC_LIBLTDL_' configure.in
+ if egrep -q '^[[:space:]]*AC_LIBLTDL_' configure.ac
then
ltdl="--ltdl"
else
ltver=`find_variant libtool ${ltversions}`
# Produce debug output about what version actually found.
-amversion=`show_version automake ${amversions}`
-acversion=`show_version autoconf ${acversions}`
-ltversion=`show_version libtool ${ltversions}`
+amversion=`show_version automake "${amver}"`
+acversion=`show_version autoconf "${acver}"`
+ltversion=`show_version libtool "${ltver}"`
# Find the libtool path to get the right aclocal includes
ltpath=`find_path libtool$ltver`
/* Assumes a `char *destination' variable. */
#define REGEX_REALLOCATE(source, osize, nsize) \
(destination = (char *) alloca (nsize), \
- xmemcpy (destination, source, osize), \
+ memcpy (destination, source, osize), \
destination)
#endif /* not REGEX_MALLOC */
osdetect.h \
psignal.h \
stdvarargs.h \
+ strnstr.cc \
strsep.h \
strtoll.h \
tempnam.h \
valgrind.h \
xalloc.cc \
xalloc.h \
+ xis.h \
xstrerror.cc \
xstrerror.h \
xstring.cc \
--- /dev/null
+/**
+\defgroup compat Portability Library
+
+\title Squid Portability
+
+
+\section 1 Aim
+
+\par
+Squid aims to build and run on many modern systems. To do this we have traditionally
+added small hacks and wrappers all over the code whenever one was needed.
+The final result of that is a vast amount of code duplication, dodgy licensing on
+some older hacks, and some cases of obsolete algorithms sitting side by side with their
+current equivalent.
+
+\par
+The Portability library libcompat-squid.la has been created to correct the three issues of
+stable build portability, code cleanliness, and clearer licensing.
+
+
+\section 2 Requirements
+
+\par
+The system calls used by Squid are not required to be standard. Often we depend on
+some non-standard call which can give great performance benefits.
+But they are required to meet several other criteria:
+ \li They must be of actual benefit to Squid during its operation.
+ \li A better alternative must not exist.
+ \li If not available on all OS an open-source GPLv2+ implementation must be available
+ to be included with the Squid sources and used when required.
+
+\par
+To be built into the libcompat-squid.la as a layer below all Squid-bundled binaries. The code
+must also qualify by being provided natively by some OS where Squid builds. \br
+Code and Algorithms which do not meet this final criteria are relegated to the slightly
+higher level of basic component, rather than portability.
+
+
+\section 3 Component Types
+
+\par Macro re-definition
+Where the only difference between systems is their naming scheme. One of the schemes is
+chosen by the developers for use and mappings are created in the form of Macros.
+
+\par Inline Functions
+
+\par Algorithm Templates and Inline functions
+Being C++ we are able to use templates in place of inline functions where that is more
+convenient. Care is taken to provide no additional requirements upon the callers when
+using the template as to when using the native constructs.
+
+\par Emulators
+As mentioned above if a useful library function calls or global is not available on all
+operating systems a GPLv2+ alternative may be added to the compat layer. As an emulator
+it retains the exact naming and definition of the source systems. Thus being able to be
+used seamlessly across all platforms by the main code.
+
+\par Wrappers
+Sometimes common and useful library functions are not always as safe as they could be.
+An alternative which wraps the original in extra safety checks is provided under the
+same name with an 'x' pre-pended. Currently these extra protections are added on string
+handling and memory allocation.
+
+
+\section 4 Layout
+The internal code structure of libcompat-squid.la files has a hierarchy. The API has a flat
+global scope separate from the file layout. The API is pulled in by including compat/compat.h.
+The strict dependency requirements which exist within the compat API make including
+individual part separately a risky operation.
+
+\par
+Squid coding guidelines require each .c and .cc file to include config.h or squid.h first
+in their included files. config.h begin with an order-specific sequence of defines and
+includes compat/compat.h to incorporate the compat layer appropriately in every soure file.
+squid.h begins by including config.h to prepare for its sub-includes and definitions.
+
+\par
+Internally the compat/ directory contains the public API file compat/compat.h which structures
+order-specific includes as documented inside that file. Included by that is compat/osdetect.h
+which determines which operating system and in some cases compiler is being used.
+
+\par
+The compat/os/ directory contains separate files for each supported system which requires
+special compat layer handling. Hacks for specific systems should be restricted to these files
+as much as possible.
+
+\par
+compat/compat_shared.h file contains the shared portability definitions which are shared
+across a great many systems. These should be written with protective macros to prevent any
+symbols or code being defined which is not necessary. Protections here must not be system-specific.
+
+\par
+Also in compat/ directory are the .h and .c files for emulators detected by autoconf. These
+are added by autoconf to the build objects as required.
+
+*/
#include "compat/xstrerror.h"
#include "compat/xstring.h"
#include "compat/xstrto.h"
+#include "compat/xis.h"
+#if !HAVE_MEMCPY
+#if HAVE_BCOPY
+#define memcpy(d,s,n) bcopy((s),(d),(n))
+#elif HAVE_MEMMOVE
+#define memcpy(d,s,n) memmove((d),(s),(n))
+#endif
+#endif
+
+#if !HAVE_MEMMOVE && HAVE_BCOPY
+#define memmove(d,s,n) bcopy((s),(d),(n))
+#endif
+
+/*
+ * strnstr() is needed. The OS may not provide a working copy.
+ */
+#if HAVE_STRNSTR
+/* If strnstr exists and is usable we do so. */
+#define squid_strnstr(a,b,c) strnstr(a,b,c)
+#else
+/* If not we have our own copy imported from FreeBSD */
+const char * squid_strnstr(const char *s, const char *find, size_t slen);
+#endif
+
+#if __GNUC__
+#if !defined(PRINTF_FORMAT_ARG1)
+#define PRINTF_FORMAT_ARG1 __attribute__ ((format (printf, 1, 2)))
+#endif
+#if !defined(PRINTF_FORMAT_ARG2)
+#define PRINTF_FORMAT_ARG2 __attribute__ ((format (printf, 2, 3)))
+#endif
+#if !defined(PRINTF_FORMAT_ARG3)
+#define PRINTF_FORMAT_ARG3 __attribute__ ((format (printf, 3, 4)))
+#endif
+#else /* !__GNU__ */
+#define PRINTF_FORMAT_ARG1
+#define PRINTF_FORMAT_ARG2
+#define PRINTF_FORMAT_ARG3
+#endif
#endif /* _SQUID_COMPAT_SHARED_H */
#ifndef SQUID_OS_MSWIN_H
#define SQUID_OS_MSWIN_H
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#define ACL WindowsACL
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
SQUIDCEXTERN size_t getpagesize(void);
#endif
-#endif /* _SQUID_WIN32_ */
+/* gcc doesn't recognize the Windows native 64 bit formatting tags causing
+ * the compile fail, so we must disable the check on native Windows.
+ */
+#if __GNUC__
+#define PRINTF_FORMAT_ARG1
+#define PRINTF_FORMAT_ARG2
+#define PRINTF_FORMAT_ARG3
+#endif
+
+#endif /* _SQUID_WINDOWS_ */
#endif /* SQUID_OS_MSWIN_H */
#include <sys/resource.h>
SQUIDCEXTERN int getrusage(int, struct rusage *);
-
/**
* prototypes for system function missing from system includes
* on some Solaris systems.
#ifndef SQUID_OS_WINDOWS_H
#define SQUID_OS_WINDOWS_H
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#ifndef ACL
#define ACL WindowsACL
#undef _MSWIN_ACL_WAS_NOT_DEFINED
#endif
-#endif /* _SQUID_WIN32_ */
+#endif /* _SQUID_WINDOWS_ */
#endif /* SQUID_OS_WINDOWS_H */
#elif defined(__DragonFly__)
#define _SQUID_DRAGONFLY_ 1
-#elif defined(__CYGWIN32__) || defined(__CYGWIN__)
+#elif defined(__CYGWIN32__) || defined(__CYGWIN__)
#define _SQUID_CYGWIN_ 1
-#define _SQUID_WIN32_ 1
+#define _SQUID_WINDOWS_ 1
+
+#elif defined(__MINGW32__) || defined(__MINGW__)
+#define _SQUID_MINGW_ 1
+#define _SQUID_WINDOWS_ 1
#elif defined(WIN32) || defined(WINNT) || defined(__WIN32__) || defined(__WIN32)
/* We are using _SQUID_MSWIN_ define in cf.data.pre, so
it must be defined to 1 to avoid the build failure of cfgen.
*/
#define _SQUID_MSWIN_ 1
-#define _SQUID_WIN32_ 1
+#define _SQUID_WINDOWS_ 1
#elif defined(__APPLE__)
#define _SQUID_APPLE_ 1
-#ifndef _SQUID_COMPAT_STRNSTR_C_
-#define _SQUID_COMPAT_STRNSTR_C_
+#ifndef _SQUID_COMPAT_STRNSTR_CC_
+#define _SQUID_COMPAT_STRNSTR_CC_
+
/*
* Shamelessly duplicated from the FreeBSD public sources
* for use by the Squid Project under GNU Public License.
*/
#include "config.h"
-#include "strnstr.h"
#if !HAVE_STRNSTR
#include <string.h>
#endif
-/*
+/**
* Find the first occurrence of find in s, where the search is limited to the
* first slen characters of s.
*/
}
#endif /* !HAVE_STRNSTR */
-#endif /* _SQUID_COMPAT_STRNSTR_C_ */
+#endif /* _SQUID_COMPAT_STRNSTR_CC_ */
for (; i <= XMS_DBG_MAXSIZE; i += XMS_DBG_GRAIN)
func(i, malloc_sizes[XMS_DBG_INDEX(i)], malloc_histo[XMS_DBG_INDEX(i)], data);
- xmemcpy(&malloc_histo, &malloc_sizes, sizeof(malloc_sizes));
+ memcpy(&malloc_histo, &malloc_sizes, sizeof(malloc_sizes));
}
#endif /* XMALLOC_STATISTICS */
if (failure_notify) {
static char msg[128];
snprintf(msg, 128, "xcalloc: Unable to allocate %Zu blocks of %Zu bytes!\n", n, sz);
- (*failure_notify) (msg);
+ failure_notify(msg);
} else {
perror("xcalloc");
}
if (failure_notify) {
static char msg[128];
snprintf(msg, 128, "xmalloc: Unable to allocate %Zu bytes!\n", sz);
- (*failure_notify) (msg);
+ failure_notify(msg);
} else {
perror("malloc");
}
if (failure_notify) {
static char msg[128];
snprintf(msg, 128, "xrealloc: Unable to reallocate %Zu bytes!\n", sz);
- (*failure_notify) (msg);
+ failure_notify(msg);
} else {
perror("realloc");
}
*/
#define safe_free(x) while (x) { xxfree(x); (x) = NULL; }
-
-#if XMALLOC_STATISTICS
- void malloc_statistics(void (*func) (int, int, int, void *), void *data);
-#endif
-
#ifdef __cplusplus
}
#endif
+#if XMALLOC_STATISTICS
+extern void malloc_statistics(void (*func) (int, int, int, void *), void *data);
+#endif
+
#endif /* _SQUID_COMPAT_XALLOC_H */
--- /dev/null
+#ifndef _SQUID_COMPAT_XIS_H
+#define _SQUID_COMPAT_XIS_H
+
+#if HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#define xisspace(x) isspace((unsigned char)x)
+#define xtoupper(x) toupper((unsigned char)x)
+#define xtolower(x) tolower((unsigned char)x)
+#define xisdigit(x) isdigit((unsigned char)x)
+#define xisascii(x) isascii((unsigned char)x)
+#define xislower(x) islower((unsigned char)x)
+#define xisalpha(x) isalpha((unsigned char)x)
+#define xisprint(x) isprint((unsigned char)x)
+#define xisalnum(x) isalnum((unsigned char)x)
+#define xiscntrl(x) iscntrl((unsigned char)x)
+#define xispunct(x) ispunct((unsigned char)x)
+#define xisupper(x) isupper((unsigned char)x)
+#define xisxdigit(x) isxdigit((unsigned char)x)
+#define xisgraph(x) isgraph((unsigned char)x)
+
+#endif /* _SQUID_COMPAT_XIS_H */
}
exit(1);
}
- if (n < 0) {
- errno = EINVAL;
- if (failure_notify) {
- (*failure_notify) ("xstrndup: tried to dup a negative length string!\n");
- } else {
- perror("xstrndup: tried to dup a negative length string!");
- }
- exit(1);
- }
sz = strlen(s) + 1;
+ // size_t is unsigned, as mandated by c99 and c++ standards.
if (sz > n)
sz = n;
AC_CANONICAL_HOST
AC_MSG_CHECKING([simplified host os])
-squid_host_os=`echo $host_os|sed 's/[0-9].*//;s/-.*//g'`
+simple_host_os=`echo $host_os|sed 's/[0-9].*//g;s/-.*//g'`
squid_host_os_version=`echo $host_os|tr -d "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"`
+if test -n "$squid_host_os_version"; then
+ squid_host_os="`echo $simple_host_os| sed s/$squid_host_os_version//g`"
+else
+ squid_host_os="$simple_host_os"
+fi
AC_MSG_RESULT($squid_host_os (version $squid_host_os_version))
# on windows squid_host_os is either mingw or cygwin, version is 32
dnl set squid required flags
if test "x$GCC" = "xyes"; then
+ case "$squid_host_os" in
+ mingw)
dnl Guido Serassio (serassio@squid-cache.org) 20070811
dnl Using the latest MinGW (gcc 3.4.5 + mingw-runtime 3.13) cannot build with
dnl -Werror -Wmissing-prototypes -Wmissing-declarations
dnl TODO: check if the problem will be present in any other newer MinGW release.
- case "$host_os" in
- mingw|mingw32)
SQUID_CFLAGS="$squid_cv_cc_option_wall -Wpointer-arith -Wwrite-strings -Wcomments"
;;
+ freebsd)
+ # FreeBSD places local libraries and packages in /usr/local
+ CFLAGS="$CFLAGS -I/usr/local/include"
+ CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib -Wl,-R/usr/local/lib"
+ ;;
*)
SQUID_CFLAGS="$squid_cv_cc_option_wall -Wpointer-arith -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wcomments"
;;
AC_MSG_NOTICE([Windows threads support automatically enabled])
;;
freebsd)
- SQUID_CFLAGS="$SQUID_CFLAGS -D_REENTRANT"
- SQUID_CXXFLAGS="$SQUID_CXXFLAGS -D_REENTRANT"
- if test "x$GCC" = "xyes" -a "x$PRESET_LDFLAGS" = "x" ; then
- LDFLAGS="$LDFLAGS -pthread"
+ if test `echo "$squid_host_os_version" | cut -b1` -lt 7 ; then
+ AC_MSG_NOTICE(pthread library requires FreeBSD 7 or later)
+ squid_opt_use_diskthreads="no"
+ else
+ SQUID_CFLAGS="$SQUID_CFLAGS -D_REENTRANT"
+ SQUID_CXXFLAGS="$SQUID_CXXFLAGS -D_REENTRANT"
+ if test "x$GCC" = "xyes" -a "x$PRESET_LDFLAGS" = "x" ; then
+ LDFLAGS="$LDFLAGS -pthread"
+ fi
fi
;;
solaris)
else
dnl Windows does things differently. We provide wrappers.
dnl TODO: Windows really needs its own DiskIO module or its Overlaped IO
- case "$host_os" in
- mingw|mingw32)
+ case "$squid_host_os" in
+ mingw)
squid_opt_use_aio="yes"
AC_MSG_NOTICE([Windows being built. Maybe-enable POSIX AIO.])
;;
DISK_MODULES="$DISK_MODULES AIO"
DISK_LIBS="$DISK_LIBS libAIO.a"
DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/AIO/AIODiskIOModule.o"
- case "$host_os" in
- mingw|mingw32)
+ case "$squid_host_os" in
+ mingw)
USE_AIO_WIN32=1
AC_MSG_NOTICE([Replacing AIO DiskIO module with: Windows overlapped I/O support])
;;
if ! test "x$squid_disk_module_candidates_AIO" = "xyes"; then
AC_MSG_ERROR([COSS requires POSIX AIO which is not available.])
fi
- # Automake om MinGW needs explicit exe extension
+ # Automake on MinGW needs explicit exe extension
# for STORE_TESTS substition
STORE_TESTS="$STORE_TESTS tests/testCoss$EXEEXT"
;;
[ if test "x$enableval" = "xyes" ; then
AC_MSG_NOTICE([Delay pools enabled])
AC_DEFINE([USE_DELAY_POOLS],1,[Traffic management via "delay pools".])
- AM_CONDITIONAL(ENABLE_DELAY_POOLS, true,)
+ AM_CONDITIONAL(ENABLE_DELAY_POOLS, true)
fi
])
if test "x$squid_opt_use_esi" = "xyes" -a "x$with_libxml2" != "xno" ; then
AC_CHECK_LIB([xml2], [main], [XMLLIB="-lxml2"; HAVE_LIBXML2=1])
dnl Find the main header and include path...
+ ac_cv_libxml2_include='no'
AC_CHECK_HEADERS([libxml/parser.h], [], [
+ AC_MSG_NOTICE([Testing in /usr/include/libxml2])
SAVED_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="-I/usr/include/libxml2 $CPPFLAGS"
unset ac_cv_header_libxml_parser_h
- AC_CHECK_HEADERS([libxml/parser.h], [ac_cv_libxml2_include=yes], [])
+ AC_CHECK_HEADERS([libxml/parser.h], [ac_cv_libxml2_include="/usr/include/libxml2"], [])
CPPFLAGS="$SAVED_CPPFLAGS"
+ if test "x$ac_cv_libxml2_include" = "xno"; then
+ AC_MSG_NOTICE([Testing in /usr/local/include/libxml2])
+ SAVED_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="-I/usr/local/include/libxml2 $CPPFLAGS"
+ unset ac_cv_header_libxml_parser_h
+ AC_CHECK_HEADERS([libxml/parser.h], [ac_cv_libxml2_include="/usr/local/include/libxml2"], [])
+ CPPFLAGS="$SAVED_CPPFLAGS"
+ fi
])
- if test "x$ac_cv_libxml2_include" = "xyes"; then
- SQUID_CXXFLAGS="-I/usr/include/libxml2 $SQUID_CXXFLAGS"
- CPPFLAGS="-I/usr/include/libxml2 $CPPFLAGS"
+ if test "x$ac_cv_libxml2_include" != "xno"; then
+ SQUID_CXXFLAGS="-I$ac_cv_libxml2_include $SQUID_CXXFLAGS"
+ CPPFLAGS="-I$ac_cv_libxml2_include $CPPFLAGS"
fi
dnl Now that we know where to look find the other headers...
AC_CHECK_HEADERS(libxml/HTMLparser.h libxml/HTMLtree.h)
dnl ])
-AC_ARG_ENABLE(useragent-log,
- AS_HELP_STRING([--enable-useragent-log],
- [Enable logging of User-Agent header]), [
-SQUID_YESNO([$enableval],
- [unrecognized argument to --enable-useragent-log: $enableval])
- enable_useragent_log=$enableval
-])
-SQUID_DEFINE_BOOL(USE_USERAGENT_LOG,${enable_useragent_log:=no},
- [If you want to log User-Agent request header values, define this.])
-AC_MSG_NOTICE([User-Agent logging enabled: $enable_useragent_log])
-
-AC_ARG_ENABLE(referer-log,
- AS_HELP_STRING([--enable-referer-log],[Enable logging of Referer header]), [
-SQUID_YESNO([$enableval],
- [unrecognized argument to --enable-referer-log: $enableval])
-])
-SQUID_DEFINE_BOOL(USE_REFERER_LOG,${enable_referer_log:=no},
- [If you want to log Referer request header values, define this.
- By default, they are written to referer.log in the Squid logdir.
- This feature is deprecated in favour of custom log formats])
-AC_MSG_NOTICE([Referer logging enabled: $enable_referer_log])
-
AC_ARG_ENABLE(wccp,
AS_HELP_STRING([--disable-wccp],[Disable Web Cache Coordination Protocol]), [
SQUID_YESNO([$enableval],[unrecognized argument to --disable-wccp: $enableval])
])
SQUID_DEFINE_BOOL(SQUID_SNMP,${enable_snmp:=yes},
[Define to enable SNMP monitoring of Squid])
-AM_CONDITIONAL(USE_SNMP, [test "x$enable_snmp" = "xyes"])
+AM_CONDITIONAL(ENABLE_SNMP, [test "x$enable_snmp" = "xyes"])
if test "x$enable_snmp" = "xyes"; then
- SNMPLIB='../snmplib/libsnmp.a'
+ SNMPLIB='../snmplib/libsnmplib.a'
makesnmplib=snmplib
fi
AC_MSG_NOTICE([SNMP support enabled: $enable_snmp])
AS_HELP_STRING([--disable-select],[Disable select(2) support.]),
[
SQUID_YESNO($enableval,[--disable-select takes no extra argument])
-test "x$enableval" = "xyes" && squid_opt_io_loop_engine="select"
+if test "x$enableval" = "xyes"; then
+ if test "x$squid_host_os" = "xmingw"; then
+ squid_opt_io_loop_engine="select_win32"
+ else
+ squid_opt_io_loop_engine="select"
+ fi
+fi
])
AC_MSG_NOTICE([enabling select syscall for net I/O: ${enable_select:=auto}])
AC_MSG_ERROR([--with-netfilter-conntrack specified but libnetfilter-conntrack headers not found])
fi
with_netfilter_conntrack=no])
+ # If nothing is broken; enable the libraries usage.
+ if test "x$with_netfilter_conntrack" != "xno"; then
+ with_netfilter_conntrack=yes
+ fi
fi
AC_MSG_NOTICE([Linux Netfilter Conntrack support enabled: ${with_netfilter_conntrack} ${squid_opt_netfilterconntrackpath}])
SQUID_CHECK_KRB5_SOLARIS_BROKEN_KRB5_H
if test "x$squid_cv_broken_krb5_h" = "xyes"; then
- AC_DEFINE(HAVE_BROKEN_SOLARIS_KRB5_H, 1, [Define to 1 if krb5.h is broken for C++])
+ AC_DEFINE(HAVE_BROKEN_SOLARIS_KRB5_H, 1, [Define to 1 if Solaris krb5.h is broken for C++])
AC_MSG_WARN([You have a broken Solaris <krb5.h> system include.])
AC_MSG_WARN([Please see http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6837512])
AC_MSG_WARN([If you need Kerberos support you'll have to patch])
AC_MSG_WARN([your system. See contrib/solaris/solaris-krb5-include.patch])
fi
+ SQUID_CHECK_KRB5_HEIMDAL_BROKEN_KRB5_H
+ if test "x$squid_cv_broken_heimdal_krb5_h" = "xyes"; then
+ AC_DEFINE(HAVE_BROKEN_HEIMDAL_KRB5_H, 1, [Define to 1 if Heimdal krb5.h is broken for C++])
+ fi
AC_CHECK_HEADERS(krb5.h com_err.h et/com_err.h)
ac_com_error_message=no
AC_MSG_ERROR(Neither SASL nor SASL2 found)
])
])
- case "$host_os" in
+ case "$squid_host_os" in
Darwin)
if test "$ac_cv_lib_sasl2_sasl_errstring" = "yes" ; then
AC_DEFINE(HAVE_SASL_DARWIN,1,[Define to 1 if Mac Darwin without sasl.h])
SQUID_YESNO([$enableval],
[unrecognized argument to --enable-cpu-profiling: $enableval])
])
+# Default OFF. This is a debug feature. Only check and enable if forced ON.
+if test "x$enable_cpu_profiling" = "xyes"; then
+ SQUID_CHECK_FUNCTIONAL_CPU_PROFILER
+ if test "x$squid_cv_cpu_profiler_works" = "xno"; then
+ AC_MSG_ERROR([CPU profiling will not be functional in this build.])
+ fi
+fi
SQUID_DEFINE_BOOL(USE_XPROF_STATS,${enable_cpu_profiling:=no},
[Define to enable CPU profiling within Squid])
AM_CONDITIONAL(ENABLE_XPROF_STATS,
SQUID_HAVE_STRUCT_MALLINFO
dnl Override rusage() detect on MinGW because is emulated in source code
-case "$host_os" in
- mingw|mingw32)
+case "$squid_host_os" in
+ mingw)
AC_DEFINE(HAVE_STRUCT_RUSAGE)
ac_cv_func_getrusage='yes'
AC_MSG_NOTICE([Using own rusage on Windows.])
esac
fi
-case "$host_os" in
-mingw|mingw32)
- AC_MSG_NOTICE([Use MSVCRT for math functions.])
- ;;
- *)
- dnl rint() and log() are only used in old C code for now.
- AC_LANG_PUSH([C])
- AC_SEARCH_LIBS([rint],[m])
- AC_SEARCH_LIBS([log],[m])
- AC_LANG_POP([C])
- ;;
+case "$squid_host_os" in
+ mingw)
+ AC_MSG_NOTICE([Use MSVCRT for math functions.])
+ ;;
+ *)
+ dnl rint() and log() are only used in old C code for now.
+ AC_LANG_PUSH([C])
+ AC_SEARCH_LIBS([rint],[m])
+ AC_SEARCH_LIBS([log],[m])
+ AC_LANG_POP([C])
+ ;;
esac
dnl On MinGW OpenLDAP is not available, so LDAP helpers can be linked
dnl only with Windows LDAP libraries using -lwldap32
-case "$host_os" in
- mingw|mingw32)
+case "$squid_host_os" in
+ mingw)
LDAPLIB="-lwldap32"
LBERLIB=""
;;
esac
fi
-dnl Override statfs() detect on MinGW becasue is emulated in source code
-case "$host_os" in
-mingw|mingw32)
+dnl Override statfs() detect on MinGW because it is emulated in source code
+if test "x$squid_host_os" = "xmingw" ; then
ac_cv_func_statfs='yes'
- ;;
-esac
+fi
dnl Check for library functions
AC_CHECK_FUNCS(\
squid_opt_io_loop_engine="devpoll"
elif test "x$enable_poll" != "xno" -a "x$ac_cv_func_poll" = "xyes" ; then
squid_opt_io_loop_engine="poll"
-elif test "x$enable_select" != "xno" -a "x$ac_cv_func_select" = "xyes" ; then
+elif test "x$enable_select" != "xno" -a "x$ac_cv_func_select" = "xyes"; then
squid_opt_io_loop_engine="select"
- if test "x$squid_host_os" = "xmingw" ; then
- squid_opt_io_loop_engine="select_win32"
- fi
+elif test "x$enable_select" != "xno" -a "x$squid_host_os" = "xmingw"; then
+ squid_opt_io_loop_engine="select_win32"
else
AC_MSG_WARN([Eep! Cannot find epoll, kqueue, /dev/poll, poll or select!])
AC_MSG_WARN([Will try select and hope for the best.])
AM_CONDITIONAL([USE_POLL], [test $squid_opt_io_loop_engine = poll])
AM_CONDITIONAL([USE_EPOLL], [test $squid_opt_io_loop_engine = epoll])
AM_CONDITIONAL([USE_SELECT], [test $squid_opt_io_loop_engine = select])
-AM_CONDITIONAL([USE_SELECT_SIMPLE], [test $squid_opt_io_loop_engine = select_simple])
AM_CONDITIONAL([USE_SELECT_WIN32], [test $squid_opt_io_loop_engine = select_win32])
AM_CONDITIONAL([USE_KQUEUE], [test $squid_opt_io_loop_engine = kqueue])
AM_CONDITIONAL([USE_DEVPOLL], [test $squid_opt_io_loop_engine = devpoll])
src/ipc/Makefile \
src/ssl/Makefile \
src/mgr/Makefile \
+ src/snmp/Makefile \
contrib/Makefile \
snmplib/Makefile \
icons/Makefile \
helpers/external_acl/unix_group/Makefile \
helpers/external_acl/wbinfo_group/Makefile \
helpers/log_daemon/Makefile \
+ helpers/log_daemon/DB/Makefile \
helpers/log_daemon/file/Makefile \
helpers/url_rewrite/Makefile \
helpers/url_rewrite/fake/Makefile \
* then passes the state off to FUBAR.
* No check for null-termination is done.
*/
- xmemcpy(g, glen, state->foo_end_ptr );
+ memcpy(g, glen, state->foo_end_ptr );
state->foo_end_ptr += glen;
fubar(state);
}
section 39 Cache Array Routing Protocol
section 39 Peer source hash based selection
section 39 Peer user hash based selection
-section 40 Referer Logging
-section 40 User-Agent Logging
section 41 Event Processing
section 42 ICMP Pinger program
section 43 AIOPS
section 44 Peer Selection Algorithm
section 45 Callback Data Registry
section 46 Access Log
+section 46 Access Log - Apache combined format
+section 46 Access Log - Apache common format
+section 46 Access Log - Squid Custom format
+section 46 Access Log - Squid ICAP Logging
+section 46 Access Log - Squid format
+section 46 Access Log - Squid referer format
+section 46 Access Log - Squid useragent format
+section 46 Access Log Format Tokens
section 47 Store COSS Directory Routines
section 47 Store Directory Routines
section 48 Persistent Connections
<!doctype linuxdoc system>
<article>
-<title>Squid 3.1.9 release notes</title>
+<title>Squid 3.1.10 release notes</title>
<author>Squid Developers</author>
<abstract>
<sect>Notice
<p>
-The Squid Team are pleased to announce the release of Squid-3.1.9
+The Squid Team are pleased to announce the release of Squid-3.1.10
This new release is available for download from <url url="http://www.squid-cache.org/Versions/v3/3.1/"> or the <url url="http://www.squid-cache.org/Mirrors/http-mirrors.html" name="mirrors">.
direct client address in delay pools.
</verb>
+ <tag>client_request_buffer_max_size</tag>
+ <p>New directive added with squid-3.1.10 to set limits on the amount of buffer space allocated
+ for receiving upload and request data from clients.
+
<tag>dns_v4_fallback</tag>
<p>New option to prevent Squid from always looking up IPv4 regardless of whether IPv6 addresses are found.
Squid will follow a policy of prefering IPv6 links, keeping the IPv4 only as a safety net behind IPv6.
follow_x_forwarded_for allow my_other_proxy
</verb>
- <tag>ftp_epsv</tag>
- <verb>
- FTP Protocol extensions permit the use of a special "EPSV" command.
-
- NATs may be able to put the connection on a "fast path" through the
- translator using EPSV, as the EPRT command will never be used and therefore,
- translation of the data portion of the segments will never be needed.
+ <tag>ftp_eprt</tag>
+ <p>New directive to control whether Squid uses EPRT extension for
+ efficient NAT handling and IPv6 protocol support in FTP.
- Turning this OFF will prevent EPSV being attempted.
-
- WARNING: Doing so will convert Squid back to the old behavior with all
- the related problems with external NAT devices/layers.
-
- Requires ftp_passive to be ON (default) for any effect.
- </verb>
+ <tag>ftp_epsv</tag>
+ <p>New directive to control whether Squid uses EPSV extension for
+ efficient NAT handling and IPv6 protocol support in FTP.
<tag>ftp_epsv_all</tag>
- <verb>
- FTP Protocol extensions permit the use of a special "EPSV ALL" command.
-
- NATs may be able to put the connection on a "fast path" through the
- translator, as the EPRT command will never be used and therefore,
- translation of the data portion of the segments will never be needed.
-
- When a client only expects to do two-way FTP transfers this may be useful.
- If Squid finds that it must do a three-way FTP transfer after issuing
- an EPSV ALL command, the FTP session will fail.
-
- If you have any doubts about this option do not use it.
- Squid will nicely attempt all other connection methods.
-
- Requires ftp_passive to be ON (default)
- </verb>
+ <p>New directive to control whether Squid uses "EPSV ALL" extension for
+ efficient NAT handling and IPv6 protocol support in FTP.
<tag>forward_max_tries</tag>
<p>Controls how many different forward paths Squid will try
X-Forwarded-For header.
If set to "truncate", Squid will remove all existing
- X-Forwarded-For entries, and place itself as the sole entry.
+ X-Forwarded-For entries, and place the client IP as the sole entry.
</verb>
<tag>http_port transparent intercept ssl-bump connection-auth[=on|off] ignore-cc</tag>
<!doctype linuxdoc system>
<article>
-<title>Squid 3.2.0.3 release notes</title>
+<title>Squid 3.2.0.4 release notes</title>
<author>Squid Developers</author>
<abstract>
<sect>Notice
<p>
-The Squid Team are pleased to announce the release of Squid-3.2.0.3 for testing.
+The Squid Team are pleased to announce the release of Squid-3.2.0.4 for testing.
This new release is available for download from <url url="http://www.squid-cache.org/Versions/v3/3.2/"> or the <url url="http://www.squid-cache.org/Mirrors/http-mirrors.html" name="mirrors">.
logging a single cache.log at relatively high debug levels on a high-traffic system. Or one which is
required to store a long period of access.log and needs to conserve disk space.
+<p>The referer_log and useragent_log directives have been converted to built-in log formats.
+ These logs are now created using an access_log line with the format "referrer" or "useragent".
<sect1> Client Bandwidth Limits
<p>In mobile environments, Squid may need to limit Squid-to-client bandwidth
<p>The else part is optional. The keywords <em>if</em>, <em>else</em> and <em>endif</em>
must be typed on their own lines, as if they were regular configuration directives.
+ <tag>max_stale</tag>
+ <p>Places an upper limit on how stale content Squid will serve from the cache if cache validation fails
+
<tag>memory_cache_mode</tag>
<p>Controls which objects to keep in the memory cache (cache_mem)
<verb>
New installs, or installs with no logs configured explicitly will use this module by default.
<p>New <em>tcp</em> module to send each log line as text data to a TCP receiver.
<p>New <em>udp</em> module to send each log line as text data to a UDP receiver.
+ <p>New format <em>referrer</em> to log with the format prevously used by referer_log directive.
+ <p>New format <em>useragent</em> to log with the format prevously used by useragent_log directive.
<tag>acl random</tag>
<p>New type <em>random</em>. Pseudo-randomly match requests based on a configured probability.
<em>concurrency=N</em> previously called <em>auth_param ... concurrency</em> as a separate option.
<p>Removed Basic, Digest, NTLM, Negotiate <em>auth_param ... concurrency</em> setting option.
+ <tag>cache_dir</tag>
+ <p><em>min-size</em> option ported from Squid-2
+
<tag>cache_peer</tag>
<p><em>htcp-*</em> options collapsed into <em>htcp=</em> taking an optional comma-separated list of flags.
The old form is deprecated but still accepted.
<p><em>icap::%>bs</em> Number of message body bytes received from the ICAP server.
<p><em>%>lp</em> Local TCP port used by transactions with http servers.
<p><em>%sn</em> Unique sequence number per log line. Ported from 2.7
- <p><em>%<eui</em> EUI logging (EUI-48 / MAC address for IPv4, EUI-64 for IPv6)
+ <p><em>%>eui</em> EUI logging (EUI-48 / MAC address for IPv4, EUI-64 for IPv6)
Both EUI forms are logged in the same field. Type can be identified by length or byte delimiter.
<p><em>%err_code</em> The ID of an error response served by Squid or
a similar internal error identifier
This will be included by default if available (see the --without-netfilter-conntrack configure option for more details).
<p><em>miss</em> sets a value for a cache miss. It is available for both the tos and mark options and takes precedence over the preserve-miss feature.
+ <tag>refresh_pattern</tag>
+ <p>New option <em>max-stale=</em> to provide a maximum staleness factor. Squid won't
+ serve objects more stale than this even if it failed to validate the object.
+
<tag>tcp_outgoing_mark</tag>
<p>New configuration parameter <em>tcp_outgoing_mark</em>
<p>Allows packets leaving Squid on the server side to be marked with a Netfilter mark value in the same way as the existing tcp_outgoing_tos feature.
<sect1>Removed tags<label id="removedtags">
<p>
<descrip>
+ <tag>emulate_httpd_log</tag>
+ <p>Replaced by <em>common</em> format option on an <em>access_log</em> directive.
+
+ <tag>forward_log</tag>
+ <p>Obsolete.
+
<tag>ftp_list_width</tag>
<p>Obsolete.
<tag>log_fqdn</tag>
<p>Obsolete. Replaced by automatic detection of the %>A logformat tag.
+ <tag>referer_log</tag>
+ <p>Replaced by the <em>referrer</em> format option on an <em>access_log</em> directive.
+
<tag>url_rewrite_concurrency</tag>
<p>Replaced by url_rewrite_children ... concurrency=N option.
+ <tag>useragent_log</tag>
+ <p>Replaced by the <em>useragent</em> format option on an <em>access_log</em> directive.
</descrip>
<tag>--enable-auth-ntlm-helpers</tag>
<p>replaced by <em>--enable-auth-ntlm</em>.
+ <tag>--enable-referer-log</tag>
+ <p>Obsolete.
+
+ <tag>--enable-useragent-log</tag>
+ <p>Obsolete.
+
</descrip>
<p>Not yet ported from 2.6
<tag>cache_dir</tag>
- <p><em>min-size</em> option not yet ported from Squid-2
<p><em>COSS</em> storage type is lacking stability fixes from 2.6
<p>COSS <em>overwrite-percent=</em> option not yet ported from 2.6
<p>COSS <em>max-stripe-waste=</em> option not yet ported from 2.6
<tag>logformat</tag>
<p><em>%oa</em> tag not yet ported from 2.7
- <tag>max_stale</tag>
- <p>Not yet ported from 2.7
-
<tag>refresh_pattern</tag>
<p><em>stale-while-revalidate=</em> not yet ported from 2.7
<p><em>ignore-stale-while-revalidate=</em> not yet ported from 2.7
- <p><em>max-stale=</em> not yet ported from 2.7
<p><em>negative-ttl=</em> not yet ported from 2.7
<tag>refresh_stale_hit</tag>
templates/ERR_FTP_PUT_ERROR \
templates/ERR_FTP_PUT_MODIFIED \
templates/ERR_FTP_UNAVAILABLE \
+ templates/ERR_GATEWAY_FAILURE \
templates/ERR_ICAP_FAILURE \
templates/ERR_INVALID_REQ \
templates/ERR_INVALID_RESP \
az Azerbaijani
bg Bulgarian
ca Catalan
-cz Czech
+cs Czech
da Danish
de German
el Greek
ko Korean
lt Lithuanian
nl Dutch
-po Polish
+pl Polish
pt Portuguese
ro Romanian
ru Russian-1251 Russian-koi8-r
"Project-Id-Version: Squid-3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-11-06 03:26+1300\n"
-"PO-Revision-Date: 2010-11-17 19:36+0200\n"
+"PO-Revision-Date: 2011-01-24 19:52+0200\n"
"Last-Translator: Bernard <fli4l.charrier@free.fr>\n"
"Language-Team: Squid Developers <squid-dev@squid-cache.org>\n"
"Language: fr\n"
"has failed."
msgstr ""
"Au moins une précondition indiquée dans l'en-tête de la requête du client "
-"HTTP a échoué."
+"HTTP a échoué."
#: templates/ERR_CACHE_ACCESS_DENIED:3 templates/ERR_CACHE_ACCESS_DENIED:5
msgid "Cache Access Denied."
#: templates/ERR_SECURE_CONNECT_FAIL:5
msgid "Failed to establish a secure connection to %I"
-msgstr "Il n'a pas été possible d'établir d'une connexion sécurisée vers %I"
+msgstr "Il n'a pas été possible d'établir une connexion sécurisée vers %I"
#: templates/ERR_FTP_PUT_CREATED:3
msgid "File created"
#: templates/ERR_AGENT_CONFIGURE:14
msgid "In the HTTP proxy box type the proxy name %h and port 3128."
msgstr ""
-"Dans l'onglet proxy HTTP, vous devez indiquer le chemin du proxy %h et le "
-"port 3128"
+"Dans l'onglet proxy HTTP, vous devez indiquer le nom du proxy %h et le port "
+"3128"
#: templates/ERR_INVALID_URL:5
msgid "Invalid URL"
#: templates/ERR_AGENT_WPAD:10
msgid "Select Automatically detect settings"
-msgstr "Sélectionnez détection automatique les paramètres"
+msgstr "Sélectionnez la détection automatique les paramètres"
#: templates/ERR_AGENT_WPAD:13
msgid "Select Use Automatic proxy configuration"
"Squid does not support all request methods for all access protocols. For "
"example, you can not POST a Gopher request."
msgstr ""
-"Squid ne prend pas en charge tout les types de requêtes par rapport à tous "
+"Squid ne prend pas en charge tous les types de requêtes par rapport à tous "
"les protocoles d'accès. Vous ne pouvez pas par exemple utiliser le protocole "
"POST dans une requête Gopher."
"Squid is unable to create a TCP socket, presumably due to excessive load. "
"Please retry your request."
msgstr ""
-"Squid n'est pas en mesure d'ouvrir une socket TCP, probablement due à une "
+"Squid n'est pas en mesure d'ouvrir le socket TCP, probablement due à une "
"surcharge. Veuillez renouveler votre requête."
#: templates/ERR_FTP_FAILURE:5 templates/ERR_FTP_FORBIDDEN:5
#: templates/ERR_FTP_UNAVAILABLE:4
msgid "The FTP server was too busy to retrieve the URL: <a href=\"%U\">%U</a>"
msgstr ""
-"Le serveur FTP était surchargé et ne permettent pas l'accès à l'URL : <a "
-"href=\"%U\">%U</a>"
+"Le serveur FTP est surchargé et ne permet pas l'accès à l'URL : <a href=\"%"
+"U\">%U</a>"
#: templates/ERR_INVALID_RESP:5
msgid ""
"The HTTP Response message received from the contacted server could not be "
"understood or was otherwise malformed. Please contact the site operator."
msgstr ""
-"Le message reçu par le serveur HTTP contacté, n'a pas pu être compris ou a "
-"été mal formulé. Veuillez contacter le responsable du site."
+"La réponse HTTP reçu, qui a été envoyée par le serveur n'a pas pu être "
+"compris ou a été mal formulé. Veuillez contacter le responsable du site."
#: templates/ERR_ICAP_FAILURE:9
msgid "The ICAP server is not reachable."
"file. Check the path, permissions, diskspace and try again."
msgstr ""
"Cela signifie que le serveur FTP n'a pas les autorisations ou pas assez "
-"d'espace pour stocker ce fichier. Veuillez vérifier l'emplacement, les "
+"d'espace pour stocker ce fichier. Veuillez vérifier le chemin, les "
"autorisations et l'espace disque puis essayez de nouveau."
#: templates/ERR_DNS_FAIL:7
"comply with RFC 1738). If this is the cause, then the file can be found at "
"<a href=\"%B\">%B</a>."
msgstr ""
-"Cela pourrait être causé par une URL FTP qui contient les chemins absolus "
-"(ce qui n'est pas compatible avec la RFC 1738). Si tel est le cas, le "
-"fichier peut être disponible à l'adresse <a% href=\\\"%B\\\"> B </ a>."
+"Cela pourrait être causé par une URL FTP qui contient un chemin absolut (ce "
+"qui n'est pas compatible avec la RFC 1738). Si tel est le cas, le fichier "
+"peut être disponible à l'adresse <a% href=\\\"%B\\\"> B </ a>."
#: templates/ERR_SECURE_CONNECT_FAIL:7
msgid ""
"the host security credentials."
msgstr ""
"Ce proxy et l'hôte distant n'ont pas pu négocier mutuellement une connexion "
-"de sécurité pour le traitement de votre requête. Il est possible que l'hôte "
+"sécurisée pour le traitement de votre requête. Il est possible que l'hôte "
"distant ne supporte pas les connexions sécurisées, ou que le proxy n'est pas "
"satisfait du certificat de sécurité de l'hôte distant."
"Valid document was not found in the cache and <q>only-if-cached</q> "
"directive was specified."
msgstr ""
-"Aucun document valide n'a été trouvé dans le cache et la directive <q>only-"
-"if-cached</q> a été spécifiée."
+"Aucun document valide n'a été trouvé dans le cache, de plus la directive <q"
+">only-if-cached</q> a été spécifiée."
#: templates/ERR_AGENT_CONFIGURE:1 templates/ERR_AGENT_CONFIGURE:3
#: templates/ERR_AGENT_WPAD:1 templates/ERR_AGENT_WPAD:3
"Project-Id-Version: Squid-3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-11-06 03:26+1300\n"
-"PO-Revision-Date: 2010-08-21 17:08+0200\n"
+"PO-Revision-Date: 2011-01-20 21:35+0200\n"
"Last-Translator: Arthur <arthurtumanyan@yahoo.com>\n"
"Language-Team: Squid Developers <squid-dev@squid-cache.org>\n"
"Language: hy\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Pootle 2.0.1\n"
+"X-Generator: Pootle 2.0.5\n"
#: templates/ERR_DIR_LISTING:6
msgid "<a href=\"../\">Parent Directory</a> (<a href=\"/\">Root Directory</a>)"
msgid ""
"At least one precondition specified by the HTTP client in the request header "
"has failed."
-msgstr ""
+msgstr "HTTP հարցումի նախապայմաններից առնվազն մեկը անհնար է մշակել"
#: templates/ERR_CACHE_ACCESS_DENIED:3 templates/ERR_CACHE_ACCESS_DENIED:5
msgid "Cache Access Denied."
msgstr "Քեշի կառավառման մուտքն արգելված է."
#: templates/ERR_URN_RESOLVE:5
-#, fuzzy
msgid "Cannot Resolve URN"
-msgstr "Cannot Resolve URN"
+msgstr "Չհաջողվեց մշակել URN հարցումը"
#: templates/ERR_LIFETIME_EXP:5
msgid "Connection Lifetime Expired"
#: templates/ERR_CONNECT_FAIL:5
msgid "Connection to %I failed."
-msgstr ""
+msgstr "Չհաջողվեց կապ հաստատել %I -ի հետ"
#: templates/ERR_INVALID_REQ:10
msgid "Content-Length missing for POST or PUT requests."
#: templates/ERR_DIR_LISTING:4
msgid "Directory Listing"
-msgstr ""
+msgstr "Դիրեկտորիայի պարունակությունը"
#: templates/ERR_DIR_LISTING:1
msgid "Directory: %U"
#: templates/ERR_ESI:5
msgid "ESI Processing failed."
-msgstr ""
+msgstr "Չհաջողվեց մշակել ESI հարցումը"
#: templates/ERR_FTP_PUT_CREATED:1 templates/ERR_FTP_PUT_MODIFIED:1
msgid "FTP PUT Successful."
#: templates/ERR_ICAP_FAILURE:5
msgid "ICAP protocol error."
-msgstr ""
+msgstr "ICAP արձանարության սխալ"
#: templates/ERR_TOO_BIG:7
-#, fuzzy
msgid ""
"If you are making a GET request, then the item you are trying to download is "
"too large."
-msgstr ""
-"Եթե Դուք GET հարցում եք ձևակերպում, ապա տարրը ,որը Դուք փորձում եք "
-"բեռնավորել, շատ մեծ ծավալ ունի."
+msgstr "GET հարցման օբյեկտը շատ մեծ ծավալ ունի."
#: templates/ERR_TOO_BIG:6
-#, fuzzy
msgid ""
"If you are making a POST or PUT request, then the item you are trying to "
"upload is too large."
-msgstr ""
-"Եթե Դուք POST կամ PUT հարցում եք ձևակերպում, ապա տարրը ,որը Դուք փորձում եք "
-"բեռնավորել, շատ մեծ ծավալ ունի"
+msgstr "POST հարցման օբյեկտը շատ մեծ ծավալ ունի."
#: templates/ERR_INVALID_REQ:11 templates/ERR_INVALID_URL:11
msgid "Illegal character in hostname; underscores are not allowed."
#: templates/ERR_PRECONDITION_FAILED:5
msgid "Precondition Failed."
-msgstr ""
+msgstr "Չհաջողվեց մշակել նախապայմանը"
#: templates/ERR_READ_ERROR:5
msgid "Read Error"
msgstr "DNS սերվերի պատասխանը:"
#: templates/ERR_ESI:6
-#, fuzzy
msgid "The ESI processor returned:"
-msgstr "ESI ÕºÖ\80Õ¸Ö\81Õ¥Õ½Õ¸Ö\80Õ¨ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¥Ö\81:"
+msgstr "ESI Õ°Õ¡Ö\80Ö\81Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ¡Õ½ÕÕ¡Õ¶Õ¶ Õ§Ö\89"
#: templates/ERR_FTP_UNAVAILABLE:4
msgid "The FTP server was too busy to retrieve the URL: <a href=\"%U\">%U</a>"
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html><head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>ERROR: The requested URL could not be retrieved</title>
+<style type="text/css"><!--
+ %l
+
+body
+:lang(fa) { direction: rtl; font-size: 100%; font-family: Tahoma, Roya, sans-serif; float: right; }
+:lang(he) { direction: rtl; float: right; }
+ --></style>
+</head><body>
+<div id="titles">
+<h1>ERROR</h1>
+<h2>The requested URL could not be retrieved</h2>
+</div>
+<hr>
+
+<div id="content">
+<p>The following error was encountered while trying to retrieve the URL: <a href="%U">%U</a></p>
+
+<blockquote id="error">
+<p><b>Gateway Proxy Failure</b></p>
+</blockquote>
+
+<p>A non-recoverable internal failure or configuration problem prevents this request from being completed.</p>
+
+<p>This may be due to limits established by the Internet Service Provider who operates this cache. Please contact them directly for more information.</p>
+
+<p>Your cache administrator is <a href="mailto:%w%W">%w</a>.</p>
+<br>
+</div>
+
+<hr>
+<div id="footer">
+<p>Generated %T by %h (%s)</p>
+<!-- %c -->
+</div>
+</body></html>
+#ifndef _SQUID_HELPERS_BASIC_AUTH_MSNT_MSNTAUTH_H
+#define _SQUID_HELPERS_BASIC_AUTH_MSNT_MSNTAUTH_H
+
extern int OpenConfigFile(void);
extern int QueryServers(char *, char *);
extern void Checktimer(void);
-extern void Check_forchange(int);
+extern "C" void Check_forchange(int);
extern int Read_denyusers(void);
extern int Read_allowusers(void);
extern int Check_user(char *);
extern int Check_ifuserallowed(char *ConnectingUser);
extern void Check_forallowchange(void);
+#endif /* _SQUID_HELPERS_BASIC_AUTH_MSNT_MSNTAUTH_H */
static char *password = NULL; /* Workaround for Solaris 2.6 brokenness */
#endif
+extern "C" int password_conversation(int num_msg, PAM_CONV_FUNC_CONST_PARM struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr);
+
/**
* A simple "conversation" function returning the supplied password.
* Has a bit to much error control, but this is my first PAM application
* so I'd rather check everything than make any mistakes. The function
* expects a single converstation message of type PAM_PROMPT_ECHO_OFF.
*/
-static int
+int
password_conversation(int num_msg, PAM_CONV_FUNC_CONST_PARM struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
{
if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) {
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#include <io.h>
#endif
#if HAVE_CTYPE_H
include $(top_srcdir)/src/Common.am
-# SAMBAPREFIX must point to the directory where Samba has been installed.
-# By default, Samba is installed in /usr/local/samba. If you changed this
-# by using the --prefix option when configuring Samba, you need to change
-# SAMBAPREFIX accordingly.
-
-## FIXME: autoconf should test for the samba path.
-
-SMB_AUTH_HELPER = basic_smb_auth.sh
-SAMBAPREFIX=/usr/local/samba
-SMB_AUTH_HELPER_PATH = $(libexecdir)/$(SMB_AUTH_HELPER)
-
-libexec_SCRIPTS = $(SMB_AUTH_HELPER)
-
+libexec_SCRIPTS = basic_smb_auth.sh
libexec_PROGRAMS = basic_smb_auth
basic_smb_auth_SOURCES= basic_smb_auth.cc
-basic_smb_auth_CXXFLAGS = -DSAMBAPREFIX=\"$(SAMBAPREFIX)\" -DHELPERSCRIPT=\"$(SMB_AUTH_HELPER_PATH)\"
+basic_smb_auth_CXXFLAGS = -DHELPERSCRIPT=\"$(libexecdir)/basic_smb_auth.sh\"
basic_smb_auth_LDADD = \
$(top_builddir)/lib/libmiscencoding.la \
$(COMPAT_LIB) \
shcmd = debug_enabled ? HELPERSCRIPT : HELPERSCRIPT " > /dev/null 2>&1";
- /* pass to helper script */
- if (putenv((char *)"SAMBAPREFIX=" SAMBAPREFIX) != 0)
- return 1;
-
while (fgets(buf, HELPER_INPUT_BUFFER, stdin) != NULL) {
if ((s = strchr(buf, '\n')) == NULL)
addropt=""
fi
echo "Query address options: $addropt"
-dcip=`$SAMBAPREFIX/bin/nmblookup $addropt "$PASSTHROUGH#1c" | awk '/^[0-9.]+ / { print $1 ; exit }'`
+dcip=`nmblookup $addropt "$PASSTHROUGH#1c" | awk '/^[0-9.]+ / { print $1 ; exit }'`
echo "Domain controller IP address: $dcip"
[ -n "$dcip" ] || exit 1
# All right, we have the IP address of a domain controller,
# but we need its name too
-dcname=`$SAMBAPREFIX/bin/nmblookup -A $dcip | awk '$2 == "<00>" { print $1 ; exit }'`
+dcname=`nmblookup -A $dcip | awk '$2 == "<00>" { print $1 ; exit }'`
echo "Domain controller NETBIOS name: $dcname"
[ -n "$dcname" ] || exit 1
# Read the contents of the file $AUTHFILE on the $AUTHSHARE share
authfilebs=`echo "$AUTHFILE" | tr / '\\\\'`
-authinfo=`$SAMBAPREFIX/bin/smbclient "//$dcname/$AUTHSHARE" -I $dcip -d 0 -E -W "$DOMAINNAME" -c "get $authfilebs -" 2>/dev/null`
+authinfo=`smbclient "//$dcname/$AUTHSHARE" -I $dcip -d 0 -E -W "$DOMAINNAME" -c "get $authfilebs -" 2>/dev/null`
echo "Contents of //$dcname/$AUTHSHARE/$AUTHFILE: $authinfo"
# Allow for both \n and \r\n end-of-line termination
#!/bin/sh
-for prefix in ${SAMBAPREFIX} /usr/local /opt /opt/samba /usr/local/samba /usr
+for prefix in /usr/local /opt /opt/samba /usr/local/samba /usr
do
if [ -x ${prefix}/bin/smbclient ]; then
exit 0
fi
done
-exit 1
+echo "WARNING: Samba smbclient not found in default location. basic_smb_auth may not work on this machine"
+# allow script install anyway.
+exit 0
#endif
/* Check if we try to compile on a Windows Platform */
-#if defined(_SQUID_CYGWIN_) || defined(_SQUID_MSWIN_)
+#if !_SQUID_WINDOWS_
+/* NON Windows Platform !!! */
+#error NON WINDOWS PLATFORM
+#endif
#include "valid.h"
}
return 0;
}
-
-#else /* NON Windows Platform !!! */
-
-#error NON WINDOWS PLATFORM
-
-#endif
#include "util.h"
/* Check if we try to compile on a Windows Platform */
-#if defined(_SQUID_CYGWIN_) || defined(_SQUID_MSWIN_)
+#if !_SQUID_WINDOWS_
+/* NON Windows Platform !!! */
+#error NON WINDOWS PLATFORM
+#endif
-#if defined(_SQUID_CYGWIN_)
+#if _SQUID_CYGWIN_
#include <wchar.h>
#endif
#include "valid.h"
}
return result;
}
-#else /* NON Windows Platform !!! */
-
-#error NON WINDOWS PLATFORM
-
-#endif
#ifndef _VALID_H_
#define _VALID_H_
-#ifdef _SQUID_CYGWIN_
+#if _SQUID_CYGWIN_
#include <windows.h>
#endif
#include <lm.h>
#include "helpers/defines.h"
#include "include/util.h"
-#ifdef _SQUID_CYGWIN_
+#if _SQUID_CYGWIN_
#include <wchar.h>
int _wcsicmp(const wchar_t *, const wchar_t *);
#endif
#include "include/util.h"
-#ifdef _SQUID_CYGWIN_
+#if _SQUID_CYGWIN_
#include <wchar.h>
int _wcsicmp(const wchar_t *, const wchar_t *);
#endif
*
********************************************************************************
*
- * ext_edirectory_userip_acl.c -- Rev 2010-09-22
+ * ext_edirectory_userip_acl.cc -- Rev 2010-12-15
*
*/
char passwd[EDUI_MAXLEN];
char search_filter[EDUI_MAXLEN]; /* search_group gets appended here by GroupLDAP */
char search_ip[EDUI_MAXLEN]; /* Could be IPv4 or IPv6, set by ConvertIP */
- char userid[EDUI_MAXLEN]; /* Resulting userid */
+ char userid[EDUI_MAXLEN]; /* Resulting userid */
unsigned int status;
unsigned int port;
unsigned long type; /* Type of bind */
} edui_ldap_t;
/* Global function prototypes */
-/* DISABLED BELOW IN FAVOR OF SQUID debug() */
-//void local_debug(const char *, const char *,...);
-//void local_debugx(const char *,...);
void local_printfx(const char *,...);
-int SplitString(char *, size_t, char, char *, size_t);
+int StringSplit(char *, char, char *, size_t);
+int BinarySplit(void *, size_t, char, void *, size_t);
static void DisplayVersion();
static void DisplayUsage();
static void InitConf();
int ResetLDAP(edui_ldap_t *);
int SearchFilterLDAP(edui_ldap_t *, char *);
int SearchLDAP(edui_ldap_t *, int, char *, char **);
-int GetValLDAP(edui_ldap_t *, char *);
-int SearchIPLDAP(edui_ldap_t *, char *);
+int SearchIPLDAP(edui_ldap_t *);
const char *ErrLDAP(int);
-void SigTrap(int);
+extern "C" void SigTrap(int);
/* Global variables */
const char *search_attrib[] = { "cn", "uid", "networkAddress", "groupMembership", NULL };
time_t edui_now;
time_t edui_elap;
-/* local_debug() -
- *
- * Print formatted message of func() to stderr if EDUI_MODE_DEBUG is set.
- *
- */
-/*
-void local_debug(const char *func, const char *msg,...)
-{
- char prog[EDUI_MAXLEN], dbuf[EDUI_MAXLEN], cbuf[EDUI_MAXLEN], bbuf[EDUI_MAXLEN];
- size_t sz, x;
- va_list ap;
- if (!(edui_conf.mode & EDUI_MODE_DEBUG))
- return;
-
- if (edui_conf.program[0] == '\0')
- xstrncpy(prog, EDUI_PROGRAM_NAME, sizeof(prog));
- else
- xstrncpy(prog, edui_conf.program, sizeof(prog));
- if ((func == NULL) || (msg == NULL) || (strlen(prog) > 256)) {
- snprintf(dbuf, sizeof(dbuf), "%s: local_debug() EPIC FAILURE.\n", prog);
- fputs(dbuf, stderr);
- return;
- }
- sz = sizeof(dbuf);
- memset(cbuf, '\0', sizeof(cbuf));
- xstrncpy(cbuf, prog, sizeof(cbuf));
- strncat(cbuf, ": [DB] ", 7);
- strncat(cbuf, func, strlen(func));
- strncat(cbuf, "() - ", 5);
- va_start(ap, msg);
- x = vsnprintf(dbuf, sz, msg, ap);
- va_end(ap);
- if (x > 0) {
- strncat(cbuf, dbuf, x);
- fputs(cbuf, stderr);
- memset(dbuf, '\0', sizeof(dbuf));
- } else {
- snprintf(bbuf, sz, "%s: local_debug(%s) FAILURE: %zd\n", prog, dbuf, x);
- fputs(bbuf, stderr);
- }
-}
-*/
-/* local_debugx() -
- *
- * Print formatted message to stderr if EDUI_MODE_DEBUG is set, without preformatting.
- *
- */
-/*
-void local_debugx(const char *msg,...)
-{
- char prog[EDUI_MAXLEN], dbuf[EDUI_MAXLEN], bbuf[EDUI_MAXLEN];
- size_t sz, x;
- va_list ap;
- if (!(edui_conf.mode & EDUI_MODE_DEBUG))
- return;
-
- if (edui_conf.program[0] == '\0')
- xstrncpy(prog, EDUI_PROGRAM_NAME, sizeof(prog));
- else
- xstrncpy(prog, edui_conf.program, sizeof(prog));
- if ((msg == NULL) || (strlen(prog) > 256)) {
- snprintf(dbuf, sizeof(dbuf), "%s: local_debugx() EPIC FAILURE.\n", prog);
- fputs(dbuf, stderr);
- return;
- }
- sz = sizeof(dbuf);
- va_start(ap, msg);
- x = vsnprintf(dbuf, sz, msg, ap);
- va_end(ap);
- if (x > 0) {
- fputs(dbuf, stderr);
- memset(dbuf, '\0', sizeof(dbuf));
- } else {
- snprintf(bbuf, sz, "%s: local_debugx(%s) FAILURE: %zd\n", prog, dbuf, x);
- fputs(bbuf, stderr);
- }
-}
-*/
-
/* local_printfx() -
*
* Print formatted message to stderr AND stdout, without preformatting.
if ((msg == NULL) || (strlen(prog) > 256)) {
/* FAIL */
- /*
- snprintf(dbuf, sizeof(dbuf), "%s: local_printfx() EPIC FAILURE.\n", prog);
- fputs(dbuf, stderr);
- */
debug("local_printfx() EPIC FAIL.\n");
return;
}
dbuf[x] = '\0';
x++;
fputs(dbuf, stdout);
- memset(dbuf, '\0', sizeof(dbuf));
+ *(dbuf) = '\0';
} else {
/* FAIL */
- /*
- snprintf(bbuf, sz, "%s: local_printfx(%s) FAILURE: %zd\n", prog, dbuf, x);
- fputs(bbuf, stderr);
- */
debug("local_printfx() FAILURE: %zd\n", x);
}
}
/*
- * SplitString() - <string> <string-size> <char> <split-object> <obj-size>
+ * StringSplit() - <string-to-split> <char> <split-object> <obj-size>
*
* Breaks down string, splitting out element <char> into <split-object>, and removing it from string.
* Will not exceed size tolerances.
*
- * NOTE: We could have used a strchr() pointer, but then '\0' would break it.
- * (Which DOES commonly exist in IP Addressing)
+ */
+int
+StringSplit(char *In_Str, char chr, char *Out_Str, size_t Out_Sz)
+{
+ if ((In_Str == NULL) || (Out_Str == NULL))
+ return (-1);
+
+ size_t In_Len = strlen(In_Str) + 1;
+
+ // find the char delimiter position...
+ char *p = In_Str;
+ while (*p != chr && *p != '\0' && (In_Str+In_Len) > p) {
+ p++;
+ }
+
+ size_t i = (p-In_Str);
+
+ // token to big for the output buffer
+ if (i >= Out_Sz)
+ return (-2);
+
+ // wipe the unused Out_Obj area
+ memset(Out_Str+i, 0, Out_Sz-i);
+ // copy token from In_Str to Out_Str
+ memcpy(Out_Str, In_Str, i);
+
+ // omit the delimiter
+ if (*p == chr) {
+ p++;
+ i++;
+ } else {
+ // chr not found (or \0 found first). Wipe whole input buffer.
+ memset(In_Str, 0, In_Len);
+// return (-3);
+// Returning <0 breaks current ConvertIP() code for last object
+ return (i);
+ }
+
+ // move the unused In_Str forward
+ memmove(In_Str, p, In_Len-i);
+ // wipe the end of In_Str
+ memset(In_Str+In_Len-i, 0, i);
+ return (i-1);
+}
+
+/*
+ * BinarySplit() - <binary-to-split> <bin-size> <char> <split-object> <obj-size>
+ *
+ * Breaks down Binary Block, splitting out element <char> into <split-object>, and removing it from Block, padding remainder with '\0'.
+ * Will not exceed size tolerances.
*
*/
-int SplitString(char *input, size_t insz, char c, char *obj, size_t objsz)
+int
+BinarySplit(void *In_Obj, size_t In_Sz, char chr, void *Out_Obj, size_t Out_Sz)
{
- size_t i, j;
- int swi;
- char buf[EDUI_MAXLEN];
- if ((input == NULL) || (obj == NULL) || (insz <= 0) || (objsz <= 0)) return -1;
-
- /* Copy input, and clear */
- memset(buf, '\0', sizeof(buf));
- memcpy(buf, input, insz);
- memset(input, '\0', insz);
- memset(obj, '\0', objsz);
- j = 0; /* obj position */
- swi = 0; /* found data yet ? */
-
- /* Scan for data, and copy */
- for (i = 0; i < insz; i++) {
- /* Scan input for first non-space character */
- if (buf[i] != c) {
- if (swi == 0) {
- swi++; /* Data found, begin copying. */
- obj[j] = buf[i];
- j++;
- } else if (swi == 1) {
- obj[j] = buf[i];
- j++;
- } else
- break; /* end of data */
- } else {
- /* Found a character c */
- if (swi == 1)
- swi++;
- else if (swi == 2)
- break; /* end of data */
- }
+ // check tolerances
+ if ((In_Obj == NULL) || (Out_Obj == NULL))
+ return (-1);
+
+ char *in = static_cast<char*>(In_Obj);
+ char *out = static_cast<char*>(Out_Obj);
+
+ // find the char delimiter position...
+ char *p = static_cast<char*>(In_Obj);
+ while (*p != chr && (in+In_Sz) > p) {
+ p++;
}
- obj[j] = '\0'; /* Terminate, i = point of split */
-
- j = 0; /* Position of input */
- for (; i < insz; i++) {
- /* Commented out for BINARY MODE, ie. May have '\0' as legit data *
- if (buf[i] == '\0')
- break;
- */
- input[j] = buf[i];
- j++;
+
+ size_t i = (p-in);
+
+ // token to big for the output buffer
+ if (i > Out_Sz)
+ return (-2);
+
+ // wipe the unused Out_Obj area
+ memset(out+i, 0, Out_Sz-i);
+ // copy token from In_Obj to Out_Obj
+ memcpy(Out_Obj, In_Obj, i);
+
+ // omit the delimiter
+ if (*p == chr) {
+ p++;
+ i++;
+ } else {
+ // chr not found
+ memset(In_Obj, 0, In_Sz);
+// return (-3);
+// Returning <0 breaks current code for last object
+ return (i);
}
- /* Should be correctly split back into input, and
- * split object in obj. memset() at next call will
- * clear array data.
- */
- i = strlen(input);
- j = strlen(obj);
-
- return j;
+
+ // move the unused In_Obj forward
+ memmove(In_Obj, p, In_Sz-i);
+ // wipe the end of In_Obj
+ memset(in+In_Sz-i, 0, i);
+ return (i-1);
}
/* Displays version information */
/* Initalizes program's configuration paremeters */
static void InitConf()
{
- memset(edui_conf.program, '\0', sizeof(edui_conf.program));
- memset(edui_conf.basedn, '\0', sizeof(edui_conf.basedn));
- memset(edui_conf.host, '\0', sizeof(edui_conf.host));
- memset(edui_conf.attrib, '\0', sizeof(edui_conf.attrib));
- memset(edui_conf.dn, '\0', sizeof(edui_conf.dn));
- memset(edui_conf.passwd, '\0', sizeof(edui_conf.passwd));
- memset(edui_conf.search_filter, '\0', sizeof(edui_conf.search_filter));
+ *(edui_conf.program) = '\0';
+ *(edui_conf.basedn) = '\0';
+ *(edui_conf.host) = '\0';
+ *(edui_conf.attrib) = '\0';
+ *(edui_conf.dn) = '\0';
+ *(edui_conf.passwd) = '\0';
+ *(edui_conf.search_filter) = '\0';
edui_conf.scope = -1;
edui_conf.ver = -1;
edui_conf.port = -1;
*/
static void InitLDAP(edui_ldap_t *l)
{
- if (l == NULL) return; /* Duh! */
+ if (l == NULL) return;
l->lp = NULL;
if (l->lm != NULL)
ldap_value_free_len(l->val);
l->lm = NULL;
l->val = NULL;
- memset(l->basedn, '\0', sizeof(l->basedn));
- memset(l->host, '\0', sizeof(l->host));
- memset(l->dn, '\0', sizeof(l->dn));
- memset(l->passwd, '\0', sizeof(l->passwd));
- memset(l->search_filter, '\0', sizeof(l->search_filter));
+ *(l->basedn) = '\0';
+ *(l->host) = '\0';
+ *(l->dn) = '\0';
+ *(l->passwd) = '\0';
+ *(l->search_filter) = '\0';
+ *(l->userid) = '\0';
memset(l->search_ip, '\0', sizeof(l->search_ip));
- memset(l->userid, '\0', sizeof(l->userid));
l->status = 0;
l->status |= LDAP_INIT_S;
l->port = 0;
l->err = -1; /* Set error to LDAP_SUCCESS by default */
l->ver = 0;
l->idle_time = 0;
- l->num_ent = 0; /* Number of entries in l->lm */
- l->num_val = 0; /* Number of entries in l->val */
+ l->num_ent = 0; /* Number of entries in l->lm */
+ l->num_val = 0; /* Number of entries in l->val */
/* Set default settings from conf */
if (edui_conf.basedn[0] != '\0')
xstrncpy(l->search_filter, edui_conf.search_filter, sizeof(l->search_filter));
if (!(edui_conf.scope < 0))
l->scope = edui_conf.scope;
-// * We Dont Need Bit-Status updates in gerneal debugging. *
-// debug("New status = %u\n", l->status);
}
/* OpenLDAP() - <edui_ldap_t> <host> <port>
{
if ((l == NULL) || (h == NULL)) return LDAP_ERR_NULL;
if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized, or might be in use */
- if (l->status & LDAP_OPEN_S) return LDAP_ERR_OPEN; /* Already open */
- if (l->status & LDAP_BIND_S) return LDAP_ERR_BIND; /* Already bound */
+ if (l->status & LDAP_OPEN_S) return LDAP_ERR_OPEN; /* Already open */
+ if (l->status & LDAP_BIND_S) return LDAP_ERR_BIND; /* Already bound */
xstrncpy(l->host, h, sizeof(l->host));
if (p > 0)
l->port = p;
else
- l->port = LDAP_PORT; /* Default is port 389 */
+ l->port = LDAP_PORT; /* Default is port 389 */
#ifdef NETSCAPE_SSL
if (l->port == LDAPS_PORT)
- l->status |= (LDAP_SSL_S | LDAP_TLS_S); /* SSL Port: 636 */
+ l->status |= (LDAP_SSL_S | LDAP_TLS_S); /* SSL Port: 636 */
#endif
#ifdef USE_LDAP_INIT
#endif
if (l->lp == NULL) {
l->err = LDAP_CONNECT_ERROR;
- return LDAP_ERR_CONNECT; /* Unable to connect */
+ return LDAP_ERR_CONNECT; /* Unable to connect */
} else {
/* set status */
// l->status &= ~(LDAP_INIT_S);
s = ldap_unbind(l->lp);
if (s == LDAP_SUCCESS) {
l->status = LDAP_INIT_S;
-// * We Dont Need Bit-Status updates in gerneal debugging. *
-// debug("New status = %u\n", l->status);
l->idle_time = 0;
l->err = s; /* Set LDAP error code */
return LDAP_ERR_SUCCESS;
if (l->lp == NULL) return LDAP_ERR_POINTER;
if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */
if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */
- if (l->status & LDAP_BIND_S) return LDAP_ERR_BIND; /* Already bound */
+ if (l->status & LDAP_BIND_S) return LDAP_ERR_BIND; /* Already bound */
/* set version */
x = ldap_set_option(l->lp, LDAP_OPT_PROTOCOL_VERSION, &v);
if (l == NULL) return LDAP_ERR_NULL;
if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */
if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */
- if (l->status & LDAP_BIND_S) return LDAP_ERR_BIND; /* Already bound */
- if (l->lp == NULL) return LDAP_ERR_POINTER; /* Error */
+ if (l->status & LDAP_BIND_S) return LDAP_ERR_BIND; /* Already bound */
+ if (l->lp == NULL) return LDAP_ERR_POINTER; /* Error */
/* Copy details - dn and pw CAN be NULL for anonymous and/or TLS */
if (dn != NULL) {
if (pw != NULL)
xstrncpy(l->passwd, pw, sizeof(l->passwd));
- /* Type ? */
+ /* Type */
switch (t) {
case LDAP_AUTH_NONE:
l->type = t;
break;
#endif
#ifdef LDAP_AUTH_TLS
- case LDAP_AUTH_TLS: /* Added for chicken switch to TLS-enabled without using SSL */
+ case LDAP_AUTH_TLS: /* Added for chicken switch to TLS-enabled without using SSL */
l->type = t;
break;
#endif
default:
l->type = LDAP_AUTH_NONE;
- break; /* Default to anonymous bind */
+ break; /* Default to anonymous bind */
}
/* Bind */
void *y, *z;
size_t s;
long x;
- int i, j, t, swi; /* IPv6 "::" cut over toggle */
+ int i, j, t, swi; /* IPv6 "::" cut over toggle */
if (l == NULL) return LDAP_ERR_NULL;
if (ip == NULL) return LDAP_ERR_PARAM;
- if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */
- if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */
- if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */
+ if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */
+ if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */
+ if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */
y = memchr((void *)ip, ':', EDUI_MAXLEN);
z = memchr((void *)ip, '.', EDUI_MAXLEN);
return LDAP_ERR_INVALID;
} else if (y != NULL) {
/* Set IPv6 mode */
-// Taboo debug() call.
- debug("Setting IPv6 Mode.\n");
if (l->status & LDAP_IPV4_S)
l->status &= ~(LDAP_IPV4_S);
if (!(l->status & LDAP_IPV6_S))
/* IPv6 Mode forced */
return LDAP_ERR_INVALID;
} else if (z != NULL) {
-// Taboo debug() call.
- debug("Setting IPv4 Mode.\n");
/* Set IPv4 mode */
if (l->status & LDAP_IPV6_S)
l->status &= ~(LDAP_IPV6_S);
z = NULL;
}
s = strlen(ip);
- memset(bufa, '\0', sizeof(bufa));
- memset(bufb, '\0', sizeof(bufb));
- memset(obj, '\0', sizeof(obj));
- /* SplitString() will zero out bufa & obj at each call */
+ *(bufa) = '\0';
+ *(bufb) = '\0';
+ *(obj) = '\0';
+ /* StringSplit() will zero out bufa & obj at each call */
memset(l->search_ip, '\0', sizeof(l->search_ip));
xstrncpy(bufa, ip, sizeof(bufa)); /* To avoid segfaults, use bufa instead of ip */
swi = 0;
if ((bufa[0] == ':') && (bufa[1] == ':')) {
/* bufa starts with a ::, so just copy and clear */
xstrncpy(bufb, bufa, sizeof(bufb));
- memset(bufa, '\0', strlen(bufa));
+ *(bufa) = '\0';
swi++; /* Indicates that there is a bufb */
} else if ((bufa[0] == ':') && (bufa[1] != ':')) {
/* bufa starts with a :, a typo so just fill in a ':', cat and clear */
bufb[0] = ':';
strncat(bufb, bufa, strlen(bufa));
- memset(bufa, '\0', strlen(bufa));
+ *(bufa) = '\0';
swi++; /* Indicates that there is a bufb */
} else {
p = strstr(bufa, "::");
if (p != NULL) {
/* Found it, break bufa down and split into bufb here */
- memset(bufb, '\0', strlen(bufb));
+ *(bufb) = '\0';
i = strlen(p);
memcpy(bufb, p, i);
*p = '\0';
while (s > 0) {
if ((l->status & LDAP_IPV4_S) && (swi == 0)) {
/* Break down IPv4 address */
- t = SplitString(bufa, s, '.', obj, sizeof(obj));
+ t = StringSplit(bufa, '.', obj, sizeof(obj));
if (t > 0) {
errno = 0;
x = strtol(obj, (char **)NULL, 10);
if (((x < 0) || (x > 255)) || ((errno != 0) && (x == 0)) || ((obj[0] != '0') && (x == 0)))
return LDAP_ERR_OOB; /* Out of bounds -- Invalid address */
memset(hexc, '\0', sizeof(hexc));
- int hlen = snprintf(hexc, sizeof(hexc), "%.2X", (int)x);
+ int hlen = snprintf(hexc, sizeof(hexc), "%02X", (int)x);
strncat(l->search_ip, hexc, hlen);
} else
break; /* reached end of octet */
} else if (l->status & LDAP_IPV6_S) {
/* Break down IPv6 address */
if (swi > 1)
- t = SplitString(bufb, s, ':', obj, sizeof(obj)); /* After "::" */
+ t = StringSplit(bufb, ':', obj, sizeof(obj)); /* After "::" */
else
- t = SplitString(bufa, s, ':', obj, sizeof(obj)); /* Before "::" */
+ t = StringSplit(bufa, ':', obj, sizeof(obj)); /* Before "::" */
/* Convert octet by size (t) - and fill 0's */
switch (t) { /* IPv6 is already in HEX, copy contents */
case 4:
if (!(l->status & LDAP_PERSIST_S)) return LDAP_ERR_PERSIST; /* Not persistent */
/* Cleanup data struct */
-// debug("Resetting LDAP connection for next query. (status = %u)\n", l->status);
if (l->status & LDAP_VAL_S)
l->status &= ~(LDAP_VAL_S);
if (l->status & LDAP_SEARCH_S)
l->val = NULL;
}
memset(l->search_ip, '\0', sizeof(l->search_ip));
- memset(l->search_filter, '\0', strlen(l->search_filter));
+ *(l->search_filter) = '\0';
xstrncpy(l->search_filter, edui_conf.search_filter, sizeof(l->search_filter));
- memset(l->userid, '\0', strlen(l->userid));
+ *(l->userid) = '\0';
if (!(l->status & LDAP_IDLE_S))
l->status |= LDAP_IDLE_S; /* Set idle mode */
l->num_ent = 0;
l->num_val = 0;
-// debug("New status = %u\n", l->status);
l->err = LDAP_SUCCESS;
return LDAP_ERR_SUCCESS;
}
int swi;
char bufa[EDUI_MAXLEN], bufb[EDUI_MAXLEN], bufc[EDUI_MAXLEN], bufd[EDUI_MAXLEN], bufg[EDUI_MAXLEN];
if (l == NULL) return LDAP_ERR_NULL;
-// if (group == NULL) return LDAP_ERR_PARAM;
if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */
if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */
if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not Bound */
if (l->search_ip[0] == '\0') return LDAP_ERR_DATA; /* Search IP is required */
/* Zero out if not already */
- memset(bufa, '\0', sizeof(bufa));
- memset(bufb, '\0', sizeof(bufb));
- memset(bufc, '\0', sizeof(bufc));
- memset(bufd, '\0', sizeof(bufd));
- memset(bufg, '\0', sizeof(bufg));
+ *(bufa) = '\0';
+ *(bufb) = '\0';
+ *(bufc) = '\0';
+ *(bufd) = '\0';
+ *(bufg) = '\0';
-// debug("Building... (Adding '\\' to IP...) - search_ip: %s\n", l->search_ip);
s = strlen(l->search_ip);
bufc[0] = '\134';
swi = 0;
if (l == NULL) return LDAP_ERR_NULL;
if ((scope < 0) || (filter == NULL)) return LDAP_ERR_PARAM; /* If attrs is NULL, then all attrs will return */
if (l->lp == NULL) return LDAP_ERR_POINTER;
- if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */
- if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */
- if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */
+ if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */
+ if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */
+ if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */
if (l->status & LDAP_SEARCH_S) return LDAP_ERR_SEARCHED; /* Already searching */
if (l->basedn[0] == '\0') return LDAP_ERR_DATA; /* We require a basedn */
if (l->lm != NULL)
if (s == LDAP_SUCCESS) {
l->status |= (LDAP_SEARCH_S); /* Mark as searched */
l->err = s;
- l->idle_time = 0; /* Connection in use, reset idle timer */
+ l->idle_time = 0; /* Connection in use, reset idle timer */
l->num_ent = ldap_count_entries(l->lp, l->lm); /* Counted */
return LDAP_ERR_SUCCESS;
} else {
}
/*
- * GetValLDAP() - <edui_ldap_t> <search-attr>
- *
- * Scan LDAP and look for search-attr, then return results in l->val
- *
- */
-int GetValLDAP(edui_ldap_t *l, char *attr)
-{
- ber_len_t x;
- /*
- ber_len_t i, j;
- int c;
- */
- LDAPMessage *ent;
- if (l == NULL) return LDAP_ERR_NULL;
- if (attr == NULL) return LDAP_ERR_PARAM;
- if (l->lp == NULL) return LDAP_ERR_POINTER;
- if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */
- if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */
- if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */
- if (!(l->status & LDAP_SEARCH_S)) return LDAP_ERR_NOT_SEARCHED; /* Not searched */
- if (l->num_ent <= 0) return LDAP_ERR_DATA; /* No entries found */
- if (l->val != NULL)
- ldap_value_free_len(l->val); /* Clear data before populating */
- l->num_val = 0;
- if (l->status & LDAP_VAL_S)
- l->status &= ~(LDAP_VAL_S); /* Clear VAL bit */
-
- /* Sift through entries -- Look for matches */
- for (ent = ldap_first_entry(l->lp, l->lm); ent != NULL; ent = ldap_next_entry(l->lp, ent)) {
- l->val = ldap_get_values_len(l->lp, ent, attr);
- if (l->val != NULL) {
- x = ldap_count_values_len(l->val); /* We got x values ... */
- l->num_val = x;
- if (x > 0) {
- /* Display all values */
- /* DEBUGGING ONLY *
- for (i = 0; i < x; i++) {
- local_debug("GetValLDAP", "value[%zd]: \"%s\"\n", i, l->val[i]->bv_val);
- local_debug("GetValLDAP", "value[%zd]: ", i);
- for (j = 0; j < (l->val[i]->bv_len); j++) {
- c = (int) l->val[i]->bv_val[j];
- if (c < 0)
- c = c + 256;
- local_debugx("%.2X", c);
- }
- local_debugx("\n");
- }
- */
- /* CRASHES?!?!
- if (ent != NULL)
- ldap_msgfree(ent);
- */
- if (l->lm != NULL) {
- ldap_msgfree(l->lm);
- l->lm = NULL;
- }
- l->num_ent = 0;
- l->status &= ~(LDAP_SEARCH_S);
- l->status |= LDAP_VAL_S;
- l->err = LDAP_SUCCESS;
- return LDAP_ERR_SUCCESS; /* Found it */
- }
- }
- /* Attr not found, continue */
- }
- /* No entries found using attr */
- if (l->val != NULL)
- ldap_value_free_len(l->val);
- /*
- if (ent != NULL)
- ldap_msgfree(ent);
- */
- if (l->lm != NULL) {
- ldap_msgfree(l->lm);
- l->lm = NULL;
- }
- l->num_ent = 0;
- l->num_val = 0;
- l->err = LDAP_NO_SUCH_OBJECT;
- l->status &= ~(LDAP_SEARCH_S);
- return LDAP_ERR_NOTFOUND; /* Not found */
-}
-
-/*
- * SearchIPLDAP() - <edui_ldap_t> <result-uid>
+ * SearchIPLDAP() - <edui_ldap_t>
*
* Scan LDAP and get all networkAddress Values, and see if they match l->search_ip
* Actual IP matching routine for eDirectory
*
*/
-int SearchIPLDAP(edui_ldap_t *l, char *uid)
+int SearchIPLDAP(edui_ldap_t *l)
{
ber_len_t i, x;
ber_len_t j, k;
char bufa[EDUI_MAXLEN], bufb[EDUI_MAXLEN], hexc[4];
LDAPMessage *ent;
if (l == NULL) return LDAP_ERR_NULL;
- if (uid == NULL) return LDAP_ERR_PARAM;
if (l->lp == NULL) return LDAP_ERR_POINTER;
if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */
if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */
if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */
if (!(l->status & LDAP_SEARCH_S)) return LDAP_ERR_NOT_SEARCHED; /* Not searched */
- if (l->num_ent <= 0) return LDAP_ERR_DATA; /* No entries found */
+ if (l->num_ent <= 0) {
+ debug("l->num_ent: %d\n", l->num_ent);
+ return LDAP_ERR_DATA; /* No entries found */
+ }
if (l->val != NULL)
ldap_value_free_len(l->val); /* Clear data before populating */
l->num_val = 0;
if (l->status & LDAP_VAL_S)
l->status &= ~(LDAP_VAL_S); /* Clear VAL bit */
if (edui_conf.attrib[0] == '\0')
- xstrncpy(edui_conf.attrib, "cn", sizeof(edui_conf.attrib)); /* Make sure edui_conf.attrib is set */
+ xstrncpy(edui_conf.attrib, "cn", sizeof(edui_conf.attrib)); /* Make sure edui_conf.attrib is set */
/* Sift through entries */
struct berval **ber = NULL;
for (i = 0; i < x; i++) {
j = l->val[i]->bv_len;
memcpy(bufa, l->val[i]->bv_val, j);
- z = SplitString(bufa, j, '#', bufb, sizeof(bufb));
- /* DEBUGGING ONLY *
- local_debug("SearchIPLDAP", "value[%zd]: SplitString(", i);
- for (k = 0; k < z; k++) {
- c = (int) bufb[k];
- if (c < 0)
- c = c + 256;
- local_debugx("%.2X", c);
- }
- local_debugx(", ");
- for (k = 0; k < (j - z - 1); k++) {
- c = (int) bufa[k];
- if (c < 0)
- c = c + 256;
- local_debugx("%.2X", c);
- }
- local_debugx("): %zd\n", z);
- */
+ z = BinarySplit(bufa, j, '#', bufb, sizeof(bufb));
+ /* BINARY DEBUGGING *
+ local_printfx("value[%zd]: BinarySplit(", (size_t) i);
+ for (k = 0; k < z; k++) {
+ c = (int) bufb[k];
+ if (c < 0)
+ c = c + 256;
+ local_printfx("%02X", c);
+ }
+ local_printfx(", ");
+ for (k = 0; k < (j - z - 1); k++) {
+ c = (int) bufa[k];
+ if (c < 0)
+ c = c + 256;
+ local_printfx("%02X", c);
+ }
+ local_printfx("): %zd\n", (size_t) z);
+ * BINARY DEBUGGING */
z = j - z - 1;
j = atoi(bufb);
- switch (j) {
- case 0: /* IPX address (We don't support these right now) */
- break;
- case 1: /* IPv4 address (eDirectory 8.7 and below) */
+ if (j == 1) {
+ /* IPv4 address (eDirectory 8.7 and below) */
/* bufa is the address, just compare it */
if (!(l->status & LDAP_IPV4_S) || (l->status & LDAP_IPV6_S))
break; /* Not looking for IPv4 */
c = (int) bufa[k];
if (c < 0)
c = c + 256;
- int hlen = snprintf(hexc, sizeof(hexc), "%.2X", c);
+ int hlen = snprintf(hexc, sizeof(hexc), "%02X", c);
if (k == 0)
xstrncpy(bufb, hexc, sizeof(bufb));
else
if (memcmp(l->search_ip, bufb, y) == 0) {
/* We got a match! - Scan 'ber' for 'cn' values */
z = ldap_count_values_len(ber);
- for (j = 0; j < z; j++)
- xstrncpy(uid, ber[j]->bv_val, min(sizeof(uid),static_cast<size_t>(ber[j]->bv_len)));
- ldap_value_free_len(l->val);
- l->val = NULL;
- ldap_value_free_len(ber);
- ber = NULL;
- l->num_val = 0;
- l->err = LDAP_SUCCESS;
- l->status &= ~(LDAP_SEARCH_S);
- return LDAP_ERR_SUCCESS; /* We got our userid */
- }
- /* Not matched, continue */
- break;
- case 8: /* IPv4 (UDP) address (eDirectory 8.8 and higher) */
- /* bufa + 2 is the address (skip 2 digit port) */
- if (!(l->status & LDAP_IPV4_S) || (l->status & LDAP_IPV6_S))
- break; /* Not looking for IPv4 */
- for (k = 2; k < z; k++) {
- c = (int) bufa[k];
- if (c < 0)
- c = c + 256;
- int hlen = snprintf(hexc, sizeof(hexc), "%.2X", c);
- if (k == 2)
- xstrncpy(bufb, hexc, sizeof(bufb));
- else
- strncat(bufb, hexc, hlen);
- }
- y = strlen(bufb);
- /* Compare value with IP */
- if (memcmp(l->search_ip, bufb, y) == 0) {
- /* We got a match! - Scan 'ber' for 'cn' values */
- z = ldap_count_values_len(ber);
- for (j = 0; j < z; j++)
- xstrncpy(uid, ber[j]->bv_val, min(sizeof(uid),static_cast<size_t>(ber[j]->bv_len)));
+ for (j = 0; j < z; j++) {
+// broken? xstrncpy(l->userid, ber[j]->bv_val, min(sizeof(l->userid),static_cast<size_t>(ber[j]->bv_len)));
+ xstrncpy(l->userid, ber[j]->bv_val, sizeof(l->userid));
+ /* Using bv_len of min() breaks the result by 2 chars */
+ }
ldap_value_free_len(l->val);
l->val = NULL;
ldap_value_free_len(ber);
return LDAP_ERR_SUCCESS; /* We got our userid */
}
/* Not matched, continue */
- break;
- case 9: /* IPv4 (TCP) address (eDirectory 8.8 and higher) */
+ } else if ((j == 8) || (j == 9)) {
+ /* IPv4 (UDP/TCP) address (eDirectory 8.8 and higher) */
/* bufa + 2 is the address (skip 2 digit port) */
if (!(l->status & LDAP_IPV4_S) || (l->status & LDAP_IPV6_S))
break; /* Not looking for IPv4 */
c = (int) bufa[k];
if (c < 0)
c = c + 256;
- int hlen = snprintf(hexc, sizeof(hexc), "%.2X", c);
+ int hlen = snprintf(hexc, sizeof(hexc), "%02X", c);
if (k == 2)
xstrncpy(bufb, hexc, sizeof(bufb));
else
/* We got a match! - Scan 'ber' for 'cn' values */
z = ldap_count_values_len(ber);
for (j = 0; j < z; j++)
- xstrncpy(uid, ber[j]->bv_val, min(sizeof(uid),static_cast<size_t>(ber[j]->bv_len)));
+// broken? xstrncpy(l->userid, ber[j]->bv_val, min(sizeof(l->userid),static_cast<size_t>(ber[j]->bv_len)));
+ xstrncpy(l->userid, ber[j]->bv_val, sizeof(l->userid));
ldap_value_free_len(l->val);
l->val = NULL;
ldap_value_free_len(ber);
return LDAP_ERR_SUCCESS; /* We got our userid */
}
/* Not matched, continue */
- break;
- case 10: /* IPv6 (UDP) address (eDirectory 8.8 and higher) */
+ } else if ((j == 10) || (j == 11)) {
+ /* IPv6 (UDP/TCP) address (eDirectory 8.8 and higher) */
/* bufa + 2 is the address (skip 2 digit port) */
if (!(l->status & LDAP_IPV6_S))
break; /* Not looking for IPv6 */
c = (int) bufa[k];
if (c < 0)
c = c + 256;
- int hlen = snprintf(hexc, sizeof(hexc), "%.2X", c);
+ int hlen = snprintf(hexc, sizeof(hexc), "%02X", c);
if (k == 2)
xstrncpy(bufb, hexc, sizeof(bufb));
else
/* We got a match! - Scan 'ber' for 'cn' values */
z = ldap_count_values_len(ber);
for (j = 0; j < z; j++)
- xstrncpy(uid, ber[j]->bv_val, min(sizeof(uid),static_cast<size_t>(ber[j]->bv_len)));
+// broken? xstrncpy(l->userid, ber[j]->bv_val, min(sizeof(l->userid),static_cast<size_t>(ber[j]->bv_len)));
+ xstrncpy(l->userid, ber[j]->bv_val, sizeof(l->userid));
ldap_value_free_len(l->val);
l->val = NULL;
ldap_value_free_len(ber);
return LDAP_ERR_SUCCESS; /* We got our userid */
}
/* Not matched, continue */
- break;
- case 11: /* IPv6 (TCP) address (eDirectory 8.8 and higher) */
- /* bufa + 2 is the address (skip 2 digit port) */
- if (!(l->status & LDAP_IPV6_S))
- break; /* Not looking for IPv6 */
- for (k = 2; k < z; k++) {
- c = (int) bufa[k];
- if (c < 0)
- c = c + 256;
- int hlen = snprintf(hexc, sizeof(hexc), "%.2X", c);
- if (k == 2)
- xstrncpy(bufb, hexc, sizeof(bufb));
- else
- strncat(bufb, hexc, hlen);
- }
- y = strlen(bufb);
- /* Compare value with IP */
- if (memcmp(l->search_ip, bufb, y) == 0) {
- /* We got a match! - Scan 'ber' for 'cn' values */
- z = ldap_count_values_len(ber);
- for (j = 0; j < z; j++)
- xstrncpy(uid, ber[j]->bv_val, min(sizeof(uid),static_cast<size_t>(ber[j]->bv_len)));
- ldap_value_free_len(l->val);
- l->val = NULL;
- ldap_value_free_len(ber);
- ber = NULL;
- l->num_val = 0;
- l->err = LDAP_SUCCESS;
- l->status &= ~(LDAP_SEARCH_S);
- return LDAP_ERR_SUCCESS; /* We gout our userid */
- }
- /* Not matched, continue */
- break;
- default: /* Other, unsupported */
- break;
}
+// else {
+ /* Others are unsupported */
+// }
}
if (ber != NULL) {
ldap_value_free_len(ber);
memset(bufb, '\0', sizeof(bufb));
memset(bufc, '\0', sizeof(bufc));
memset(sfmod, '\0', sizeof(sfmod));
+
InitConf();
xstrncpy(edui_conf.program, argv[0], sizeof(edui_conf.program));
edui_now = -1;
t = -1;
-// debug("InitConf() done.\n");
/* Scan args */
if (k > 1) {
case 'd':
if (!(edui_conf.mode & EDUI_MODE_DEBUG))
edui_conf.mode |= EDUI_MODE_DEBUG; /* Don't set mode more than once */
- debug_enabled = 1; /* Squid-3 Debug Mode */
+ debug_enabled = 1; /* Official Squid-3 Debug Mode */
break;
case '4':
if (!(edui_conf.mode & EDUI_MODE_IPV4) || !(edui_conf.mode & EDUI_MODE_IPV6))
- edui_conf.mode |= EDUI_MODE_IPV4; /* Don't set mode more than once */
+ edui_conf.mode |= EDUI_MODE_IPV4; /* Don't set mode more than once */
break;
case '6':
if (!(edui_conf.mode & EDUI_MODE_IPV4) || !(edui_conf.mode & EDUI_MODE_IPV6))
- edui_conf.mode |= EDUI_MODE_IPV6; /* Don't set mode more than once */
+ edui_conf.mode |= EDUI_MODE_IPV6; /* Don't set mode more than once */
break;
case 'Z':
if (!(edui_conf.mode & EDUI_MODE_TLS))
- edui_conf.mode |= EDUI_MODE_TLS; /* Don't set mode more than once */
+ edui_conf.mode |= EDUI_MODE_TLS; /* Don't set mode more than once */
break;
case 'P':
if (!(edui_conf.mode & EDUI_MODE_PERSIST))
- edui_conf.mode |= EDUI_MODE_PERSIST; /* Don't set mode more than once */
+ edui_conf.mode |= EDUI_MODE_PERSIST; /* Don't set mode more than once */
break;
case 'v':
- i++;
+ i++; /* Set LDAP version */
if (argv[i] != NULL) {
edui_conf.ver = atoi(argv[i]);
if (edui_conf.ver < 1)
}
break;
case 't':
- i++;
+ i++; /* Set Persistent timeout */
if (argv[i] != NULL) {
edui_conf.persist_timeout = atoi(argv[i]);
if (edui_conf.persist_timeout < 0)
}
break;
case 'b':
- i++; /* Set Base DN */
+ i++; /* Set Base DN */
if (argv[i] != NULL)
xstrncpy(edui_conf.basedn, argv[i], sizeof(edui_conf.basedn));
else {
}
break;
case 'H':
- i++; /* Set Hostname */
+ i++; /* Set Hostname */
if (argv[i] != NULL)
xstrncpy(edui_conf.host, argv[i], sizeof(edui_conf.host));
else {
}
break;
case 'p':
- i++; /* Set port */
+ i++; /* Set port */
if (argv[i] != NULL)
edui_conf.port = atoi(argv[i]);
else {
}
break;
case 'D':
- i++; /* Set Bind DN */
+ i++; /* Set Bind DN */
if (argv[i] != NULL)
xstrncpy(edui_conf.dn, argv[i], sizeof(edui_conf.dn));
else {
}
break;
case 'W':
- i++; /* Set Bind PWD */
+ i++; /* Set Bind PWD */
if (argv[i] != NULL)
xstrncpy(edui_conf.passwd, argv[i], sizeof(edui_conf.passwd));
else {
}
break;
case 'F':
- i++; /* Set Search Filter */
+ i++; /* Set Search Filter */
if (argv[i] != NULL)
xstrncpy(edui_conf.search_filter, argv[i], sizeof(edui_conf.search_filter));
else {
edui_conf.mode |= EDUI_MODE_GROUP; /* Don't set mode more than once */
break;
case 's':
- i++; /* Set Scope Level */
+ i++; /* Set Scope Level */
if (argv[i] != NULL) {
if (!strncmp(argv[i], "base", 4))
edui_conf.scope = 0;
return 1;
}
break;
- case '-': /* We got a second '-' ... ignore */
+ case '-': /* We got a second '-' ... ignore */
break;
default:
local_printfx("Invalid parameter - '%c'.\n", argv[i][j]);
DisplayUsage();
return 1;
}
- debug("Configuration done.\n");
-
- DisplayConf();
- /* Done with arguments */
-
/* Trap the following signals */
sigemptyset(&sv.sa_mask);
sv.sa_handler = SigTrap;
sigaction(SIGINT, &sv, NULL);
sv.sa_handler = SigTrap;
sigaction(SIGSEGV, &sv, NULL);
-// debug("Signals trapped.\n");
+
+ DisplayConf();
+ /* Done with arguments */
/* Set elap timer */
time(&edui_now);
t = edui_now;
-
/* Main loop -- Waits for stdin input before action */
while (fgets(bufa, sizeof(bufa), stdin) != NULL) {
if (edui_conf.mode & EDUI_MODE_KILL)
if (t < edui_now) {
/* Elapse seconds */
edui_elap = edui_now - t;
-// debug("while() -> %d seconds elapsed.\n", edui_elap);
t = edui_now;
} else
edui_elap = 0;
k = strlen(bufa);
- /* *** Extended DEBUGGING ONLY ***
- local_debug("main", "while() -> bufa[%zd]: %s", k, bufa);
- local_debug("main", "while() -> bufa[%zd]: ");
- for (i = 0; i < k; i++)
- local_debugx("%.2X", bufa[i]);
- local_debugx("\n");
- */
+ /* BINARY DEBUGGING *
+ local_printfx("while() -> bufa[%zd]: %s", k, bufa);
+ for (i = 0; i < k; i++)
+ local_printfx("%02X", bufa[i]);
+ local_printfx("\n");
+ * BINARY DEBUGGING */
/* Check for CRLF */
p = strchr(bufa, '\n');
if (p != NULL)
/* If we got a group string, split it */
if (p != NULL) {
/* Split string */
-// debug("SplitString(%s, %zd, ' ', %s, %zd)\n", bufa, strlen(bufa), bufb, sizeof(bufb));
- i = SplitString(bufa, strlen(bufa), ' ', bufb, sizeof(bufb));
+ debug("StringSplit(%s, ' ', %s, %zd)\n", bufa, bufb, sizeof(bufb));
+ i = StringSplit(bufa, ' ', bufb, sizeof(bufb));
if (i > 0) {
- debug("SplitString(%s, %s) done. Result: %zd\n", bufa, bufb, i);
+ debug("StringSplit(%s, %s) done. Result: %zd\n", bufa, bufb, i);
/* Got a group to match against */
x = ConvertIP(&edui_ldap, bufb);
if (x < 0) {
} else {
edui_ldap.err = -1;
debug("SearchLDAP(-, %d, %s, -) -> %s\n", edui_conf.scope, edui_ldap.search_filter, ErrLDAP(x));
- x = SearchIPLDAP(&edui_ldap, bufc);
+ x = SearchIPLDAP(&edui_ldap);
if (x != LDAP_ERR_SUCCESS) {
debug("SearchIPLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
local_printfx("ERR (SearchIPLDAP: %s)\n", ErrLDAP(x));
} else {
- debug("SearchIPLDAP(-, %s) -> %s\n", bufc, ErrLDAP(x));
- local_printfx("OK user=%s\n", bufc); /* Got userid --> OK user=<userid> */
+ debug("SearchIPLDAP(-, %s) -> %s\n", edui_ldap.userid, ErrLDAP(x));
+ local_printfx("OK user=%s\n", edui_ldap.userid); /* Got userid --> OK user=<userid> */
}
}
/* Clear for next query */
- memset(bufc, '\0', strlen(bufc));
+ memset(bufc, '\0', sizeof(bufc));
}
}
} else {
- debug("SplitString() -> Error: %Zu\n", i);
- local_printfx("ERR (SplitString Error %d)\n", i);
+ debug("StringSplit() -> Error: %Zu\n", i);
+ local_printfx("ERR (StringSplit Error %d)\n", i);
}
} else {
/* No group to match against, only an IP */
} else {
edui_ldap.err = -1;
debug("SearchLDAP(-, %d, %s, -) -> %s\n", edui_conf.scope, edui_ldap.search_filter, ErrLDAP(x));
- x = SearchIPLDAP(&edui_ldap, bufc);
+ x = SearchIPLDAP(&edui_ldap);
if (x != LDAP_ERR_SUCCESS) {
debug("SearchIPLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
local_printfx("ERR (SearchIPLDAP: %s)\n", ErrLDAP(x));
} else {
- debug("SearchIPLDAP(-, %s) -> %s\n", bufc, ErrLDAP(x));
- local_printfx("OK user=%s\n", bufc); /* Got a userid --> OK user=<userid> */
+ debug("SearchIPLDAP(-, %s) -> %s\n", edui_ldap.userid, ErrLDAP(x));
+ local_printfx("OK user=%s\n", edui_ldap.userid); /* Got a userid --> OK user=<userid> */
}
}
}
/* Clear for next query */
- memset(bufc, '\0', strlen(bufc));
+ memset(bufc, '\0', sizeof(bufc));
}
}
/* Clear buffer and close for next data, if not persistent */
edui_ldap.err = -1;
- memset(bufa, '\0', strlen(bufa));
+ memset(bufa, '\0', sizeof(bufa));
if (!(edui_ldap.status & LDAP_PERSIST_S)) {
x = CloseLDAP(&edui_ldap);
debug("CloseLDAP(-) -> %s\n", ErrLDAP(x));
# Don't build without gssapi.h
if [ -f /usr/include/ldap.h -o -f /usr/local/include/ldap.h ]; then
# Won't link without SASL as well
- if [ -f /usr/include/sasl.h -o -f /usr/include/sasl/sasl.h ]; then
+ if [ -f /usr/include/sasl.h -o -f /usr/include/sasl/sasl.h -o -f /usr/local/include/sasl.h -o -f /usr/local/include/sasl/sasl.h ]; then
if [ -f /usr/lib/libsasl.a -o -f /usr/lib/libsasl2.a ]; then
exit 0
fi
if [ -f /usr/lib/libsasl.la -o -f /usr/lib/libsasl2.la ]; then
exit 0
fi
+ if [ -f /usr/lib/libsasl.so -o -f /usr/lib/libsasl2.so ]; then
+ exit 0
+ fi
+ if [ -f /usr/local/lib/libsasl.so -o -f /usr/local/lib/libsasl2.so ]; then
+ exit 0
+ fi
fi
fi
exit 1
#include <string.h>
#endif
-#if HAVE_HEIMDAL_KERBEROS
#if HAVE_GSSAPI_GSSAPI_H
#include <gssapi/gssapi.h>
#elif HAVE_GSSAPI_H
#include <gssapi.h>
#endif /* HAVE_GSSAPI_GSSAPI_H/HAVE_GSSAPI_H */
-#if HAVE_KRB5_H
-#if HAVE_BROKEN_SOLARIS_KRB5_H
-#warn "Warning! You have a broken Solaris <krb5.h> fsystem header"
-#warn "http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6837512"
-#endif /* HAVE_BROKEN_SOLARIS_KRB5_H */
-#include <krb5.h>
-#endif /* HAVE_KRB5_H */
-#if HAVE_COM_ERR_H
-#include <com_err.h>
-#else
-#define error_message(code) krb5_get_err_text(kparam.context,code)
-#endif /* HAVE_COM_ERR_H */
-#else /*MIT */
-#ifdef HAVE_GSSAPI_GSSAPI_H
-#include <gssapi/gssapi.h>
-#elif defined(HAVE_GSSAPI_H)
-#include <gssapi.h>
-#endif
-#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
+
+#if !HAVE_HEIMDAL_KERBEROS
+#if HAVE_GSSAPI_GSSAPI_KRB5_H
#include <gssapi/gssapi_krb5.h>
#endif
-#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#if HAVE_GSSAPI_GSSAPI_GENERIC_H
#include <gssapi/gssapi_generic.h>
#endif
-#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
+#if HAVE_GSSAPI_GSSAPI_EXT_H
#include <gssapi/gssapi_ext.h>
#endif
-#ifdef HAVE_KRB5_H
+#endif
+
+#if HAVE_KRB5_H
#if HAVE_BROKEN_SOLARIS_KRB5_H
+#warn "Warning! You have a broken Solaris <krb5.h> system header"
+#warn "http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6837512"
#if defined(__cplusplus)
#define KRB5INT_BEGIN_DECLS extern "C" {
#define KRB5INT_END_DECLS
KRB5INT_BEGIN_DECLS
#endif
-#endif
+#endif /* HAVE_BROKEN_SOLARIS_KRB5_H */
+#if HAVE_BROKEN_HEIMDAL_KRB5_H
+extern "C" {
+#include <krb5.h>
+}
+#else
#include <krb5.h>
#endif
-#ifdef HAVE_COM_ERR_H
+#endif /* HAVE_KRB5_H */
+
+#if HAVE_COM_ERR_H
#include <com_err.h>
-#endif
-#endif
+#elif HAVE_HEIMDAL_KERBEROS
+#define error_message(code) krb5_get_err_text(kparam.context,code)
+#endif /* HAVE_COM_ERR_H */
+
#ifndef gss_nt_service_name
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
#endif
gettimeofday(&now, NULL);
if (now.tv_sec != last_t) {
- tm = localtime(&now.tv_sec);
+ time_t tmp = now.tv_sec;
+ tm = localtime(&tmp);
strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
last_t = now.tv_sec;
}
#!/bin/sh
-
-for sambaprefix in ${SAMBAPREFIX} /usr/local /opt /opt/samba /usr/local/samba /usr
+samba_found="no"
+for sambaprefix in /usr/local /opt /opt/samba /usr/local/samba /usr
do
- for perlprefix in /usr /usr/local /opt /opt/perl
- do
- if [ -x $sambaprefix/bin/wbinfo -a -x $perlprefix/bin/perl ]; then
- exit 0
- fi
- done
+ if [ -x $sambaprefix/bin/wbinfo ]; then
+ samba_found="yes"
+ fi
+done
+if test "$samba_found" = "no"; then
+ echo "WARNING: Samba wbinfo not found in default location. ext_wbinfo_group_acl may not work on this machine"
+fi
+for perlprefix in /usr /usr/local /opt /opt/perl
+do
+ if [ -x $perlprefix/bin/perl ]; then
+ exit 0
+ fi
done
exit 1
--- /dev/null
+include $(top_srcdir)/src/Common.am
+
+libexec_SCRIPTS = log_db_daemon
+CLEANFILES += log_db_daemon log_db_daemon.8
+man_MANS = log_db_daemon.8
+EXTRA_DIST= \
+ config.test \
+ doc/views.sql \
+ doc/date_day_column.sql \
+ log_db_daemon.8 \
+ log_db_daemon.pl.in
+
+log_db_daemon.8: log_db_daemon
+ pod2man log_db_daemon log_db_daemon.8
+
+log_db_daemon: log_db_daemon.pl.in
+ $(subst_perlshell)
--- /dev/null
+#!/bin/sh
+
+## Test: do we have perl to build the helper scripts?
+## Test: do we have pod2man to build the manual?
+perl --version >/dev/null && echo | pod2man >/dev/null
+
+exit $?
--- /dev/null
+-- we need a separate column to store the date and time of the request
+ALTER TABLE access_log ADD COLUMN date_day DATE;
+ALTER TABLE access_log ADD COLUMN date_time TIME;
+
+-- let's populate the new columns, in case some rows already exist;
+-- the date and time values should be set by a trigger
+UPDATE access_log SET date_day = DATE(FROM_UNIXTIME(time_since_epoch));
+UPDATE access_log SET date_time = TIME(FROM_UNIXTIME(time_since_epoch));
+
+-- let's create a view that uses the date column
+CREATE VIEW requests_per_day_2 AS SELECT date_day, COUNT(*) AS num_of_requests FROM access_log GROUP BY 1 ORDER BY 1;
+
+-- that view needs an index on the group by column
+CREATE INDEX date_day_idx ON access_log(date_day);
+
+
+-- a trigger that automatically extracts the date value from the time_since_epoch column
+-- and stores it in the date_day column
+DELIMITER //
+CREATE TRIGGER extract_date_day_bi BEFORE INSERT ON access_log FOR EACH ROW
+BEGIN
+ SET NEW.date_day = DATE(FROM_UNIXTIME(NEW.time_since_epoch));
+ SET NEW.date_time = TIME(FROM_UNIXTIME(NEW.time_since_epoch));
+END //
+
+
+-- Note: after running this script against an already populated access_log,
+-- views have to be recreated, or the new date_day column will not show up.
--- /dev/null
+--
+-- Sample views
+--
+
+-- ip address of hosts accessing the cache
+CREATE OR REPLACE VIEW cache_clients AS
+ SELECT DISTINCT ip_client FROM access_log ORDER BY 1;
+
+-- this index helps view 'cache_clients'
+CREATE INDEX client_ip_idx ON access_log(ip_client);
+
+
+-- traffic by client
+CREATE OR REPLACE VIEW traffic_by_client AS
+ SELECT
+ ip_client,
+ SUM(http_reply_size) AS total_bytes,
+ SUM(http_reply_size)/1024 AS total_kilobytes,
+ SUM(http_reply_size)/1048576 AS total_megabytes
+ FROM access_log
+ GROUP BY 1
+ ORDER BY 1;
+
+-- most active clients
+-- same as before, but sorted by traffic;
+-- show only the 10 most active clients
+CREATE OR REPLACE VIEW most_active_clients AS
+ SELECT
+ ip_client,
+ SUM(http_reply_size) AS total_bytes,
+ SUM(http_reply_size)/1024 AS total_kilobytes,
+ SUM(http_reply_size)/1048576 AS total_megabytes
+ FROM access_log
+ GROUP BY 1
+ ORDER BY 2 DESC
+ LIMIT 10;
+
+
+-- traffic per day
+CREATE OR REPLACE VIEW traffic_per_day AS
+ SELECT
+ date_day,
+ SUM(http_reply_size) AS total_bytes,
+ SUM(http_reply_size)/1024 AS total_kilobytes,
+ SUM(http_reply_size)/1048576 AS total_megabytes
+ FROM access_log
+ GROUP BY 1
+ ORDER BY 1;
+
+-- traffic by client per day
+CREATE OR REPLACE VIEW traffic_per_day_per_client AS
+ SELECT
+ date_day,
+ ip_client,
+ SUM(http_reply_size) AS total_bytes,
+ SUM(http_reply_size)/1024 AS total_kilobytes,
+ SUM(http_reply_size)/1048576 AS total_megabytes
+ FROM access_log
+ GROUP BY 1,2
+ ORDER BY 1,2 DESC;
+
+CREATE OR REPLACE VIEW traffic_per_month_per_client AS
+ SELECT
+ YEAR(date_day) AS date_year,
+ MONTH(date_day) AS date_month,
+ ip_client,
+ SUM(http_reply_size) AS total_bytes,
+ SUM(http_reply_size)/1024 AS total_kilobytes,
+ SUM(http_reply_size)/1048576 AS total_megabytes
+ FROM access_log
+ GROUP BY 2,3
+ ORDER BY 1,2,3;
+
+-- list of clients with some stats
+CREATE OR REPLACE VIEW cache_clients_with_infos AS
+SELECT
+ a.ip_client,
+ COUNT(*) AS total_requests,
+ (COUNT(*)/(SELECT COUNT(*) FROM access_log))*100 AS requests_perc,
+ SUM(a.http_reply_size) AS total_traffic,
+ (SUM(a.http_reply_size)/(SELECT SUM(http_reply_size) FROM access_log))*100 AS traffic_perc,
+ (SELECT COUNT(*) FROM access_log a1 WHERE a1.ip_client=a.ip_client AND squid_request_status LIKE '%HIT%')
+ /
+ (SELECT COUNT(*) FROM access_log)
+ * 100 AS hit_perc,
+ (SELECT COUNT(*) FROM access_log a1 WHERE a1.ip_client=a.ip_client AND squid_request_status LIKE '%MISS%')
+ /
+ (SELECT COUNT(*) FROM access_log)
+ * 100 AS miss_perc,
+ MIN(date_day) AS first_access_date,
+ MIN(date_time) AS first_access_time,
+ MAX(date_day) AS last_access_date,
+ MAX(date_time) AS last_access_time
+FROM access_log a
+GROUP BY 1
+ORDER BY 1;
+
+-- this index helps view 'cache_clients_with_infos'
+CREATE INDEX client_req_status_idx ON access_log(ip_client, squid_request_status);
+
+
+-- number of requests per day
+CREATE OR REPLACE VIEW requests_per_day AS
+ SELECT
+ DATE(FROM_UNIXTIME(time_since_epoch)) AS date_day,
+ COUNT(*) AS num_of_requests
+ FROM access_log
+ GROUP BY 1
+ ORDER BY 1;
+
+-- number of requests per minute
+CREATE OR REPLACE VIEW requests_per_minute AS
+ SELECT
+ DATE(FROM_UNIXTIME(time_since_epoch)) AS date_day,
+ HOUR(FROM_UNIXTIME(time_since_epoch)) AS date_hour,
+ MINUTE(FROM_UNIXTIME(time_since_epoch)) AS date_minute,
+ COUNT(*) AS num_of_requests
+ FROM access_log
+ GROUP BY 1,2,3
+ ORDER BY 1,2,3;
+
+-- number of requests per day of each cache client
+CREATE OR REPLACE VIEW requests_per_day_per_client AS
+ SELECT
+ DATE(FROM_UNIXTIME(time_since_epoch)) AS date_day,
+ ip_client,
+ COUNT(*) AS num_of_requests
+ FROM access_log
+ GROUP BY 1,2
+ ORDER BY 1,2;
+
+-- percentage of each request status
+CREATE OR REPLACE VIEW requests_status_perc AS
+ SELECT
+ squid_request_status,
+ (COUNT(*)/(SELECT COUNT(*) FROM access_log)*100) AS percentage
+ FROM access_log
+ GROUP BY squid_request_status
+ ORDER BY 2 DESC;
+
+-- this index helps view 'requests_status_perc'
+CREATE INDEX req_status_idx ON access_log(squid_request_status);
+
+-- request hits and misses, in percentage
+CREATE OR REPLACE VIEW hits_misses_perc AS
+ SELECT
+ 'hits',
+ (SELECT COUNT(*) FROM access_log WHERE squid_request_status LIKE '%HIT%')
+ /
+ (SELECT COUNT(*) FROM access_log)*100
+ AS percentage
+UNION
+ SELECT
+ 'misses',
+ (SELECT COUNT(*) FROM access_log WHERE squid_request_status LIKE '%MISS%')
+ /
+ (SELECT COUNT(*) FROM access_log)*100
+ AS pecentage;
+
+-- response times
+CREATE OR REPLACE VIEW time_response_ranges AS
+ SELECT
+ '0..500',
+ COUNT(*) / (SELECT COUNT(*) FROM access_log)*100 AS percentage
+ FROM access_log
+ WHERE time_response >= 0 AND time_response < 500
+UNION
+ SELECT
+ '500..1000',
+ COUNT(*) / (SELECT COUNT(*) FROM access_log)*100 AS percentage
+ FROM access_log
+ WHERE time_response >= 500 AND time_response < 1000
+UNION
+ SELECT
+ '1000..2000',
+ COUNT(*) / (SELECT COUNT(*) FROM access_log)*100 AS percentage
+ FROM access_log
+ WHERE time_response >= 1000 AND time_response < 2000
+UNION
+ SELECT
+ '>= 2000',
+ COUNT(*) / (SELECT COUNT(*) FROM access_log)*100 AS percentage
+ FROM access_log
+ WHERE time_response >= 2000;
+
+-- this index helps view 'time_response_ranges'
+CREATE INDEX time_response_idx ON access_log(time_response);
+
+-- response time graph
+CREATE OR REPLACE VIEW time_response_graph AS
+ SELECT
+ time_response,
+ COUNT(*) AS num_req
+ FROM access_log
+ GROUP BY 1
+ ORDER BY 1;
+
+-- traffic by mime type
+CREATE OR REPLACE VIEW traffic_by_http_mime_type AS
+ SELECT
+ http_mime_type,
+ SUM(http_reply_size) as total_bytes
+ FROM access_log
+ GROUP BY http_mime_type
+ ORDER BY 2 DESC;
+
+-- last 10 queries
+CREATE OR REPLACE VIEW last_10_queries AS
+ SELECT *
+ FROM access_log
+ WHERE
+ id > (SELECT MAX(id) FROM access_log) - 10
+ ORDER BY id DESC;
+
+-- id of the last query of each client
+-- this view is required by the "last n queries by ip" view
+CREATE OR REPLACE VIEW last_query_by_client AS
+ SELECT
+ ip_client,
+ MAX(id) AS last_query_id
+ FROM access_log
+ GROUP BY ip_client;
+
+
+-- last 10 queries of each client
+-- NOTE: this query is conceptually wrong because it assumes that no holes exist
+-- in the values of column 'id'.
+-- This can be false if e.g. some access_log entries get deleted...
+CREATE OR REPLACE VIEW last_10_queries_by_client AS
+ SELECT *
+ FROM access_log a
+ WHERE
+ id > (
+ SELECT l.last_query_id
+ FROM last_query_by_client l
+ WHERE l.ip_client = a.ip_client
+ ) - 10
+ ORDER BY a.ip_client, a.id DESC;
+
+-- this index helps the "last_10_queries_by_client" view
+CREATE INDEX client_ip_record_id_idx ON access_log(ip_client, id);
+
+
+-- number of HIT requests per day
+CREATE OR REPLACE VIEW hits_per_day AS
+ SELECT
+ date_day,
+ COUNT(*) AS num_hits
+ FROM access_log
+ WHERE squid_request_status LIKE '%HIT%'
+ GROUP BY 1;
+
+-- HIT requests per day, percent (100% = total number of requests that day)
+CREATE OR REPLACE VIEW hits_per_day_perc AS
+ SELECT
+ r.date_day,
+ h.num_hits/r.num_of_requests*100 AS hits_per_day_perc
+ FROM requests_per_day r
+ JOIN
+ hits_per_day h
+ ON r.date_day = h.date_day;
+
+
+-- request methods (count)
+CREATE OR REPLACE VIEW http_methods AS
+ SELECT
+ http_method,
+ COUNT(*)
+ FROM access_log
+ GROUP BY 1
+ ORDER BY 1;
+
+-- request methods by percent
+CREATE OR REPLACE VIEW http_methods_perc AS
+ SELECT
+ http_method,
+ COUNT(*) / (SELECT COUNT(*) FROM access_log) * 100 AS perc
+ FROM access_log
+ GROUP BY 1
+ ORDER BY 2 DESC;
+
+
+-- slowest queries
+CREATE OR REPLACE VIEW slowest_requests AS
+ SELECT *
+ FROM access_log
+ ORDER BY time_response DESC
+ LIMIT 10;
+
+
+CREATE OR REPLACE VIEW slowest_request_by_method AS
+ SELECT *
+ FROM access_log
+ GROUP BY http_method
+ ORDER BY http_method, time_response DESC;
+
+
+-- requests with the biggest reply size
+CREATE OR REPLACE VIEW biggest_requests AS
+ SELECT *
+ FROM access_log
+ ORDER BY http_reply_size DESC
+ LIMIT 10;
+
+
+
+-- list each day which has at least one request, with some statistics
+CREATE OR REPLACE VIEW days_with_infos AS
+ SELECT
+ date_day,
+ MIN(date_time) AS first_req_time,
+ MAX(date_time) AS last_req_time,
+ COUNT(*) AS number_of_requests,
+ SUM(http_reply_size) AS total_traffic_bytes,
+ SUM(http_reply_size) / 1048576 AS total_traffic_megabytes,
+ COUNT(DISTINCT ip_client) AS number_of_clients,
+ AVG(time_response) AS avg_time_response,
+ MAX(time_response) AS max_time_response,
+
+ -- client that has made the highest number of requests that day
+ (
+ SELECT ip_client
+ FROM requests_per_day_per_client r
+ WHERE r.date_day = a.date_day
+ ORDER BY r.num_of_requests DESC LIMIT 1
+ ) AS most_active_client_r,
+
+ -- the number of requests that client actually made
+ (
+ SELECT r.num_of_requests
+ FROM requests_per_day_per_client r
+ WHERE r.date_day = a.date_day
+ ORDER BY r.num_of_requests DESC LIMIT 1
+ ) AS most_active_client_r_nr,
+
+ -- same info but as percentage on the total number of requests that day
+ -- we have to repeat the whole query because we cannot reference aliases
+ -- defined in previous columns
+ -- a date_day column with an index on it would help here; a view would probably help too...
+ (
+ (
+ SELECT r.num_of_requests
+ FROM requests_per_day_per_client r
+ WHERE r.date_day = a.date_day
+ ORDER BY 1 DESC LIMIT 1
+ ) / (
+ SELECT COUNT(*)
+ FROM access_log a1
+ WHERE a.date_day = a1.date_day
+ ) * 100
+ ) AS most_active_client_r_pc,
+
+ -- client that has generated the highest traffic that day
+ (
+ SELECT t.ip_client
+ FROM traffic_per_day_per_client t
+ WHERE t.date_day = a.date_day
+ ORDER BY t.total_bytes DESC LIMIT 1
+ ) AS most_active_client_t,
+
+ -- the actual traffic generated by that client
+ (
+ SELECT t.total_bytes
+ FROM traffic_per_day_per_client t
+ WHERE t.date_day = a.date_day
+ ORDER BY t.total_bytes DESC LIMIT 1
+ ) AS most_active_client_t_b,
+
+ -- same info expressed in megabytes
+ (
+ SELECT t.total_bytes
+ FROM traffic_per_day_per_client t
+ WHERE t.date_day = a.date_day
+ ORDER BY t.total_bytes DESC LIMIT 1
+ ) / 1048576 AS most_active_client_t_mb,
+
+ -- same info in percentage on the total traffic that day
+ -- see previous comments
+ (
+ (
+ SELECT t.total_bytes
+ FROM traffic_per_day_per_client t
+ WHERE t.date_day = a.date_day
+ ORDER BY t.total_bytes DESC LIMIT 1
+ ) / (
+ SELECT SUM(http_reply_size)
+ FROM access_log a1
+ WHERE a.date_day = a1.date_day
+ ) * 100
+ ) AS most_active_client_t_pc
+
+ FROM access_log a
+ GROUP BY 1
+ ORDER BY 1;
+
+-- this index helps the "days_with_info" view
+CREATE INDEX date_day_idx ON access_log(date_day);
+
+
+CREATE OR REPLACE VIEW requests_in_last_minute AS
+ select * from access_log where time_since_epoch >= ( (select max(time_since_epoch) from access_log) - 60);
+
+
+CREATE OR REPLACE VIEW avg_req_per_minute AS
+ SELECT COUNT(*) FROM requests_in_last_minute;
--- /dev/null
+#!@PERL@
+use strict;
+use warnings;
+use DBI;
+use English qw( -no_match_vars );
+use Getopt::Long;
+use Pod::Usage;
+
+$|=1;
+
+=pod
+
+=head1 NAME
+
+log_db_daemon - Database logging daemon for Squid
+
+=head1 SYNOPSIS
+
+log_db_daemon DSN [options]
+
+=head1 DESCRIPTOIN
+
+This program writes Squid access.log entries to a database.
+Presently only accepts the B<squid> native format
+
+=over 8
+
+=item B<DSN>
+
+Database DSN encoded as a path. This is sent as the access_log file path.
+
+Sample configuration:
+ access_log daemon:/host/database/table/username/password squid
+
+ to leave a parameter unspecified use a double slash:
+ access_log daemon://database/table/username/password squid
+
+Default "DBI:mysql:database=squid"
+
+=item B<--debug>
+
+Write debug messages to Squid stderr or cache.log
+
+=cut
+
+# the first argument to this script is the log file path describing the DSN
+my $log_file = shift;
+
+# others may be options
+my $debug = 0;
+GetOptions(
+ 'debug' => \$debug,
+ );
+
+
+# utility routine to print messages on stderr (so they appear in cache log)
+# without using warn, which would clutter the log with source line numbers
+sub log_info {
+ my $msg = shift;
+ print STDERR "$msg\n";
+}
+
+# we use logfile to pass database access information to this script
+# sample configuration:
+# access_log daemon:/host/database/table/username/password squid
+# to let a parmeter unspecified, e.g. the database host, use a double slash:
+# access_log daemon://database/table/username/password squid
+my ( $host, $database, $table, $user, $pass ) = $log_file =~ / \/(.*?)\/(.*?)\/(.*?)\/(.*?)\/(.*?) \z /xms;
+
+if ( !$host ) {
+ $host = 'localhost';
+ log_info("Database host not specified. Using $host.");
+}
+
+if ( !$database ) {
+ $database = 'squid_log';
+ log_info("Database name not specified. Using $database.");
+}
+
+if ( !$table ) {
+ $table = 'access_log';
+ log_info("Table parameter not specified. Using $table.");
+}
+
+if ( !$user ) {
+ $user = 'squid';
+ log_info("User parameter not specified. Using $user.");
+}
+
+if ( !$pass ) {
+ log_info('No password specified. Connecting with NO password.');
+}
+
+# fields that we should have in the table
+# Order here must match the order of fields in the Log format and parse() output array.
+my @db_fields = qw(
+ id
+ time_since_epoch
+ time_response
+ ip_client
+ squid_request_status
+ http_status_code
+ http_reply_size
+ http_method
+ http_url
+ http_username
+ squid_hier_status
+ ip_server
+ http_mime_type
+);
+
+# perform db connection
+my $dsn = "DBI:mysql:database=$database" . ($host ne "localhost" ? ":$host" : "");
+my $dbh;
+my $sth;
+eval {
+ warn "Connecting... dsn='$dsn', username='$user', password='...'";
+ $dbh = DBI->connect($dsn, $user, $pass, { AutoCommit => 1, RaiseError => 1, PrintError => 1 });
+};
+if ($EVAL_ERROR) {
+ die "Cannot connect to database: $DBI::errstr";
+}
+
+
+# a simple test to assure the specified table exists
+eval {
+ my $q = 'SELECT ' . join(',',@db_fields) . " FROM $table LIMIT 1";
+ my $sth = $dbh->prepare($q);
+ $sth->execute;
+};
+if ($EVAL_ERROR) {
+ # run a query to create the table of required syntax
+ my $create_query = 'CREATE TABLE ' . $table . ' (' .
+ " id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY," .
+ " time_since_epoch DECIMAL(15,3)," .
+ " time_response INTEGER," .
+ " ip_client CHAR(15)," .
+ " ip_server CHAR(15)," .
+ " http_status_code VARCHAR(10)," .
+ " http_reply_size INTEGER," .
+ " http_method VARCHAR(20)," .
+ " http_url TEXT," .
+ " http_username VARCHAR(20)," .
+ " http_mime_type VARCHAR(50)," .
+ " squid_request_status VARCHAR(50)," .
+ " squid_hier_status VARCHAR(20)" .
+ ");" ;
+
+ $sth = $dbh->prepare($create_query);
+ $sth->execute;
+ # test again and fail hard if it is still broken.
+ eval {
+ my $q = 'SELECT ' . join(',',@db_fields) . " FROM $table LIMIT 1";
+ my $sth = $dbh->prepare($q);
+ $sth->execute;
+ };
+ if ($EVAL_ERROR) {
+ die "Error initializing database table: $EVAL_ERROR";
+ };
+}
+# test
+
+# for better performance, prepare the statement at startup
+eval {
+ my $q = "INSERT INTO $table (" . join(',',@db_fields) . ") VALUES(NULL" . ',?' x (scalar(@db_fields)-1) . ')';
+ #$sth = $dbh->prepare("INSERT INTO $table VALUES(NULL,?,?,?,?,?,?,?,?,?,?,?,?)");
+ $sth = $dbh->prepare($q);
+};
+if ($EVAL_ERROR) {
+ die "Error while preparing sql statement: $EVAL_ERROR";
+}
+
+sub parse($) {
+ my ($line) = @_;
+ my (@t) = $line =~ /^L(\d+\.\d+) *(\d+?) (.*?) (.*?)\/(\d+?) (\d+?) (.*?) (.*?) (.*?) (.*?)\/(.*?) (.*)$/;
+}
+
+# main loop
+while (my $line = <>) {
+ chomp $line;
+
+ my $cmd = substr($line, 0, 1); # extract command byte
+
+ if ( $cmd eq 'L' ) {
+ my @log_entry = parse($line);
+ eval { # we catch db errors to avoid crashing squid in case something goes wrong...
+ $sth->execute(@log_entry) or die $sth->errstr
+ };
+ if ( $EVAL_ERROR ) { # leave a trace of the error in the logs
+ warn $EVAL_ERROR . " values=(" . join(', ', @log_entry) . ')';
+ }
+ }
+}
+
+$dbh->disconnect();
+
+__END__
+
+=head1 DESCRIPTION
+
+This module exploits the new logfile daemon support available in squid 2.7 and 3.2 to store access log entries in a MySQL database.
+
+=head1 CONFIGURATION
+
+=head2 Squid configuration
+
+=head3 access_log directive
+
+The path to the access log file is used to provide the database connection parameters.
+
+ access_log daemon:/mysql_host:port/database/table/username/password squid
+
+The 'daemon' prefix is mandatory and tells squid that the B<logfile_daemon> helper is to be used instead of the normal file logging.
+
+The last parameter tells squid which log format to use when writing lines to the log daemon.
+Presently B<squid> format is supported.
+
+=over 4
+
+=item mysql_host:port
+
+Host where the mysql server is running. If left empty, 'localhost' is assumed.
+
+=item database
+
+Name of the database to connect to. If left empty, 'squid_log' is assumed.
+
+=item table
+
+Name of the database table where log lines are stored. If left empty, 'access_log' is assumed.
+
+=item username
+
+Username to use when connecting to the database. If left empty, 'squid' is assumed.
+
+=item password
+
+Password to use when connecting to the database. If left empty, no password is used.
+
+=back
+
+To leave all fields to their default values, you can use a single slash:
+
+ access_log daemon:/ squid
+
+To specify only the database password, which by default is empty, you must leave unspecified all the other parameters by using null strings:
+
+ access_log daemon://///password squid
+
+=head3 logfile_daemon directive
+
+This is the current way of telling squid where the logfile daemon resides.
+
+ logfile_daemon /path/to/squid/libexec/logfile-daemon_mysql.pl
+
+The script must be copied to the location specified in the directive.
+
+=head2 Database configuration
+
+Let's call the database 'squid_log' and the log table 'access_log'. The username and password for the db connection will be both 'squid'.
+
+=head3 Database
+
+Create the database:
+
+ CREATE DATABASE squid_log;
+
+=head3 User
+
+Create the user:
+
+ GRANT INSERT,SELECT,CREATE ON squid_log.* TO 'squid'@'localhost' IDENTIFIED BY 'squid';
+ FLUSH PRIVILEGES;
+
+Note that only CREATE, INSERT and SELECT privileges are granted to the 'squid' user. This ensures that the logfile daemon script cannot change or modify the log entries.
+
+=head3 Table
+
+The Daemon will attempt to initialize this table if none exists when it starts.
+
+The table created should look like:
+
+ CREATE TABLE access_log (
+ id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ time_since_epoch DECIMAL(15,3),
+ time_response INTEGER,
+ ip_client CHAR(15),
+ ip_server CHAR(15),
+ http_status_code VARCHAR(10),
+ http_reply_size INTEGER,
+ http_method VARCHAR(20),
+ http_url TEXT,
+ http_username VARCHAR(20),
+ http_mime_type VARCHAR(50),
+ squid_hier_status VARCHAR(20),
+ squid_request_status VARCHAR(20)
+ );
+
+=head1 VERSION INFORMATION
+
+This document refers to C<log_db_daemon> script version 0.5.
+
+The script has been developed and tested in the following environment:
+
+=over 4
+
+=item squid-2.7 Squid-3.2
+
+=item mysql 5.0.26 and 5.1
+
+=item perl 5.8.8
+
+=item OpenSUSE 10.2
+
+=back
+
+=head1 DATA EXTRACTION
+
+=head2 Sample queries.
+
+=over 4
+
+=item Clients accessing the cache
+
+ SELECT DISTINCT ip_client FROM access_log;
+
+=item Number of request per day
+
+ SELECT
+ DATE(FROM_UNIXTIME(time_since_epoch)) AS date_day,
+ COUNT(*) AS num_of_requests
+ FROM access_log
+ GROUP BY 1
+ ORDER BY 1;
+
+=item Request status count
+
+To obtain the raw count of each request status:
+
+ SELECT squid_request_status, COUNT(*) AS n
+ FROM access_log
+ GROUP BY squid_request_status
+ ORDER BY 2 DESC;
+
+To calculate the percentage of each request status:
+
+ SELECT
+ squid_request_status,
+ (COUNT(*)/(SELECT COUNT(*) FROM access_log)*100) AS percentage
+ FROM access_log
+ GROUP BY squid_request_status
+ ORDER BY 2 DESC;
+
+To distinguish only between HITs and MISSes:
+
+ SELECT
+ 'hits',
+ (SELECT COUNT(*)
+ FROM access_log
+ WHERE squid_request_status LIKE '%HIT%')
+ /
+ (SELECT COUNT(*) FROM access_log)*100
+ AS percentage
+ UNION
+ SELECT
+ 'misses',
+ (SELECT COUNT(*)
+ FROM access_log
+ WHERE squid_request_status LIKE '%MISS%')
+ /
+ (SELECT COUNT(*) FROM access_log)*100
+ AS pecentage;
+
+=item Response time ranges
+
+ SELECT
+ '0..500',
+ COUNT(*)/(SELECT COUNT(*) FROM access_log)*100 AS percentage
+ FROM access_log
+ WHERE time_response >= 0 AND time_response < 500
+ UNION
+ SELECT
+ '500..1000',
+ COUNT(*)/(SELECT COUNT(*) FROM access_log)*100 AS percentage
+ FROM access_log
+ WHERE time_response >= 500 AND time_response < 1000
+ UNION
+ SELECT
+ '1000..2000',
+ COUNT(*)/(SELECT COUNT(*) FROM access_log)*100 AS percentage
+ FROM access_log
+ WHERE time_response >= 1000 AND time_response < 2000
+ UNION
+ SELECT
+ '>= 2000',
+ COUNT(*)/(SELECT COUNT(*) FROM access_log)*100 AS percentage
+ FROM access_log
+ WHERE time_response >= 2000;
+
+=item Traffic by mime type
+
+ SELECT
+ http_mime_type,
+ SUM(http_reply_size) as total_bytes
+ FROM access_log
+ GROUP BY http_mime_type
+ ORDER BY 2 DESC;
+
+=item Traffic by client
+
+ SELECT
+ ip_client,
+ SUM(http_reply_size) AS total_bytes
+ FROM access_log
+ GROUP BY 1
+ ORDER BY 2 DESC;
+
+=back
+
+=head2 Speed issues
+
+The MyISAM storage engine is known to be faster than the InnoDB one, so although it doesn't support transactions and referential integrity, it might be more appropriate in this scenario. You might want to append "ENGINE=MYISAM" at the end of the table creation code in the above SQL script.
+
+Indexes should be created according to the queries that are more frequently run. The DDL script only creates an implicit index for the primary key column.
+
+=head1 TODO
+
+=head2 Table cleanup
+
+This script currently implements only the C<L> (i.e. "append a line to the log") command, therefore the log lines are never purged from the table. This approach has an obvious scalability problem.
+
+One solution would be to implement e.g. the "rotate log" command in a way that would calculate some summary values, put them in a "summary table" and then delete the lines used to caluclate those values.
+
+Similar cleanup code could be implemented in an external script and run periodically independently from squid log commands.
+
+=head2 Testing
+
+This script has only been tested in low-volume scenarios (single client, less than 10 req/s). Tests in high volume environments could reveal performance bottlenecks and bugs.
+
+=head1 AUTHOR
+
+Marcello Romani, marcello.romani@libero.it
+Amos Jeffries, amosjeffries@squid-cache.org
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2008 by Marcello Romani
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.8.8 or,
+at your option, any later version of Perl 5 you may have available.
+
+=cut
## Alphabetical list of sub-directories to distribute with Squid:
DIST_SUBDIRS = \
+ DB \
file
SUBDIRS = $(LOG_DAEMON_HELPERS)
i--;
snprintf(from, MAXPATHLEN, "%s.%d", path, i - 1);
snprintf(to, MAXPATHLEN, "%s.%d", path, i);
-#if defined(_SQUID_OS2_) || defined(_SQUID_WIN32_)
+#if _SQUID_OS2_ || _SQUID_WINDOWS_
remove(to);
#endif
rename(from, to);
}
if (rotate_count > 0) {
snprintf(to, MAXPATHLEN, "%s.%d", path, 0);
-#if defined(_SQUID_OS2_) || defined(_SQUID_WIN32_)
+#if _SQUID_OS2_ || _SQUID_WINDOWS_
remove(to);
#endif
rename(path, to);
#include <gssapi/gssapi.h>
#elif HAVE_GSSAPI_H
#include <gssapi.h>
-#endif /* HAVE_GSSAPI_GSSAPI_H */
+#endif
+
+#if !HAVE_HEIMDAL_KERBEROS
#if HAVE_GSSAPI_GSSAPI_KRB5_H
#include <gssapi/gssapi_krb5.h>
-#endif /* HAVE_GSSAPI_GSSAPI_KRB5_H */
+#endif
#if HAVE_GSSAPI_GSSAPI_GENERIC_H
#include <gssapi/gssapi_generic.h>
-#endif /* HAVE_GSSAPI_GSSAPI_GENERIC_H */
+#endif
+#if HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+#endif
+
#ifndef gss_nt_service_name
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
#endif
#include <gssapi/gssapi.h>
#elif HAVE_GSSAPI_H
#include <gssapi.h>
-#endif /* HAVE_GSSAPI_GSSAPI_H */
+#endif
+
+#if !HAVE_HEIMDAL_KERBEROS
#if HAVE_GSSAPI_GSSAPI_KRB5_H
#include <gssapi/gssapi_krb5.h>
-#endif /* HAVE_GSSAPI_GSSAPI_KRB5_H */
+#endif
#if HAVE_GSSAPI_GSSAPI_GENERIC_H
#include <gssapi/gssapi_generic.h>
-#endif /* HAVE_GSSAPI_GSSAPI_GENERIC_H */
+#endif
+#if HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+#endif
+
#ifndef gss_nt_service_name
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
#endif
#else
/* no gcc, no debugging. varargs macros are a gcc extension */
#define SEND2(X,Y) debug("sending '" X "' to squid\n",Y); printf(X "\n",Y);
-#define SEND4(X,Y,Z,W) debug("sending '" X "' to squid\n",Y,Z); printf(X "\n",Y,Z);
+#define SEND4(X,Y,Z,W) debug("sending '" X "' to squid\n",Y,Z,W); printf(X "\n",Y,Z,W);
#endif
const char *authenticate_ntlm_domain = "WORKGROUP";
return credentials;
}
-/* signal handler to be invoked when the authentication operation
- * times out */
+extern "C" void timeout_during_auth(int signum);
+
static char got_timeout = 0;
-static void
+/** signal handler to be invoked when the authentication operation
+ * times out */
+void
timeout_during_auth(int signum)
{
dc_disconnect();
/* represents [start, end) */
-template <class C>
+template <class C, class S = size_t>
class Range
{
C start;
C end;
Range intersection (Range const &) const;
- C size() const;
+ S size() const;
};
-template <class C>
-std::ostream& operator << (std::ostream &os, Range<C> const &aRange)
+template <class C, class S>
+std::ostream& operator << (std::ostream &os, Range<C, S> const &aRange)
{
os << "[" << aRange.start << "," << aRange.end << ")";
return os;
}
-template<class C>
-Range<C>::Range () : start(), end() {}
+template<class C, class S>
+Range<C, S>::Range () : start(), end() {}
-template<class C>
-Range<C>::Range (C start_, C end_) : start(start_), end(end_) {}
+template<class C, class S>
+Range<C, S>::Range (C start_, C end_) : start(start_), end(end_) {}
-template<class C>
-Range<C>
-Range<C>::intersection (Range const &rhs) const
+template<class C, class S>
+Range<C, S>
+Range<C, S>::intersection (Range const &rhs) const
{
- Range<C> result (max(start, rhs.start), min(end, rhs.end));
+ Range<C, S> result (max(start, rhs.start), min(end, rhs.end));
return result;
}
-template<class C>
-C
-Range<C>::size() const
+template<class C, class S>
+S
+Range<C, S>::size() const
{
- return end > start ? end - start : 0;
+ return (S) (end > start ? end - start : 0);
}
#endif /* SQUID_RANGE_H */
#define SQUID_UDP_SO_RCVBUF SQUID_DETECT_UDP_SO_RCVBUF
#endif
-#if HAVE_MEMCPY
-#define xmemcpy(d,s,n) memcpy((d),(s),(n))
-#elif HAVE_BCOPY
-#define xmemcpy(d,s,n) bcopy((s),(d),(n))
-#elif HAVE_MEMMOVE
-#define xmemcpy(d,s,n) memmove((d),(s),(n))
-#endif
-
-#if HAVE_MEMMOVE
-#define xmemmove(d,s,n) memmove((d),(s),(n))
-#elif HAVE_BCOPY
-#define xmemmove(d,s,n) bcopy((s),(d),(n))
-#endif
-
-#if HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#define xisspace(x) isspace((unsigned char)x)
-#define xtoupper(x) toupper((unsigned char)x)
-#define xtolower(x) tolower((unsigned char)x)
-#define xisdigit(x) isdigit((unsigned char)x)
-#define xisascii(x) isascii((unsigned char)x)
-#define xislower(x) islower((unsigned char)x)
-#define xisalpha(x) isalpha((unsigned char)x)
-#define xisprint(x) isprint((unsigned char)x)
-#define xisalnum(x) isalnum((unsigned char)x)
-#define xiscntrl(x) iscntrl((unsigned char)x)
-#define xispunct(x) ispunct((unsigned char)x)
-#define xisupper(x) isupper((unsigned char)x)
-#define xisxdigit(x) isxdigit((unsigned char)x)
-#define xisgraph(x) isgraph((unsigned char)x)
-
#if HAVE_RANDOM
#define squid_random random
#define squid_srandom srandom
#define squid_srandom srand
#endif
-/* gcc doesn't recognize the Windows native 64 bit formatting tags causing
- * the compile fail, so we must disable the check on native Windows.
- */
-
-#if __GNUC__ && !defined(_SQUID_MSWIN_)
-#define PRINTF_FORMAT_ARG1 __attribute__ ((format (printf, 1, 2)))
-#define PRINTF_FORMAT_ARG2 __attribute__ ((format (printf, 2, 3)))
-#define PRINTF_FORMAT_ARG3 __attribute__ ((format (printf, 3, 4)))
-#else
-#define PRINTF_FORMAT_ARG1
-#define PRINTF_FORMAT_ARG2
-#define PRINTF_FORMAT_ARG3
-#endif
-
/*
* Determine if this is a leak check build or standard
*/
/* temp hack: needs to be pre-defined for now. */
#define SQUID_MAXPATHLEN 256
-/*
- * strnstr() is needed. The OS may not provide a working copy.
- */
-#include "strnstr.h"
-
#endif /* SQUID_CONFIG_H */
SQUIDCEXTERN void fatal(const char *message);
SQUIDCEXTERN void fatalf(const char *fmt,...) PRINTF_FORMAT_ARG1;
-SQUIDCEXTERN void fatal_dump(const char *message);
+extern void fatal_dump(const char *message);
-#endif
+#endif /* SQUID_FATAL_H */
(void *v, void *mask, struct squid_radix_node_head * head, struct squid_radix_node nodes[]);
struct squid_radix_node *(*rnh_deladdr) /* remove based on sockaddr */
-
(void *v, void *mask, struct squid_radix_node_head * head);
struct squid_radix_node *(*rnh_delpkt) /* remove based on packet hdr */
-
(void *v, void *mask, struct squid_radix_node_head * head);
struct squid_radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
-
(void *v, struct squid_radix_node_head * head);
struct squid_radix_node *(*rnh_lookup) /* locate based on sockaddr */
(void *v, void *mask, struct squid_radix_node_head * head);
struct squid_radix_node *(*rnh_matchpkt) /* locate based on packet hdr */
-
(void *v, struct squid_radix_node_head * head);
int (*rnh_walktree) /* traverse tree */
-
(struct squid_radix_node_head * head, int (*f) (struct squid_radix_node *, void *), void *w);
struct squid_radix_node rnh_nodes[3]; /* empty tree for common case */
#include "Stack.h"
template <class V>
-
class SplayNode
{
SplayNode<V> const * start() const;
SplayNode<V> const * finish() const;
- SplayNode<V> * remove
- (const Value data, SPLAYCMP * compare);
+ SplayNode<V> * remove(const Value data, SPLAYCMP * compare);
SplayNode<V> * insert(Value data, SPLAYCMP * compare);
typedef SplayNode<void *> splayNode;
template <class V>
-
class SplayConstIterator;
template <class V>
-
class SplayIterator;
template <class V>
-
class Splay
{
template <class FindValue> Value const *find (FindValue const &, int( * compare)(FindValue const &a, Value const &b)) const;
void insert(Value const &, SPLAYCMP *compare);
- void remove
- (Value const &, SPLAYCMP *compare);
+ void remove(Value const &, SPLAYCMP *compare);
void destroy(SPLAYFREE *);
template<class V>
SplayNode<V> *
-SplayNode<V>::remove
-(Value const dataToRemove, SPLAYCMP * compare)
+SplayNode<V>::remove(Value const dataToRemove, SPLAYCMP * compare)
{
if (this == NULL)
return NULL;
template <class V>
void
-Splay<V>::remove
-(Value const &value, SPLAYCMP *compare)
+Splay<V>::remove(Value const &value, SPLAYCMP *compare)
{
assert (find (value, compare));
- head = head->remove
- (value, compare);
+ head = head->remove(value, compare);
--elements;
}
}
template <class V>
-
class SplayConstIterator
{
#ifndef _INC_SQUID_WINDOWS_H
#define _INC_SQUID_WINDOWS_H
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#ifndef ACL
#define ACL WindowsACL
#undef _MSWIN_ACL_WAS_NOT_DEFINED
#endif
-#endif /* _SQUID_WIN32_ */
-
+#endif /* _SQUID_WINDOWS_ */
#endif /* _INC_SQUID_WINDOWS_H */
#ifndef _LIBSSPWIN32_H_
#define _LIBSSPWIN32_H_
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#define SECURITY_WIN32
#define NTLM_PACKAGE_NAME "NTLM"
#define NEGOTIATE_PACKAGE_NAME "Negotiate"
-#ifdef _SQUID_CYGWIN_
+#if _SQUID_CYGWIN_
#include <wchar.h>
#define _T(x) TEXT(x)
#else
extern BOOL Use_Unicode;
extern BOOL NTLM_LocalCall;
-#endif /* _SQUID_WIN32_ */
-
+#endif /* _SQUID_WINDOWS_ */
#endif /* LIBSSPWIN32_H_ */
+++ /dev/null
-#if HAVE_STRNSTR
-
-/* Is strnstr exists and is usable we do so. */
-#define squid_strnstr(a,b,c) strnstr(a,b,c)
-
-#else /* not HAVE_STRNSTR */
-
-/* If its not usable we have our own copy imported from FreeBSD */
-const char * squid_strnstr(const char *s, const char *find, size_t slen);
-
-#endif /* HAVE_STRNSTR*/
#include "SquidNew.h"
#endif
-#if 0 && XMALLOC_STATISTICS
-SQUIDCEXTERN void malloc_statistics(void (*)(int, int, int, void *), void *);
-#endif
-
#if XMALLOC_TRACE
#define xmalloc(size) (xmalloc_func="xmalloc",xmalloc_line=__LINE__,xmalloc_file=__FILE__,xmalloc(size))
#define xfree(ptr) (xmalloc_func="xfree",xmalloc_line=__LINE__,xmalloc_file=__FILE__,xfree(ptr))
rfc3596.c \
$(SNPRINTFSOURCE) \
Splay.cc \
- strnstr.cc \
stub_memaccount.c \
util.c \
xusleep.c \
{
MemImplementingAllocator *find_pool, *prev_pool;
- assert(MemPools::GetInstance().pools != NULL && "Called MemImplementingAllocator::~MemImplementingAllocator, but no pool exists!");
+ /* Abort if the associated pool doesn't exist */
+ assert(MemPools::GetInstance().pools != NULL );
/* Pool clean, remove it from List and free */
for (find_pool = MemPools::GetInstance().pools, prev_pool = NULL; (find_pool && this != find_pool); find_pool = find_pool->next)
prev_pool = find_pool;
- assert(find_pool != NULL && "pool to destroy not found");
+
+ /* make sure that we found the pool to destroy */
+ assert(find_pool != NULL);
if (prev_pool)
prev_pool->next = next;
flushMetersFull();
clean(0);
- assert(meter.inuse.level == 0 && "While trying to destroy pool");
+ assert(meter.inuse.level == 0);
chunk = Chunks;
while ( (fchunk = chunk) != NULL) {
MemPoolMalloc::~MemPoolMalloc()
{
- assert(meter.inuse.level == 0 && "While trying to destroy pool");
+ assert(meter.inuse.level == 0);
clean(0);
}
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
- The file `configure.ac' (or `configure.in') is used to create
+ The file `configure.ac' is used to create
`configure' by a program called `autoconf'. You only need
`configure.ac' if you want to change it or regenerate `configure' using
a newer version of `autoconf'.
* bindings. libtrie itself is written in C++.
*/
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
* For C bindings see Trie.h
*/
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
/* C bindings */
#ifndef __cplusplus
* For C bindings see Trei.h
*/
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
/* C bindings */
#ifndef __cplusplus
#include "Trie.cci"
#endif
-Trie::Trie (TrieCharTransform *aTransform) : head (0) , transform (aTransform)
+Trie::Trie(TrieCharTransform *aTransform) : head(0) , transform(aTransform)
{}
-extern "C" void *TrieCreate ()
+extern "C" void *TrieCreate()
{
return new Trie;
}
-Trie::~Trie ()
+Trie::~Trie()
{
delete head;
delete transform;
}
-extern "C" void TrieDestroy (void *aTrie)
+extern "C" void TrieDestroy(void *aTrie)
{
delete (Trie *)aTrie;
}
-extern "C" void *TrieFind (void *aTrie, char const *aString, size_t theLength)
+extern "C" void *TrieFind(void *aTrie, char const *aString, size_t theLength)
{
- return ((Trie *)aTrie)->find (aString, theLength);
+ return ((Trie *)aTrie)->find(aString, theLength);
}
bool
-
-Trie::add
-(char const *aString, size_t theLength, void *privatedata)
+Trie::add(char const *aString, size_t theLength, void *privatedata)
{
if (!privatedata)
return false;
if (head) {
- if (find (aString, theLength))
+ if (find(aString, theLength))
return false;
- return head->add
- (aString, theLength, privatedata, transform);
+ return head->add(aString, theLength, privatedata, transform);
}
head = new TrieNode;
- return head->add
- (aString, theLength, privatedata, transform);
+ return head->add(aString, theLength, privatedata, transform);
}
-extern "C" int TrieAdd (void *aTrie, char const *aString, size_t theLength, void *privatedata)
+extern "C" int TrieAdd(void *aTrie, char const *aString, size_t theLength, void *privatedata)
{
- return ((Trie *)aTrie)->add
- (aString, theLength, privatedata);
+ return ((Trie *)aTrie)->add(aString, theLength, privatedata);
}
#include <unistd.h>
#endif
-TrieNode::TrieNode () : _privateData (NULL)
+TrieNode::TrieNode() : _privateData(NULL)
{
for (int i = 0; i < 256; ++i)
internal[i] = NULL;
}
-TrieNode::~TrieNode ()
+TrieNode::~TrieNode()
{
for (int i = 0; i < 256; ++i)
delete internal[i];
/* as for find */
bool
-
-TrieNode::add
-(char const *aString, size_t theLength, void *privatedata, TrieCharTransform *transform)
+TrieNode::add(char const *aString, size_t theLength, void *privatedata, TrieCharTransform *transform)
{
/* We trust that privatedata and existant keys have already been checked */
if (theLength) {
- int index = transform ? (*transform) (*aString): *aString;
+ int index = transform ? (*transform)(*aString): *aString;
if (!internal[index])
internal[index] = new TrieNode;
- return internal[index]->add
- (aString + 1, theLength - 1, privatedata, transform);
+ return internal[index]->add(aString + 1, theLength - 1, privatedata, transform);
} else {
/* terminal node */
MDString("abc");
MDString("message digest");
MDString("abcdefghijklmnopqrstuvwxyz");
- MDString
- ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
- MDString
- ("1234567890123456789012345678901234567890\
-1234567890123456789012345678901234567890");
+ MDString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ MDString("1234567890123456789012345678901234567890"
+ "1234567890123456789012345678901234567890");
return 0;
}
#if !USE_XPROF_STATS
-#define PROF_start(ARGS) ((void)0)
-#define PROF_stop(ARGS) ((void)0)
+#define PROF_start(probename) ((void)0)
+#define PROF_stop(probename) ((void)0)
#else /* USE_XPROF_STATS */
extern void xprof_stop(xprof_type type, const char *timer);
extern void xprof_event(void *data);
-#define PROF_start(type) xprof_start(XPROF_##type, #type)
-#define PROF_stop(type) xprof_stop(XPROF_##type, #type)
+#define PROF_start(probename) xprof_start(XPROF_##probename, #probename)
+#define PROF_stop(probename) xprof_stop(XPROF_##probename, #probename)
#endif /* USE_XPROF_STATS */
#if USE_XPROF_STATS
+/*
+ * Ensure that any changes here are synchronised with SQUID_CHECK_FUNCTIONAL_CPU_PROFILER
+ */
+
#if !_SQUID_SOLARIS_
typedef int64_t hrtime_t;
#endif
#else
/* This CPU is unsupported. Short-circuit, no profiling here */
-#define get_tick() 0
-#undef USE_XPROF_STATS
-#define USE_XPROF_STATS 0
+// #error for configure tests to prevent library construction
+#error This CPU is unsupported. No profiling available here.
#endif
#endif /* USE_XPROF_STATS */
#ifndef _PROFILER_XPROF_TYPE_H_
#define _PROFILER_XPROF_TYPE_H_
-
+/* AUTO-GENERATED FILE */
#if USE_XPROF_STATS
-
-// TODO: auto-generate this list from a scan of the source code.
-
-// This list MUST be kept in sync with the PROF_start()/PROF_stop() macros
-// used throughout the rest of the sources.
-
typedef enum {
XPROF_PROF_UNACCOUNTED,
+ XPROF_HttpHeaderClean,
+ XPROF_HttpHeaderParse,
+ XPROF_HttpHeader_getCc,
+ XPROF_HttpMsg_httpMsgParseStep,
+ XPROF_HttpParserParseReqLine,
+ XPROF_HttpStateData_processReplyBody,
+ XPROF_HttpStateData_processReplyHeader,
+ XPROF_HttpStateData_readReply,
+ XPROF_InvokeHandlers,
+ XPROF_MemBuf_append,
+ XPROF_MemBuf_consume,
+ XPROF_MemBuf_grow,
+ XPROF_MemObject_write,
XPROF_PROF_OVERHEAD,
- XPROF_hash_lookup,
- XPROF_splay_splay,
- XPROF_xmalloc,
- XPROF_malloc,
- XPROF_free,
- XPROF_free_const,
- XPROF_xrealloc,
- XPROF_realloc,
- XPROF_xcalloc,
- XPROF_calloc,
- XPROF_xstrdup,
- XPROF_xstrndup,
- XPROF_xstrncpy,
- XPROF_xcountws,
- XPROF_socket,
- XPROF_read,
- XPROF_write,
- XPROF_send,
- XPROF_recv,
- XPROF_sendto,
- XPROF_recvfrom,
- XPROF_accept,
- XPROF_connect,
- XPROF_memPoolChunkNew,
- XPROF_memPoolAlloc,
- XPROF_memPoolFree,
- XPROF_memPoolClean,
- XPROF_aclMatchAclList,
+ XPROF_SignalEngine_checkEvents,
+ XPROF_StoreEntry_write,
+ XPROF_StringAllocAndFill,
+ XPROF_StringAppend,
+ XPROF_StringClean,
+ XPROF_StringInitBuf,
+ XPROF_StringReset,
XPROF_aclCheckFast,
- XPROF_comm_open,
- XPROF_comm_connect_addr,
- XPROF_comm_accept,
- XPROF_comm_close,
- XPROF_comm_udp_sendto,
+ XPROF_aclMatchAclList,
+ XPROF_calloc,
+ XPROF_clientSocketRecipient,
XPROF_commHandleWrite,
+ XPROF_comm_accept,
XPROF_comm_check_incoming,
- XPROF_comm_poll_prep_pfds,
- XPROF_comm_poll_normal,
+ XPROF_comm_close,
+ XPROF_comm_connect_addr,
XPROF_comm_handle_ready_fd,
+ XPROF_comm_open,
+ XPROF_comm_poll_normal,
+ XPROF_comm_poll_prep_pfds,
XPROF_comm_read_handler,
+ XPROF_comm_udp_sendto,
XPROF_comm_write_handler,
- XPROF_storeGet,
- XPROF_storeMaintainSwapSpace,
- XPROF_storeRelease,
- XPROF_diskHandleWrite,
XPROF_diskHandleRead,
+ XPROF_diskHandleWrite,
+ XPROF_esiExpressionEval,
+ XPROF_esiParsing,
+ XPROF_esiProcessing,
+ XPROF_eventRun,
+ XPROF_file_close,
XPROF_file_open,
XPROF_file_read,
XPROF_file_write,
- XPROF_file_close,
- XPROF_esiExpressionEval,
- XPROF_esiProcessing,
- XPROF_esiParsing,
+ XPROF_free,
+ XPROF_free_const,
+ XPROF_hash_lookup,
+ XPROF_headersEnd,
+ XPROF_httpRequestFree,
+ XPROF_httpStart,
+ XPROF_malloc,
+ XPROF_mem_hdr_write,
+ XPROF_parseHttpRequest,
+ XPROF_read,
+ XPROF_realloc,
+ XPROF_recv,
+ XPROF_send,
XPROF_storeClient_kickReads,
- XPROF_eventRun,
XPROF_storeDirCallback,
- XPROF_comm_calliocallback,
- XPROF_CommReadCallbackData_callCallback,
- XPROF_CommAcceptCallbackData_callCallback,
- XPROF_CommWriteCallbackData_callCallback,
- XPROF_CommFillCallbackData_callCallback,
- XPROF_HttpStateData_readReply,
- XPROF_HttpStateData_processReplyBody,
- XPROF_StoreEntry_write,
+ XPROF_storeGet,
XPROF_storeGetMemSpace,
- XPROF_MemObject_write,
+ XPROF_storeMaintainSwapSpace,
+ XPROF_storeRelease,
XPROF_storeWriteComplete,
- XPROF_mem_hdr_write,
- XPROF_headersEnd,
- XPROF_parseHttpRequest,
- XPROF_HttpStateData_processReplyHeader,
- XPROF_MemBuf_consume,
- XPROF_MemBuf_append,
- XPROF_MemBuf_grow,
- XPROF_InvokeHandlers,
- XPROF_HttpMsg_httpMsgParseStep,
- XPROF_EventDispatcher_dispatch,
- XPROF_SignalEngine_checkEvents,
- XPROF_Temp1,
- XPROF_Temp2,
- XPROF_Temp3,
- XPROF_clientSocketRecipient,
- XPROF_httpStart,
- XPROF_HttpParserParseReqLine,
- XPROF_httpRequestFree,
- XPROF_HttpHeaderParse,
- XPROF_HttpHeaderClean,
- XPROF_StringInitBuf,
- XPROF_StringAllocAndFill,
- XPROF_StringClean,
- XPROF_StringReset,
- XPROF_StringAppend,
- XPROF_HttpHeader_findEntry,
- XPROF_HttpHeader_getCc,
- XPROF_HttpHeader_getRange,
- XPROF_checkTimeouts,
- XPROF_CommSelect,
+ XPROF_write,
+ XPROF_xcalloc,
+ XPROF_xcountws,
+ XPROF_xmalloc,
+ XPROF_xrealloc,
XPROF_LAST
} xprof_type;
-
-#endif /* USE_XPROF_STATS */
-#endif /* _PROFILING_H_ */
+#endif
+#endif
t = mktime(tm);
if (t != -1) {
time_t dst = 0;
-#if defined (_TIMEZONE)
-#elif defined (_timezone)
-#elif defined(_SQUID_AIX_)
-#elif defined(_SQUID_CYGWIN_)
-#elif defined(_SQUID_MSWIN_)
-#elif defined(_SQUID_SGI_)
-#else
- extern long timezone;
+#if !(defined(_TIMEZONE) || defined(_timezone) || _SQUID_AIX_ || _SQUID_WINDOWS_ || _SQUID_SGI_)
+ extern long timezone;
#endif
/*
* The following assumes a fixed DST offset of 1 hour,
*/
if (tm->tm_isdst > 0)
dst = -3600;
-#if defined ( _timezone) || defined(_SQUID_WIN32_)
+#if defined(_timezone) || _SQUID_WINDOWS_
t -= (_timezone + dst);
#else
t -= (timezone + dst);
return buf;
}
-const char *
-mkhttpdlogtime(const time_t * t)
-{
- static char buf[128];
-
- struct tm *gmt = gmtime(t);
-
-#if !USE_GMT
- int gmt_min, gmt_hour, gmt_yday, day_offset;
- size_t len;
- struct tm *lt;
- int min_offset;
-
- /* localtime & gmtime may use the same static data */
- gmt_min = gmt->tm_min;
- gmt_hour = gmt->tm_hour;
- gmt_yday = gmt->tm_yday;
-
- lt = localtime(t);
-
- day_offset = lt->tm_yday - gmt_yday;
- /* wrap round on end of year */
- if (day_offset > 1)
- day_offset = -1;
- else if (day_offset < -1)
- day_offset = 1;
-
- min_offset = day_offset * 1440 + (lt->tm_hour - gmt_hour) * 60
- + (lt->tm_min - gmt_min);
-
- len = strftime(buf, 127 - 5, "%d/%b/%Y:%H:%M:%S ", lt);
- snprintf(buf + len, 128 - len, "%+03d%02d",
- (min_offset / 60) % 24,
- min_offset % 60);
-#else /* USE_GMT */
- buf[0] = '\0';
- strftime(buf, 127, "%d/%b/%Y:%H:%M:%S -000", gmt);
-#endif /* USE_GMT */
-
- return buf;
-}
-
#if 0
int
main()
/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- SMB Byte handling
- Copyright (C) Andrew Tridgell 1992-1995
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * SMB Byte handling
+ * Copyright (C) Andrew Tridgell 1992-1995
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
/*
- This file implements macros for machine independent short and
- int manipulation
-*/
+ * This file implements macros for machine independent short and
+ * int manipulation
+ */
#undef CAREFUL_ALIGNMENT
/* we know that the 386 can handle misalignment and has the "right"
- byteorder */
+ * byteorder */
#ifdef __i386__
#define CAREFUL_ALIGNMENT 0
#endif
#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val)))
#else
/* this handles things for architectures like the 386 that can handle
- alignment errors */
+ * alignment errors */
/*
- WARNING: This section is dependent on the length of int16 and int32
- being correct
-*/
+ * WARNING: This section is dependent on the length of int16 and int32
+ * being correct
+ */
#define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos)))
#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
#define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos)))
/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
-
- Version 1.0
- RFCNB Common Structures etc Defines
-
- Copyright (C) Richard Sharpe 1996
-
-*/
+ *
+ * Version 1.0
+ * RFCNB Common Structures etc Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifndef _RFCNB_RFCNB_COMMON_H
#define _RFCNB_RFCNB_COMMON_H
typedef struct RFCNB_Pkt {
- char * data; /* The data in this portion */
+ char *data; /* The data in this portion */
int len;
struct RFCNB_Pkt *next;
#ifdef __cplusplus
}
+
#endif
-#endif /* _RFCNB_RFCNB_COMMON_H */
+#endif /* _RFCNB_RFCNB_COMMON_H */
/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
-
- Version 1.0
- RFCNB Error Response Defines
-
- Copyright (C) Richard Sharpe 1996
-
-*/
+ *
+ * Version 1.0
+ * RFCNB Error Response Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifndef _RFCNB_ERROR_H_
#define _RFCNB_ERROR_H_
/* Error responses */
-#define RFCNBE_Bad -1 /* Bad response */
+#define RFCNBE_Bad -1 /* Bad response */
#define RFCNBE_OK 0
- /* these should follow the spec ... is there one ?*/
+ /* these should follow the spec ... is there one ? */
-#define RFCNBE_NoSpace 1 /* Could not allocate space for a struct */
-#define RFCNBE_BadName 2 /* Could not translate a name */
-#define RFCNBE_BadRead 3 /* Read sys call failed */
-#define RFCNBE_BadWrite 4 /* Write Sys call failed */
-#define RFCNBE_ProtErr 5 /* Protocol Error */
-#define RFCNBE_ConGone 6 /* Connection dropped */
-#define RFCNBE_BadHandle 7 /* Handle passed was bad */
-#define RFCNBE_BadSocket 8 /* Problems creating socket */
-#define RFCNBE_ConnectFailed 9 /* Connect failed */
-#define RFCNBE_CallRejNLOCN 10 /* Call rejected, not listening on CN */
-#define RFCNBE_CallRejNLFCN 11 /* Call rejected, not listening for CN */
-#define RFCNBE_CallRejCNNP 12 /* Call rejected, called name not present */
-#define RFCNBE_CallRejInfRes 13/* Call rejetced, name ok, no resources */
-#define RFCNBE_CallRejUnSpec 14/* Call rejected, unspecified error */
-#define RFCNBE_BadParam 15/* Bad parameters passed ... */
-#define RFCNBE_Timeout 16/* IO Timed out */
+#define RFCNBE_NoSpace 1 /* Could not allocate space for a struct */
+#define RFCNBE_BadName 2 /* Could not translate a name */
+#define RFCNBE_BadRead 3 /* Read sys call failed */
+#define RFCNBE_BadWrite 4 /* Write Sys call failed */
+#define RFCNBE_ProtErr 5 /* Protocol Error */
+#define RFCNBE_ConGone 6 /* Connection dropped */
+#define RFCNBE_BadHandle 7 /* Handle passed was bad */
+#define RFCNBE_BadSocket 8 /* Problems creating socket */
+#define RFCNBE_ConnectFailed 9 /* Connect failed */
+#define RFCNBE_CallRejNLOCN 10 /* Call rejected, not listening on CN */
+#define RFCNBE_CallRejNLFCN 11 /* Call rejected, not listening for CN */
+#define RFCNBE_CallRejCNNP 12 /* Call rejected, called name not present */
+#define RFCNBE_CallRejInfRes 13 /* Call rejetced, name ok, no resources */
+#define RFCNBE_CallRejUnSpec 14 /* Call rejected, unspecified error */
+#define RFCNBE_BadParam 15 /* Bad parameters passed ... */
+#define RFCNBE_Timeout 16 /* IO Timed out */
/* Text strings for the error responses */
#ifdef __cplusplus
}
+
#endif
-#endif /* _RFCNB_ERROR_H_ */
+#endif /* _RFCNB_ERROR_H_ */
#include "config.h"
/* UNIX RFCNB (RFC1001/RFC1002) NEtBIOS implementation
-
- Version 1.0
- RFCNB IO Routines ...
-
- Copyright (C) Richard Sharpe 1996
-
-*/
+ *
+ * Version 1.0
+ * RFCNB IO Routines ...
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#include "rfcnb/std-includes.h"
#include "rfcnb/rfcnb-priv.h"
#include <string.h>
#endif
-int RFCNB_Timeout = 0; /* Timeout in seconds ... */
+int RFCNB_Timeout = 0; /* Timeout in seconds ... */
-int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len);
+static int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len);
#ifdef NOT_USED
-void rfcnb_alarm(int sig)
-
+void
+rfcnb_alarm(int sig)
{
fprintf(stderr, "IO Timed out ...\n");
}
-/* Set timeout value and setup signal handling */
-
-int RFCNB_Set_Timeout(int seconds)
+#endif /* NOT_USED */
+#ifdef NOT_USED
+/* Set timeout value and setup signal handling */
+int
+RFCNB_Set_Timeout(int seconds)
{
/* If we are on a Bezerkeley system, use sigvec, else sigaction */
RFCNB_Timeout = seconds;
- if (RFCNB_Timeout > 0) { /* Set up handler to ignore but not restart */
+ if (RFCNB_Timeout > 0) { /* Set up handler to ignore but not restart */
#ifndef SA_RESTART
- invec.sv_handler = (void (*)())rfcnb_alarm;
+ invec.sv_handler = (void (*)()) rfcnb_alarm;
invec.sv_mask = 0;
invec.sv_flags = SV_INTERRUPT;
- if (sigvec(SIGALRM, &invec, &outvec) < 0)
- return(-1);
-#else
- inact.sa_handler = (void (*)())rfcnb_alarm;
+ if (sigvec(SIGALRM, &invec, &outvec) < 0)
+ return (-1);
+#else /* !SA_RESTART */
+ inact.sa_handler = (void (*)()) rfcnb_alarm;
#ifdef Solaris
/* Solaris seems to have an array of vectors ... */
inact.sa_mask.__sigbits[0] = 0;
inact.sa_mask.__sigbits[1] = 0;
inact.sa_mask.__sigbits[2] = 0;
inact.sa_mask.__sigbits[3] = 0;
-#else
- inact.sa_mask = (sigset_t)0;
-#endif
- inact.sa_flags = 0; /* Don't restart */
+#else /* !Solaris */
+ inact.sa_mask = (sigset_t) 0;
+#endif /* Solaris */
+ inact.sa_flags = 0; /* Don't restart */
if (sigaction(SIGALRM, &inact, &outact) < 0)
- return(-1);
+ return (-1);
-#endif
+#endif /* !SA_RESTART */
}
-
-#else /* ADAPTED SQUID CODE */
+#else /* !ORIGINAL_SAMBA_CODE ADAPTED SQUID CODE */
#if HAVE_SIGACTION
struct sigaction inact, outact;
#else
if (sigaction(SIGALRM, &inact, &outact) < 0)
return (-1);
-#else
+#else /* !HAVE_SIGACTION */
invec.sv_handler = (void (*)()) rfcnb_alarm;
invec.sv_mask = 0;
invec.sv_flags = SV_INTERRUPT;
if (sigvec(SIGALRM, &invec, &outvec) < 0)
return (-1);
-#endif
-
-#endif
- return(0);
-
+#endif /* !HAVE_SIGACTION */
+ }
+#endif /* !ORIGINAL_SAMBA_CODE ADAPTED SQUID CODE */
+ return (0);
}
-#endif
+#endif /* NOT_USED */
/* Discard the rest of an incoming packet as we do not have space for it
- in the buffer we allocated or were passed ... */
-
-int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
+ * in the buffer we allocated or were passed ... */
+int
+RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
{
- char temp[100]; /* Read into here */
+ char temp[100]; /* Read into here */
int rest, this_read, bytes_read;
/* len is the amount we should read */
while (rest > 0) {
- this_read = (rest > sizeof(temp)?sizeof(temp):rest);
+ this_read = (rest > sizeof(temp) ? sizeof(temp) : rest);
- bytes_read = read(con -> fd, temp, this_read);
+ bytes_read = read(con->fd, temp, this_read);
- if (bytes_read <= 0) { /* Error so return */
+ if (bytes_read <= 0) { /* Error so return */
if (bytes_read < 0)
RFCNB_errno = RFCNBE_BadRead;
RFCNB_errno = RFCNBE_ConGone;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
rest = rest - bytes_read;
}
- return(0);
+ return (0);
}
/* Send an RFCNB packet to the connection.
-
- We just send each of the blocks linked together ...
-
- If we can, try to send it as one iovec ...
-
-*/
-
-int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
-
+ *
+ * We just send each of the blocks linked together ...
+ *
+ * If we can, try to send it as one iovec ...
+ *
+ */
+
+int
+RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
{
int len_sent, tot_sent, this_len;
struct RFCNB_Pkt *pkt_ptr;
char *this_data;
int i;
- struct iovec io_list[10]; /* We should never have more */
- /* If we do, this will blow up ...*/
+ struct iovec io_list[10]; /* We should never have more */
+ /* If we do, this will blow up ... */
/* Try to send the data ... We only send as many bytes as len claims */
/* We should try to stuff it into an IOVEC and send as one write */
pkt_ptr = pkt;
- len_sent = tot_sent = 0; /* Nothing sent so far */
+ len_sent = tot_sent = 0; /* Nothing sent so far */
i = 0;
- while ((pkt_ptr != NULL) & (i < 10)) { /* Watch that magic number! */
+ while ((pkt_ptr != NULL) & (i < 10)) { /* Watch that magic number! */
- this_len = pkt_ptr -> len;
- this_data = pkt_ptr -> data;
+ this_len = pkt_ptr->len;
+ this_data = pkt_ptr->data;
if ((tot_sent + this_len) > len)
- this_len = len - tot_sent; /* Adjust so we don't send too much */
+ this_len = len - tot_sent; /* Adjust so we don't send too much */
/* Now plug into the iovec ... */
tot_sent += this_len;
- if (tot_sent == len) break; /* Let's not send too much */
+ if (tot_sent == len)
+ break; /* Let's not send too much */
- pkt_ptr = pkt_ptr -> next;
+ pkt_ptr = pkt_ptr->next;
}
if (RFCNB_Timeout > 0)
alarm(RFCNB_Timeout);
- if ((len_sent = writev(con -> fd, io_list, i)) < 0) { /* An error */
+ if ((len_sent = writev(con->fd, io_list, i)) < 0) { /* An error */
- con -> errn = errno;
- if (errno == EINTR) /* We were interrupted ... */
+ con->errn = errno;
+ if (errno == EINTR) /* We were interrupted ... */
RFCNB_errno = RFCNBE_Timeout;
else
RFCNB_errno = RFCNBE_BadWrite;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
- if (len_sent < tot_sent) { /* Less than we wanted */
- if (errno == EINTR) /* We were interrupted */
+ if (len_sent < tot_sent) { /* Less than we wanted */
+ if (errno == EINTR) /* We were interrupted */
RFCNB_errno = RFCNBE_Timeout;
else
RFCNB_errno = RFCNBE_BadWrite;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
if (RFCNB_Timeout > 0)
- alarm(0); /* Reset that sucker */
+ alarm(0); /* Reset that sucker */
#ifdef RFCNB_DEBUG
fprintf(stderr, "Len sent = %i ...\n", len_sent);
- RFCNB_Print_Pkt(stderr, "sent", pkt, len_sent); /* Print what send ... */
+ RFCNB_Print_Pkt(stderr, "sent", pkt, len_sent); /* Print what send ... */
#endif
- return(len_sent);
+ return (len_sent);
}
/* Read an RFCNB packet off the connection.
+ *
+ * We read the first 4 bytes, that tells us the length, then read the
+ * rest. We should implement a timeout, but we don't just yet
+ *
+ */
- We read the first 4 bytes, that tells us the length, then read the
- rest. We should implement a timeout, but we don't just yet
-
-*/
-
-
-int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
+int
+RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
{
int read_len, pkt_len;
- char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */
+ char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */
struct RFCNB_Pkt *pkt_frag;
int more, this_time, offset, frag_len, this_len;
BOOL seen_keep_alive = TRUE;
/* Read that header straight into the buffer */
- if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */
+ if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */
#ifdef RFCNB_DEBUG
fprintf(stderr, "Trying to read less than a packet:");
perror("");
#endif
RFCNB_errno = RFCNBE_BadParam;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
/* We discard keep alives here ... */
if (RFCNB_Timeout > 0)
while (seen_keep_alive) {
- if ((read_len = read(con -> fd, hdr, sizeof(hdr))) < 0) { /* Problems */
+ if ((read_len = read(con->fd, hdr, sizeof(hdr))) < 0) { /* Problems */
#ifdef RFCNB_DEBUG
fprintf(stderr, "Reading the packet, we got:");
perror("");
else
RFCNB_errno = RFCNBE_BadRead;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
/* Now we check out what we got */
- if (read_len == 0) { /* Connection closed, send back eof? */
+ if (read_len == 0) { /* Connection closed, send back eof? */
#ifdef RFCNB_DEBUG
fprintf(stderr, "Connection closed reading\n");
else
RFCNB_errno = RFCNBE_ConGone;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
if (RFCNB_Pkt_Type(hdr) == RFCNB_SESSION_KEEP_ALIVE) {
#ifdef RFCNB_DEBUG
/* What if we got less than or equal to a hdr size in bytes? */
- if (read_len < sizeof(hdr)) { /* We got a small packet */
+ if (read_len < sizeof(hdr)) { /* We got a small packet */
/* Now we need to copy the hdr portion we got into the supplied packet */
- memcpy(pkt -> data, hdr, read_len); /*Copy data */
+ memcpy(pkt->data, hdr, read_len); /*Copy data */
#ifdef RFCNB_DEBUG
RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len);
#endif
- return(read_len);
+ return (read_len);
}
-
/* Now, if we got at least a hdr size, alloc space for rest, if we need it */
pkt_len = RFCNB_Pkt_Len(hdr);
/* Now copy in the hdr */
- memcpy(pkt -> data, hdr, sizeof(hdr));
+ memcpy(pkt->data, hdr, sizeof(hdr));
/* Get the rest of the packet ... first figure out how big our buf is? */
/* And make sure that we handle the fragments properly ... Sure should */
/* use an iovec ... */
- if (len < pkt_len) /* Only get as much as we have space for */
+ if (len < pkt_len) /* Only get as much as we have space for */
more = len - RFCNB_Pkt_Hdr_Len;
else
more = pkt_len;
/* We read for each fragment ... */
- if (pkt -> len == read_len) { /* If this frag was exact size */
- pkt_frag = pkt -> next; /* Stick next lot in next frag */
- offset = 0; /* then we start at 0 in next */
+ if (pkt->len == read_len) { /* If this frag was exact size */
+ pkt_frag = pkt->next; /* Stick next lot in next frag */
+ offset = 0; /* then we start at 0 in next */
} else {
- pkt_frag = pkt; /* Otherwise use rest of this frag */
- offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */
+ pkt_frag = pkt; /* Otherwise use rest of this frag */
+ offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */
}
- frag_len = pkt_frag -> len;
+ frag_len = pkt_frag->len;
- if (more <= frag_len) /* If len left to get less than frag space */
+ if (more <= frag_len) /* If len left to get less than frag space */
this_len = more; /* Get the rest ... */
else
this_len = frag_len - offset;
while (more > 0) {
- if ((this_time = read(con -> fd, (pkt_frag -> data) + offset, this_len)) <= 0) { /* Problems */
+ if ((this_time = read(con->fd, (pkt_frag->data) + offset, this_len)) <= 0) { /* Problems */
if (errno == EINTR) {
}
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
#ifdef RFCNB_DEBUG
fprintf(stderr, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len,
this_time, this_len, more);
#endif
- read_len = read_len + this_time; /* How much have we read ... */
+ read_len = read_len + this_time; /* How much have we read ... */
/* Now set up the next part */
- if (pkt_frag -> next == NULL) break; /* That's it here */
+ if (pkt_frag->next == NULL)
+ break; /* That's it here */
- pkt_frag = pkt_frag -> next;
- this_len = pkt_frag -> len;
+ pkt_frag = pkt_frag->next;
+ this_len = pkt_frag->len;
offset = 0;
more = more - this_time;
}
#ifdef RFCNB_DEBUG
- fprintf(stderr,"Pkt Len = %i, read_len = %i\n", pkt_len, read_len);
+ fprintf(stderr, "Pkt Len = %i, read_len = %i\n", pkt_len, read_len);
RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len + sizeof(hdr));
#endif
- if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */
+ if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */
- return(RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len));
+ return (RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len));
}
-
if (RFCNB_Timeout > 0)
- alarm(0); /* Reset that sucker */
+ alarm(0); /* Reset that sucker */
- return(read_len + sizeof(RFCNB_Hdr));
+ return (read_len + sizeof(RFCNB_Hdr));
}
/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
-
- Version 1.0
- RFCNB IO Routines Defines
-
- Copyright (C) Richard Sharpe 1996
-
-*/
+ *
+ * Version 1.0
+ * RFCNB IO Routines Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len);
/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
-
- Version 1.0
- RFCNB Defines
-
- Copyright (C) Richard Sharpe 1996
-
-*/
+ *
+ * Version 1.0
+ * RFCNB Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifndef _RFCNB_RFCNB_PRIV_H
#define _RFCNB_RFCNB_PRIV_H
/* Structures */
-typedef struct redirect_addr * redirect_ptr;
+typedef struct redirect_addr *redirect_ptr;
struct redirect_addr {
typedef struct RFCNB_Con {
int fd; /* File descripter for TCP/IP connection */
- int errn; /* last error */
- int timeout; /* How many milli-secs before IO times out */
- int redirects; /* How many times we were redirected */
- struct redirect_addr *redirect_list; /* First is first address */
+ int errn; /* last error */
+ int timeout; /* How many milli-secs before IO times out */
+ int redirects; /* How many times we were redirected */
+ struct redirect_addr *redirect_list; /* First is first address */
struct redirect_addr *last_addr;
} RFCNB_Con;
-typedef char RFCNB_Hdr[4]; /* The header is 4 bytes long with */
+typedef char RFCNB_Hdr[4]; /* The header is 4 bytes long with */
/* char[0] as the type, char[1] the */
/* flags, and char[2..3] the length */
/* Macros to extract things from the header. These are for portability
- between architecture types where we are worried about byte order */
+ * between architecture types where we are worried about byte order */
#define RFCNB_Pkt_Hdr_Len 4
#define RFCNB_Pkt_Sess_Len 72
#define RFCNB_Pkt_Nack_Len 5
#define RFCNB_Pkt_Type_Offset 0
#define RFCNB_Pkt_Flags_Offset 1
-#define RFCNB_Pkt_Len_Offset 2 /* Length is 2 bytes plus a flag bit */
+#define RFCNB_Pkt_Len_Offset 2 /* Length is 2 bytes plus a flag bit */
#define RFCNB_Pkt_N1Len_Offset 4
#define RFCNB_Pkt_Called_Offset 5
#define RFCNB_Pkt_N2Len_Offset 38
#define RFCNB_Pkt_Port_Offset 8
/* The next macro isolates the length of a packet, including the bit in the
- flags */
+ * flags */
#define RFCNB_Pkt_Len(p) (PVAL((p), 3) | (PVAL((p), 2) << 8) | \
((PVAL((p), RFCNB_Pkt_Flags_Offset) & 0x01) << 16))
#define RFCNB_Put_Pkt_Len(p, v) ((p)[1] = (((v) >> 16) & 1)); \
- ((p)[2] = (((v) >> 8) & 0xFF)); \
- ((p)[3] = ((v) & 0xFF));
+ ((p)[2] = (((v) >> 8) & 0xFF)); \
+ ((p)[3] = ((v) & 0xFF));
#define RFCNB_Pkt_Type(p) (CVAL((p), RFCNB_Pkt_Type_Offset))
-/*typedef struct RFCNB_Hdr {
-
- unsigned char type;
- unsigned char flags;
- int16 len;
-
- } RFCNB_Hdr;
+#if UNUSED_CODE
+typedef struct RFCNB_Hdr {
+ unsigned char type;
+ unsigned char flags;
+ int16 len;
+} RFCNB_Hdr;
typedef struct RFCNB_Sess_Pkt {
unsigned char type;
char called_name[33];
unsigned char n2_len;
char calling_name[33];
- } RFCNB_Sess_Pkt;
+} RFCNB_Sess_Pkt;
typedef struct RFCNB_Nack_Pkt {
-
- struct RFCNB_Hdr hdr;
- unsigned char error;
-
- } RFCNB_Nack_Pkt;
+ struct RFCNB_Hdr hdr;
+ unsigned char error;
+} RFCNB_Nack_Pkt;
typedef struct RFCNB_Retarget_Pkt {
-
- struct RFCNB_Hdr hdr;
- int dest_ip;
- unsigned char port;
-
- } RFCNB_Redir_Pkt; */
+ struct RFCNB_Hdr hdr;
+ int dest_ip;
+ unsigned char port;
+} RFCNB_Redir_Pkt;
+#endif /* UNUSED_CODE */
/* Static variables */
#ifndef RFCNB_ERRNO
extern int RFCNB_errno;
-extern int RFCNB_saved_errno; /* Save this from point of error */
+extern int RFCNB_saved_errno; /* Save this from point of error */
#endif
#endif /* _RFCNB_RFCNB_PRIV_H */
#include "config.h"
/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
-
- Version 1.0
- RFCNB Utility Routines ...
-
- Copyright (C) Richard Sharpe 1996
-
-*/
+ *
+ * Version 1.0
+ * RFCNB Utility Routines ...
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#include "rfcnb/rfcnb.h"
#include "rfcnb/std-includes.h"
#include <string.h>
#endif
-extern void (*Prot_Print_Routine)(); /* Pointer to protocol print routine */
-
const char *RFCNB_Error_Strings[] = {
-
"RFCNBE_OK: Routine completed successfully.",
"RFCNBE_NoSpace: No space available for a malloc call.",
"RFCNBE_BadName: NetBIOS name could not be translated to IP address.",
"RFCNBE_CallRejUnSpec: Call rejected. Unspecified error.",
"RFCNBE_BadParam: Bad parameters passed to a routine.",
"RFCNBE_Timeout: IO Operation timed out ..."
-
};
/* Convert name and pad to 16 chars as needed */
/* Name 1 is a C string with null termination, name 2 may not be */
/* If SysName is true, then put a <00> on end, else space> */
-
-void RFCNB_CvtPad_Name(char *name1, char *name2)
-
+void
+RFCNB_CvtPad_Name(char *name1, char *name2)
{
char c, c1, c2;
int i, len;
if (i >= len) {
c1 = 'C';
- c2 = 'A'; /* CA is a space */
+ c2 = 'A'; /* CA is a space */
} else {
c = name1[i];
- c1 = (char)((int)c/16 + (int)'A');
- c2 = (char)((int)c%16 + (int)'A');
+ c1 = (char) ((int) c / 16 + (int) 'A');
+ c2 = (char) ((int) c % 16 + (int) 'A');
}
- name2[i*2] = c1;
- name2[i*2+1] = c2;
+ name2[i * 2] = c1;
+ name2[i * 2 + 1] = c2;
}
- name2[32] = 0; /* Put in the nll ...*/
+ name2[32] = 0; /* Put in the nll ... */
}
/* Converts an Ascii NB Name (16 chars) to an RFCNB Name (32 chars)
- Uses the encoding in RFC1001. Each nibble of byte is added to 'A'
- to produce the next byte in the name.
-
- This routine assumes that AName is 16 bytes long and that NBName has
- space for 32 chars, so be careful ...
-
-*/
-
-void RFCNB_AName_To_NBName(char *AName, char *NBName)
-
+ * Uses the encoding in RFC1001. Each nibble of byte is added to 'A'
+ * to produce the next byte in the name.
+ *
+ * This routine assumes that AName is 16 bytes long and that NBName has
+ * space for 32 chars, so be careful ...
+ */
+void
+RFCNB_AName_To_NBName(char *AName, char *NBName)
{
char c, c1, c2;
int i;
- for (i=0; i < 16; i++) {
+ for (i = 0; i < 16; i++) {
c = AName[i];
- c1 = (char)((c >> 4) + 'A');
- c2 = (char)((c & 0xF) + 'A');
+ c1 = (char) ((c >> 4) + 'A');
+ c2 = (char) ((c & 0xF) + 'A');
- NBName[i*2] = c1;
- NBName[i*2+1] = c2;
+ NBName[i * 2] = c1;
+ NBName[i * 2 + 1] = c2;
}
- NBName[32] = 0; /* Put in a null */
-
+ NBName[32] = 0; /* Put in a null */
}
/* Do the reverse of the above ... */
-
-void RFCNB_NBName_To_AName(char *NBName, char *AName)
-
+void
+RFCNB_NBName_To_AName(char *NBName, char *AName)
{
char c, c1, c2;
int i;
- for (i=0; i < 16; i++) {
+ for (i = 0; i < 16; i++) {
- c1 = NBName[i*2];
- c2 = NBName[i*2+1];
+ c1 = NBName[i * 2];
+ c2 = NBName[i * 2 + 1];
- c = (char)(((int)c1 - (int)'A') * 16 + ((int)c2 - (int)'A'));
+ c = (char) (((int) c1 - (int) 'A') * 16 + ((int) c2 - (int) 'A'));
AName[i] = c;
}
- AName[i] = 0; /* Put a null on the end ... */
-
+ AName[i] = 0; /* Put a null on the end ... */
}
/* Print a string of bytes in HEX etc */
-
-void RFCNB_Print_Hex(FILE *fd, struct RFCNB_Pkt *pkt, int Offset, int Len)
-
+void
+RFCNB_Print_Hex(FILE * fd, struct RFCNB_Pkt *pkt, int Offset, int Len)
{
char c1, c2, outbuf1[33];
unsigned char c;
while (pkt_ptr != NULL) {
for (i = 0;
- i < ((Len > (pkt_ptr -> len)?pkt_ptr -> len:Len) - Offset);
+ i < ((Len > (pkt_ptr->len) ? pkt_ptr->len : Len) - Offset);
i++) {
- c = pkt_ptr -> data[i + Offset];
+ c = pkt_ptr->data[i + Offset];
c1 = Hex_List[c >> 4];
c2 = Hex_List[c & 0xF];
outbuf1[j++] = c1;
outbuf1[j++] = c2;
- if (j == 32) { /* Print and reset */
+ if (j == 32) { /* Print and reset */
outbuf1[j] = 0;
fprintf(fd, " %s\n", outbuf1);
j = 0;
}
-
}
Offset = 0;
- Len = Len - pkt_ptr -> len; /* Reduce amount by this much */
- pkt_ptr = pkt_ptr -> next;
+ Len = Len - pkt_ptr->len; /* Reduce amount by this much */
+ pkt_ptr = pkt_ptr->next;
}
fprintf(fd, " %s\n", outbuf1);
}
-
fprintf(fd, "\n");
-
}
/* Get a packet of size n */
-
-struct RFCNB_Pkt *RFCNB_Alloc_Pkt(int n)
-
-{
+struct RFCNB_Pkt *
+RFCNB_Alloc_Pkt(int n) {
RFCNB_Pkt *pkt;
- if ((pkt = (struct RFCNB_Pkt *)malloc(sizeof(struct RFCNB_Pkt))) == NULL) {
+ if ((pkt = (struct RFCNB_Pkt *) malloc(sizeof(struct RFCNB_Pkt))) == NULL) {
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
- return(NULL);
+ return (NULL);
}
+ pkt->next = NULL;
+ pkt->len = n;
- pkt -> next = NULL;
- pkt -> len = n;
-
- if (n == 0) return(pkt);
+ if (n == 0)
+ return (pkt);
- if ((pkt -> data = (char *)malloc(n)) == NULL) {
+ if ((pkt->data = (char *) malloc(n)) == NULL) {
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
free(pkt);
- return(NULL);
+ return (NULL);
}
-
- return(pkt);
-
+ return (pkt);
}
/* Free up a packet */
-
-void RFCNB_Free_Pkt(struct RFCNB_Pkt *pkt)
-
+void
+RFCNB_Free_Pkt(struct RFCNB_Pkt *pkt)
{
struct RFCNB_Pkt *pkt_next;
char *data_ptr;
while (pkt != NULL) {
- pkt_next = pkt -> next;
+ pkt_next = pkt->next;
- data_ptr = pkt -> data;
+ data_ptr = pkt->data;
if (data_ptr != NULL)
free(data_ptr);
pkt = pkt_next;
}
-
}
/* Print an RFCNB packet */
-
-void RFCNB_Print_Pkt(FILE *fd, char *dirn, struct RFCNB_Pkt *pkt, int len)
-
+void
+RFCNB_Print_Pkt(FILE * fd, char *dirn, struct RFCNB_Pkt *pkt, int len)
{
char lname[17];
fprintf(fd, "RFCNB Pkt %s:", dirn);
- switch (RFCNB_Pkt_Type(pkt -> data)) {
+ switch (RFCNB_Pkt_Type(pkt->data)) {
case RFCNB_SESSION_MESSAGE:
- fprintf(fd, "SESSION MESSAGE: Length = %i\n", RFCNB_Pkt_Len(pkt -> data));
+ fprintf(fd, "SESSION MESSAGE: Length = %i\n", RFCNB_Pkt_Len(pkt->data));
RFCNB_Print_Hex(fd, pkt, RFCNB_Pkt_Hdr_Len,
#ifdef RFCNB_PRINT_DATA
- RFCNB_Pkt_Len(pkt -> data) - RFCNB_Pkt_Hdr_Len);
+ RFCNB_Pkt_Len(pkt->data) - RFCNB_Pkt_Hdr_Len);
#else
40);
#endif
- if (Prot_Print_Routine != 0) { /* Print the rest of the packet */
+ if (Prot_Print_Routine) { /* Print the rest of the packet */
Prot_Print_Routine(fd, strcmp(dirn, "sent"), pkt, RFCNB_Pkt_Hdr_Len,
- RFCNB_Pkt_Len(pkt -> data) - RFCNB_Pkt_Hdr_Len);
+ RFCNB_Pkt_Len(pkt->data) - RFCNB_Pkt_Hdr_Len);
}
-
break;
case RFCNB_SESSION_REQUEST:
fprintf(fd, "SESSION REQUEST: Length = %i\n",
- RFCNB_Pkt_Len(pkt -> data));
- RFCNB_NBName_To_AName((char *)(pkt -> data + RFCNB_Pkt_Called_Offset), lname);
+ RFCNB_Pkt_Len(pkt->data));
+ RFCNB_NBName_To_AName((char *) (pkt->data + RFCNB_Pkt_Called_Offset), lname);
fprintf(fd, " Called Name: %s\n", lname);
- RFCNB_NBName_To_AName((char *)(pkt -> data + RFCNB_Pkt_Calling_Offset), lname);
+ RFCNB_NBName_To_AName((char *) (pkt->data + RFCNB_Pkt_Calling_Offset), lname);
fprintf(fd, " Calling Name: %s\n", lname);
break;
case RFCNB_SESSION_ACK:
fprintf(fd, "RFCNB SESSION ACK: Length = %i\n",
- RFCNB_Pkt_Len(pkt -> data));
+ RFCNB_Pkt_Len(pkt->data));
break;
case RFCNB_SESSION_REJ:
fprintf(fd, "RFCNB SESSION REJECT: Length = %i\n",
- RFCNB_Pkt_Len(pkt -> data));
+ RFCNB_Pkt_Len(pkt->data));
- if (RFCNB_Pkt_Len(pkt -> data) < 1) {
+ if (RFCNB_Pkt_Len(pkt->data) < 1) {
fprintf(fd, " Protocol Error, short Reject packet!\n");
} else {
- fprintf(fd, " Error = %x\n", CVAL(pkt -> data, RFCNB_Pkt_Error_Offset));
+ fprintf(fd, " Error = %x\n", CVAL(pkt->data, RFCNB_Pkt_Error_Offset));
}
break;
case RFCNB_SESSION_RETARGET:
fprintf(fd, "RFCNB SESSION RETARGET: Length = %i\n",
- RFCNB_Pkt_Len(pkt -> data));
+ RFCNB_Pkt_Len(pkt->data));
/* Print out the IP address etc and the port? */
case RFCNB_SESSION_KEEP_ALIVE:
fprintf(fd, "RFCNB SESSION KEEP ALIVE: Length = %i\n",
- RFCNB_Pkt_Len(pkt -> data));
+ RFCNB_Pkt_Len(pkt->data));
break;
default:
break;
}
-
}
/* Resolve a name into an address */
-
-int RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP)
-
+int
+RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP)
{
- int addr; /* Assumes IP4, 32 bit network addresses */
+ int addr; /* Assumes IP4, 32 bit network addresses */
struct hostent *hp;
/* Use inet_addr to try to convert the address */
- if ((addr = inet_addr(host)) == INADDR_NONE) { /* Oh well, a good try :-) */
+ if ((addr = inet_addr(host)) == INADDR_NONE) { /* Oh well, a good try :-) */
/* Now try a name look up with gethostbyname */
- if ((hp = gethostbyname(host)) == NULL) { /* Not in DNS */
+ if ((hp = gethostbyname(host)) == NULL) { /* Not in DNS */
/* Try NetBIOS name lookup, how the hell do we do that? */
- RFCNB_errno = RFCNBE_BadName; /* Is this right? */
+ RFCNB_errno = RFCNBE_BadName; /* Is this right? */
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
- } else { /* We got a name */
+ } else { /* We got a name */
- memcpy((void *)Dest_IP, (void *)hp -> h_addr_list[0], sizeof(struct in_addr));
+ memcpy((void *) Dest_IP, (void *) hp->h_addr_list[0], sizeof(struct in_addr));
}
- } else { /* It was an IP address */
+ } else { /* It was an IP address */
- memcpy((void *)Dest_IP, (void *)&addr, sizeof(struct in_addr));
+ memcpy((void *) Dest_IP, (void *) &addr, sizeof(struct in_addr));
}
return 0;
-
}
/* Disconnect the TCP connection to the server */
-
-int RFCNB_Close(int socket)
-
+int
+RFCNB_Close(int socket)
{
close(socket);
/* If we want to do error recovery, here is where we put it */
return 0;
-
}
/* Connect to the server specified in the IP address.
- Not sure how to handle socket options etc. */
-
-int RFCNB_IP_Connect(struct in_addr Dest_IP, int port)
-
+ * Not sure how to handle socket options etc. */
+int
+RFCNB_IP_Connect(struct in_addr Dest_IP, int port)
{
struct sockaddr_in Socket;
int fd;
/* Create a socket */
- if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { /* Handle the error */
+ if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { /* Handle the error */
RFCNB_errno = RFCNBE_BadSocket;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
- memset((char *)&Socket, 0, sizeof(Socket));
- memcpy((char *)&Socket.sin_addr, (char *)&Dest_IP, sizeof(Dest_IP));
+ memset((char *) &Socket, 0, sizeof(Socket));
+ memcpy((char *) &Socket.sin_addr, (char *) &Dest_IP, sizeof(Dest_IP));
Socket.sin_port = htons(port);
Socket.sin_family = PF_INET;
/* Now connect to the destination */
- if (connect(fd, (struct sockaddr *)&Socket, sizeof(Socket)) < 0) { /* Error */
+ if (connect(fd, (struct sockaddr *) &Socket, sizeof(Socket)) < 0) { /* Error */
close(fd);
RFCNB_errno = RFCNBE_ConnectFailed;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
- return(fd);
-
+ return (fd);
}
/* handle the details of establishing the RFCNB session with remote
- end
-
-*/
-
-int RFCNB_Session_Req(struct RFCNB_Con *con,
- char *Called_Name,
- char *Calling_Name,
- BOOL *redirect,
- struct in_addr *Dest_IP,
- int * port)
-
+ * end
+ */
+int
+RFCNB_Session_Req(struct RFCNB_Con *con,
+ char *Called_Name,
+ char *Calling_Name,
+ BOOL * redirect,
+ struct in_addr *Dest_IP,
+ int *port)
{
char *sess_pkt;
pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Sess_Len);
if (pkt == NULL) {
-
- return(RFCNBE_Bad); /* Leave the error that RFCNB_Alloc_Pkt gives) */
-
+ return (RFCNBE_Bad); /* Leave the error that RFCNB_Alloc_Pkt gives) */
}
+ sess_pkt = pkt->data; /* Get pointer to packet proper */
- sess_pkt = pkt -> data; /* Get pointer to packet proper */
-
- sess_pkt[RFCNB_Pkt_Type_Offset] = RFCNB_SESSION_REQUEST;
- RFCNB_Put_Pkt_Len(sess_pkt, RFCNB_Pkt_Sess_Len-RFCNB_Pkt_Hdr_Len);
+ sess_pkt[RFCNB_Pkt_Type_Offset] = RFCNB_SESSION_REQUEST;
+ RFCNB_Put_Pkt_Len(sess_pkt, RFCNB_Pkt_Sess_Len - RFCNB_Pkt_Hdr_Len);
sess_pkt[RFCNB_Pkt_N1Len_Offset] = 32;
sess_pkt[RFCNB_Pkt_N2Len_Offset] = 32;
/* Now send the packet */
#ifdef RFCNB_DEBUG
-
fprintf(stderr, "Sending packet: ");
-
#endif
if ((len = RFCNB_Put_Pkt(con, pkt, RFCNB_Pkt_Sess_Len)) < 0) {
- return(RFCNBE_Bad); /* Should be able to write that lot ... */
+ return (RFCNBE_Bad); /* Should be able to write that lot ... */
}
-
#ifdef RFCNB_DEBUG
-
fprintf(stderr, "Getting packet.\n");
-
#endif
res_pkt.data = resp;
- res_pkt.len = sizeof(resp);
+ res_pkt.len = sizeof(resp);
res_pkt.next = NULL;
if ((len = RFCNB_Get_Pkt(con, &res_pkt, sizeof(resp))) < 0) {
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
/* Now analyze the packet ... */
switch (RFCNB_Pkt_Type(resp)) {
- case RFCNB_SESSION_REJ: /* Didnt like us ... too bad */
+ case RFCNB_SESSION_REJ: /* Didnt like us ... too bad */
/* Why did we get rejected ? */
- switch (CVAL(resp,RFCNB_Pkt_Error_Offset)) {
+ switch (CVAL(resp, RFCNB_Pkt_Error_Offset)) {
case 0x80:
RFCNB_errno = RFCNBE_CallRejNLOCN;
break;
}
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
break;
- case RFCNB_SESSION_ACK: /* Got what we wanted ... */
+ case RFCNB_SESSION_ACK: /* Got what we wanted ... */
- return(0);
+ return (0);
break;
- case RFCNB_SESSION_RETARGET: /* Go elsewhere */
+ case RFCNB_SESSION_RETARGET: /* Go elsewhere */
*redirect = TRUE; /* Copy port and ip addr */
memcpy(Dest_IP, (resp + RFCNB_Pkt_IP_Offset), sizeof(struct in_addr));
*port = SVAL(resp, RFCNB_Pkt_Port_Offset);
- return(0);
+ return (0);
break;
- default: /* A protocol error */
+ default: /* A protocol error */
RFCNB_errno = RFCNBE_ProtErr;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
break;
}
}
-
-
-
-
-
-
-
-
-
/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
-
- Version 1.0
- RFCNB Utility Defines
-
- Copyright (C) Richard Sharpe 1996
-
-*/
+ *
+ * Version 1.0
+ * RFCNB Utility Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
void RFCNB_CvtPad_Name(char *name1, char *name2);
void RFCNB_NBName_To_AName(char *NBName, char *AName);
-void RFCNB_Print_Hex(FILE *fd, struct RFCNB_Pkt *pkt, int Offset, int Len);
+void RFCNB_Print_Hex(FILE * fd, struct RFCNB_Pkt *pkt, int Offset, int Len);
-void RFCNB_Print_Pkt(FILE *fd, char *dirn, struct RFCNB_Pkt *pkt, int len);
+void RFCNB_Print_Pkt(FILE * fd, char *dirn, struct RFCNB_Pkt *pkt, int len);
int RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP);
int RFCNB_Session_Req(struct RFCNB_Con *con,
char *Called_Name,
char *Calling_Name,
- BOOL *redirect,
+ BOOL * redirect,
struct in_addr *Dest_IP,
- int * port);
+ int *port);
+typedef void RFCNB_Prot_Print_Routine(FILE * fd, int dir, struct RFCNB_Pkt *pkt, int header, int payload);
+extern RFCNB_Prot_Print_Routine *Prot_Print_Routine;
/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
-
- Version 1.0
- RFCNB Defines
-
- Copyright (C) Richard Sharpe 1996
-
-*/
+ *
+ * Version 1.0
+ * RFCNB Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifndef _RFCNB_RFCNB_H
#define _RFCNB_RFCNB_H
int RFCNB_Hangup(struct RFCNB_Con *con_Handle);
- void *RFCNB_Listen();
+ void *RFCNB_Listen(void);
void RFCNB_Get_Error(char *buffer, int buf_len);
#ifdef __cplusplus
}
+
#endif
-#endif /* _RFCNB_RFCNB_H */
+#endif /* _RFCNB_RFCNB_H */
#include "config.h"
/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
-
- Version 1.0
- Session Routines ...
-
- Copyright (C) Richard Sharpe 1996
-
-*/
+ *
+ * Version 1.0
+ * Session Routines ...
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
int RFCNB_errno = 0;
int RFCNB_saved_errno = 0;
int RFCNB_Stats[RFCNB_MAX_STATS];
-void (*Prot_Print_Routine)() = NULL; /* Pointer to print routine */
-
-int RFCNB_Get_Last_Errno(void);
-int RFCNB_Get_Error_Msg(int code, char *msg_buf, int len);
-void RFCNB_Register_Print_Routine(void (*fn)());
+RFCNB_Prot_Print_Routine *Prot_Print_Routine = NULL; /* Pointer to protocol print routine */
/* Set up a session with a remote name. We are passed Called_Name as a
- string which we convert to a NetBIOS name, ie space terminated, up to
- 16 characters only if we need to. If Called_Address is not empty, then
- we use it to connect to the remote end, but put in Called_Name ... Called
- Address can be a DNS based name, or a TCP/IP address ...
-*/
-
-void *RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address,
- int port)
-
+ * string which we convert to a NetBIOS name, ie space terminated, up to
+ * 16 characters only if we need to. If Called_Address is not empty, then
+ * we use it to connect to the remote end, but put in Called_Name ... Called
+ * Address can be a DNS based name, or a TCP/IP address ...
+ */
+
+void *
+RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address, int port)
{
struct RFCNB_Con *con;
struct in_addr Dest_IP;
/* Now, we really should look up the port in /etc/services ... */
- if (port == 0) port = RFCNB_Default_Port;
+ if (port == 0)
+ port = RFCNB_Default_Port;
/* Create a connection structure first */
- if ((con = (struct RFCNB_Con *)malloc(sizeof(struct RFCNB_Con))) == NULL) { /* Error in size */
+ if ((con = (struct RFCNB_Con *) malloc(sizeof(struct RFCNB_Con))) == NULL) { /* Error in size */
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
- return(NULL);
+ return (NULL);
}
-
- con -> fd = -0; /* no descriptor yet */
- con -> errn = 0; /* no error yet */
- con -> timeout = 0; /* no timeout */
- con -> redirects = 0;
+ con->fd = -0; /* no descriptor yet */
+ con->errn = 0; /* no error yet */
+ con->timeout = 0; /* no timeout */
+ con->redirects = 0;
/* Resolve that name into an IP address */
Service_Address = Called_Name;
- if (strcmp(Called_Address, "") != 0) { /* If the Called Address = "" */
+ if (strcmp(Called_Address, "") != 0) { /* If the Called Address = "" */
Service_Address = Called_Address;
}
-
- if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) { /* Error */
+ if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) { /* Error */
/* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
free(con);
- return(NULL);
+ return (NULL);
}
-
/* Now connect to the remote end */
- redirect = TRUE; /* Fudge this one so we go once through */
+ redirect = TRUE; /* Fudge this one so we go once through */
- while (redirect) { /* Connect and get session info etc */
+ while (redirect) { /* Connect and get session info etc */
- redirect = FALSE; /* Assume all OK */
+ redirect = FALSE; /* Assume all OK */
/* Build the redirect info. First one is first addr called */
/* And tack it onto the list of addresses we called */
- if ((redir_addr = (struct redirect_addr *)malloc(sizeof(struct redirect_addr))) == NULL) { /* Could not get space */
+ if ((redir_addr = (struct redirect_addr *) malloc(sizeof(struct redirect_addr))) == NULL) { /* Could not get space */
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
free(con);
- return(NULL);
+ return (NULL);
}
+ memcpy((char *) &(redir_addr->ip_addr), (char *) &Dest_IP, sizeof(Dest_IP));
+ redir_addr->port = port;
+ redir_addr->next = NULL;
- memcpy((char *)&(redir_addr -> ip_addr), (char *)&Dest_IP, sizeof(Dest_IP));
- redir_addr -> port = port;
- redir_addr -> next = NULL;
+ if (con->redirect_list == NULL) { /* Stick on head */
- if (con -> redirect_list == NULL) { /* Stick on head */
-
- con -> redirect_list = con -> last_addr = redir_addr;
+ con->redirect_list = con->last_addr = redir_addr;
} else {
- con -> last_addr -> next = redir_addr;
- con -> last_addr = redir_addr;
+ con->last_addr->next = redir_addr;
+ con->last_addr = redir_addr;
}
/* Now, make that connection */
- if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) { /* Error */
+ if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) { /* Error */
/* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
free(con);
- return(NULL);
+ return (NULL);
}
-
- con -> fd = Client;
+ con->fd = Client;
/* Now send and handle the RFCNB session request */
/* If we get a redirect, we will comeback with redirect true
- and a new IP address in DEST_IP */
+ * and a new IP address in DEST_IP */
if ((errno = RFCNB_Session_Req(con,
Called_Name,
/* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
- RFCNB_Close(con->fd); /* Close it */
+ RFCNB_Close(con->fd); /* Close it */
free(con);
- return(NULL);
+ return (NULL);
}
-
if (redirect) {
/* We have to close the connection, and then try again */
- (con -> redirects)++;
+ (con->redirects)++;
- RFCNB_Close(con -> fd); /* Close it */
+ RFCNB_Close(con->fd); /* Close it */
}
}
- return(con);
-
+ return (con);
}
/* We send a packet to the other end ... for the moment, we treat the
- data as a series of pointers to blocks of data ... we should check the
- length ... */
-
-int RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
-
+ * data as a series of pointers to blocks of data ... we should check the
+ * length ... */
+int
+RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
{
struct RFCNB_Pkt *pkt;
char *hdr;
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
+ pkt->next = udata; /* The user data we want to send */
- pkt -> next = udata; /* The user data we want to send */
-
- hdr = pkt -> data;
+ hdr = pkt->data;
/* Following crap is for portability across multiple UNIX machines */
- *(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE;
+ *(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE;
RFCNB_Put_Pkt_Len(hdr, Length);
#ifdef RFCNB_DEBUG
/* No need to change RFCNB_errno as it was done by put_pkt ... */
- return(RFCNBE_Bad); /* Should be able to write that lot ... */
+ return (RFCNBE_Bad); /* Should be able to write that lot ... */
}
-
/* Now we have sent that lot, let's get rid of the RFCNB Header and return */
- pkt -> next = NULL;
+ pkt->next = NULL;
RFCNB_Free_Pkt(pkt);
- return(len);
-
+ return (len);
}
/* We pick up a message from the internet ... We have to worry about
- non-message packets ... */
-
-int RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
-
+ * non-message packets ... */
+int
+RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
{
struct RFCNB_Pkt *pkt;
// struct RFCNB_Hdr *hdr;
RFCNB_errno = RFCNBE_BadHandle;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
/* Now get a packet from below. We allocate a header first */
/* Plug in the header and send the data */
RFCNB_errno = RFCNBE_NoSpace;
RFCNB_saved_errno = errno;
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
- pkt -> next = Data; /* Plug in the data portion */
+ pkt->next = Data; /* Plug in the data portion */
if ((ret_len = RFCNB_Get_Pkt(con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
fprintf(stderr, "Bad packet return in RFCNB_Recv... \n");
#endif
- return(RFCNBE_Bad);
+ return (RFCNBE_Bad);
}
-
/* We should check that we go a message and not a keep alive */
- pkt -> next = NULL;
+ pkt->next = NULL;
RFCNB_Free_Pkt(pkt);
- return(ret_len);
-
+ return (ret_len);
}
/* We just disconnect from the other end, as there is nothing in the RFCNB */
/* protocol that specifies any exchange as far as I can see */
-
-int RFCNB_Hangup(struct RFCNB_Con *con_Handle)
-
+int
+RFCNB_Hangup(struct RFCNB_Con *con_Handle)
{
if (con_Handle != NULL) {
- RFCNB_Close(con_Handle -> fd); /* Could this fail? */
+ RFCNB_Close(con_Handle->fd); /* Could this fail? */
free(con_Handle);
}
-
return 0;
-
-
}
/* Set TCP_NODELAY on the socket */
-
-int RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, BOOL yn)
-
+int
+RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, BOOL yn)
{
- return(setsockopt(con_Handle -> fd, IPPROTO_TCP, TCP_NODELAY,
- (char *)&yn, sizeof(yn)));
-
+ return (setsockopt(con_Handle->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &yn, sizeof(yn)));
}
#if NOT_IMPLEMENTED
-
/* Listen for a connection on a port???, when */
/* the connection comes in, we return with the connection */
-
-void *RFCNB_Listen()
-
+void *
+RFCNB_Listen()
{
-
}
+
#endif
/* Pick up the last error response as a string, hmmm, this routine should */
/* have been different ... */
-
-void RFCNB_Get_Error(char *buffer, int buf_len)
-
+void
+RFCNB_Get_Error(char *buffer, int buf_len)
{
if (RFCNB_saved_errno <= 0) {
- snprintf(buffer, (buf_len-1) ,"%s", RFCNB_Error_Strings[RFCNB_errno]);
+ snprintf(buffer, (buf_len - 1), "%s", RFCNB_Error_Strings[RFCNB_errno]);
} else {
- snprintf(buffer, (buf_len-1), "%s\n\terrno:%s", RFCNB_Error_Strings[RFCNB_errno],
+ snprintf(buffer, (buf_len - 1), "%s\n\terrno:%s", RFCNB_Error_Strings[RFCNB_errno],
strerror(RFCNB_saved_errno));
}
-
}
/* Pick up the last error response and returns as a code */
-
-int RFCNB_Get_Last_Error()
-
-{
-
- return(RFCNB_errno);
-
-}
-
-/* Pick up saved errno as well */
-
-int RFCNB_Get_Last_Errno()
-
+int
+RFCNB_Get_Last_Error()
{
-
- return(RFCNB_saved_errno);
-
-}
-
-/* Pick up the last error response and return in string ... */
-
-int RFCNB_Get_Error_Msg(int code, char *msg_buf, int len)
-
-{
-
- return (strncpy(msg_buf, RFCNB_Error_Strings[abs(code)], len) != NULL);
-
-}
-
-/* Register a higher level protocol print routine */
-
-void RFCNB_Register_Print_Routine(void (*fn)())
-
-{
-
- Prot_Print_Routine = fn;
-
+ return (RFCNB_errno);
}
/* RFCNB Standard includes ... */
/*
-
- RFCNB Standard Includes
-
- Copyright (C) 1996, Richard Sharpe
-*/
+ *
+ * RFCNB Standard Includes
+ *
+ * Copyright (C) 1996, Richard Sharpe
+ */
/* One day we will conditionalize these on OS types ... */
/*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifndef _RFCNB_STD_INCLUDES_H
#define _RFCNB_STD_INCLUDES_H
#include "smblib/smblib-priv.h"
#define uchar unsigned char
-extern int DEBUGLEVEL;
#include "rfcnb/byteorder.h"
-1
};
+#if UNDEFINED
char *SMB_DOSTimToStr(int DOS_time);
char *SMB_AtrToStr(int attribs, BOOL verbose);
int SMB_Get_Tree_MBS(SMB_Tree_Handle tree);
int SMB_Get_Max_Buf_Siz(SMB_Handle_Type Con_Handle);
int SMB_Get_Protocol_IDX(SMB_Handle_Type Con_Handle);
+#endif /* UNDEFINED */
int SMB_Get_Protocol(SMB_Handle_Type Con_Handle);
int SMB_Figure_Protocol(const char *dialects[], int prot_index);
int SMB_TreeDisconnect(SMB_Tree_Handle Tree_Handle, BOOL discard);
/* Convert a DOS Date_Time to a local host type date time for printing */
+#if UNDEFINED
char *SMB_DOSTimToStr(int DOS_time)
{
}
}
+#endif /* UNDEFINED */
/* Pick up the protocol from the connection structure */
NULL
};
-int SMB_Term(void);
-int SMBlib_Set_Sock_NoDelay(SMB_Handle_Type Con_Handle, BOOL yn);
/* Initialize the SMBlib package */
}
-int SMB_Term()
-
-{
-
-#ifdef SMBLIB_INSTRUMENT
-
- SMBlib_Instrument_Term(); /* Clean up and print results */
-
-#endif
-
- return 0;
-
-}
-
/* SMB_Create: Create a connection structure and return for later use */
/* We have other helper routines to set variables */
}
-int SMBlib_Set_Sock_NoDelay(SMB_Handle_Type Con_Handle, BOOL yn)
-
-{
-
-
- if (RFCNB_Set_Sock_NoDelay(Con_Handle -> Trans_Connect, yn) < 0) {
-
-#ifdef DEBUG
-#endif
-
- fprintf(stderr, "Setting no-delay on TCP socket failed ...\n");
-
- }
-
- return(0);
-
-}
-
/* SMB_Connect_Server: Connect to a server, but don't negotiate protocol */
/* or anything else ... */
exit 1
fi
RELEASE=`echo $VERSION | cut -d. -f1,2 | cut -d- -f1`
-ed -s configure.in <<EOS
+ed -s configure.ac <<EOS
g/${VERSION}-BZR/ s//${VERSION}/
w
EOS
rm -f ${tag}.out
bzr export ${tmpdir} ${BZRROOT}/${module}/${branchpath} || exit 1
-if [ ! -f ${tmpdir}/configure ] && [ -f ${tmpdir}/configure.in ]; then
+if [ ! -f ${tmpdir}/configure ] && [ -f ${tmpdir}/configure.ac ]; then
sh -c "cd ${tmpdir} && ./bootstrap.sh"
fi
if [ ! -f ${tmpdir}/configure ]; then
cd ${tmpdir}
eval `grep "^ *PACKAGE_VERSION=" configure | sed -e 's/-BZR//' | sed -e 's/PACKAGE_//'`
eval `grep "^ *PACKAGE_TARNAME=" configure | sed -e 's/_TARNAME//'`
-ed -s configure.in <<EOS
+ed -s configure.ac <<EOS
g/${VERSION}-[A-Z]*/ s//${VERSION}-${date}/
w
EOS
done
}
+# Build XPROF types file from current sources
+echo "#ifndef _PROFILER_XPROF_TYPE_H_" >${ROOT}/lib/profiler/list
+echo "#define _PROFILER_XPROF_TYPE_H_" >>${ROOT}/lib/profiler/list
+echo "/* AUTO-GENERATED FILE */" >>${ROOT}/lib/profiler/list
+echo "#if USE_XPROF_STATS" >>${ROOT}/lib/profiler/list
+echo "typedef enum {" >>${ROOT}/lib/profiler/list
+echo "XPROF_PROF_UNACCOUNTED," >>${ROOT}/lib/profiler/list
+grep -R -h "PROF_start.*" ./* | grep -v probename | sed -e 's/ //g; s/PROF_start(/XPROF_/; s/);/,/' | sort -u >>${ROOT}/lib/profiler/list
+echo " XPROF_LAST } xprof_type;" >>${ROOT}/lib/profiler/list
+echo "#endif" >>${ROOT}/lib/profiler/list
+echo "#endif" >>${ROOT}/lib/profiler/list
+mv ${ROOT}/lib/profiler/list ${ROOT}/lib/profiler/xprof_type.h
+
+# Run formating
echo "" >${ROOT}/doc/debug-sections.tmp
srcformat || exit 1
sort -u <${ROOT}/doc/debug-sections.tmp | sort -n >${ROOT}/doc/debug-sections.txt
my (@chained);
my $in_options = 0;
-sub start_option($)
+sub start_option($$)
{
- my ($name) = @_;
+ my ($name, $type) = @_;
if (!$in_options) {
print $index "<ul>\n";
$in_options = 1;
}
+ return if $type eq "obsolete";
print $index ' <li><a href="' . htmlescape(section_link($name)) . '" name="toc_' . htmlescape($name) . '">' . htmlescape($name) . "</a></li>\n";
}
sub end_options()
$data->{'name'} = $name;
$data->{'aliases'} = \@aliases;
- start_option($name);
print "DEBUG: new option: $name\n" if $verbose;
} elsif ($_ =~ /^COMMENT: (.*)$/) {
$data->{"comment"} = $1;
} elsif ($_ =~ /^TYPE: (.*)$/) {
$data->{"type"} = $1;
+ start_option($data->{"name"}, $data->{"type"});
} elsif ($_ =~ /^DEFAULT: (.*)$/) {
if ($1 eq "none") {
$data->{"default"} = "$1";
##
AM_CFLAGS = $(SQUID_CFLAGS)
AM_CXXFLAGS = $(SQUID_CXXFLAGS)
-noinst_LIBRARIES = libsnmp.a
-libsnmp_a_SOURCES = asn1.c parse.c snmp_vars.c \
+noinst_LIBRARIES = libsnmplib.a
+libsnmplib_a_SOURCES = asn1.c parse.c snmp_vars.c \
coexistance.c snmp_api.c snmp_error.c \
mib.c snmp_api_error.c \
snmp_msg.c \
snmp_set_api_error(SNMPERR_ASN_DECODE);
return (NULL);
}
- xmemcpy((char *) string, (char *) bufp, (int) asn_length);
+ memcpy((char *) string, (char *) bufp, (int) asn_length);
*strlength = (int) asn_length;
*datalength -= (int) asn_length + (bufp - data);
return (bufp + asn_length);
snmp_set_api_error(SNMPERR_ASN_DECODE);
return (NULL);
}
- xmemcpy((char *) data, (char *) string, strlength);
+ memcpy((char *) data, (char *) string, strlength);
*datalength -= strlength;
return (data + strlength);
}
return (NULL);
}
*length = (u_int) 0;
- xmemcpy((char *) (length), (char *) data + 1, (int) lengthbyte);
+ memcpy((char *) (length), (char *) data + 1, (int) lengthbyte);
*length = ntohl(*length);
*length >>= (8 * ((sizeof *length) - lengthbyte));
return (data + lengthbyte + 1);
snmp_set_api_error(SNMPERR_ASN_DECODE);
return (NULL);
}
- xmemcpy((char *) data, (char *) buf, asnlength);
+ memcpy((char *) data, (char *) buf, asnlength);
*datalength -= asnlength;
return (data + asnlength);
}
snmp_set_api_error(SNMPERR_ASN_DECODE);
return (NULL);
}
- xmemcpy((char *) string, (char *) bufp, (int) asn_length);
+ memcpy((char *) string, (char *) bufp, (int) asn_length);
*strlength = (int) asn_length;
*datalength -= (int) asn_length + (bufp - data);
return (bufp + asn_length);
snmp_set_api_error(SNMPERR_ASN_ENCODE);
return (NULL);
}
- xmemcpy((char *) data, (char *) string, strlength);
+ memcpy((char *) data, (char *) string, strlength);
*datalength -= strlength;
return (data + strlength);
}
snmp_set_api_error(SNMPERR_OS_ERR);
return (NULL);
}
- xmemcpy((char *) Dest, (char *) Src, sizeof(struct snmp_pdu));
+ memcpy((char *) Dest, (char *) Src, sizeof(struct snmp_pdu));
#if DEBUG_PDU
snmplib_debug(8, "PDU %x: Created %x\n", (unsigned int) Src, (unsigned int) Dest);
snmp_set_api_error(SNMPERR_OS_ERR);
return (NULL);
}
- xmemcpy((char *) PDU->enterprise, (char *) objid,
- PDU->enterprise_length * sizeof(oid));
+ memcpy((char *) PDU->enterprise, (char *) objid,
+ PDU->enterprise_length * sizeof(oid));
/* Agent-addr */
four = 4;
/* Only copy a name if it was specified. */
if (Name)
- xmemcpy((char *) New->name, (char *) Name, Len * sizeof(oid));
+ memcpy((char *) New->name, (char *) Name, Len * sizeof(oid));
return (New);
}
sizeof(struct variable_list));
#endif
- xmemcpy((char *) Dest, (char *) Src, sizeof(struct variable_list));
+ memcpy((char *) Dest, (char *) Src, sizeof(struct variable_list));
if (Src->name != NULL) {
Dest->name = (oid *) xmalloc(Src->name_length * sizeof(oid));
#if DEBUG_VARS
printf("VARS: Copying name OID. (Size %d)\n", Src->name_length);
#endif
- xmemcpy((char *) Dest->name, (char *) Src->name,
- Src->name_length * sizeof(oid));
+ memcpy((char *) Dest->name, (char *) Src->name,
+ Src->name_length * sizeof(oid));
}
/* CISCO Catalyst 2900 returns NULL strings as data of length 0. */
if ((Src->val.string != NULL) &&
#if DEBUG_VARS
printf("VARS: Copying value (Size %d)\n", Src->val_len);
#endif
- xmemcpy((char *) Dest->val.string, (char *) Src->val.string, Src->val_len);
+ memcpy((char *) Dest->val.string, (char *) Src->val.string, Src->val_len);
}
#if DEBUG_VARS
printf("VARS: Cloned %x.\n", (unsigned int) Dest);
}
/* Only copy if we successfully decoded something */
if (bufp) {
- xmemcpy((char *) Var->val.objid, (char *) TmpBuf, Var->val_len);
+ memcpy((char *) Var->val.objid, (char *) TmpBuf, Var->val_len);
}
#if DEBUG_VARS_DECODE
printf("VARS: Decoded OBJID (length %d) (%d bytes left)\n",
clone->count = cd->count;
clone->del_count = cd->del_count;
assert(cd->mask_size == clone->mask_size);
- xmemcpy(clone->mask, cd->mask, cd->mask_size);
+ memcpy(clone->mask, cd->mask, cd->mask_size);
return clone;
}
const unsigned int bit_count = cd->mask_size * 8;
unsigned int tmp_keys[4];
/* we must memcpy to ensure alignment */
- xmemcpy(tmp_keys, key, sizeof(tmp_keys));
+ memcpy(tmp_keys, key, sizeof(tmp_keys));
hashed_keys[0] = htonl(tmp_keys[0]) % bit_count;
hashed_keys[1] = htonl(tmp_keys[1]) % bit_count;
hashed_keys[2] = htonl(tmp_keys[2]) % bit_count;
{
public:
typedef CommAcceptCbParams Params;
+ typedef RefCount<CommAcceptCbPtrFun> Pointer;
CommAcceptCbPtrFun(IOACB *aHandler, const CommAcceptCbParams &aParams);
void dial();
class CommCbFunPtrCallT: public AsyncCall
{
public:
+ typedef RefCount<CommCbFunPtrCallT<Dialer> > Pointer;
typedef typename Dialer::Params Params;
inline CommCbFunPtrCallT(int debugSection, int debugLevel,
const char *callName, const Dialer &aDialer);
+ inline CommCbFunPtrCallT(const CommCbFunPtrCallT &o) :
+ AsyncCall(o.debugSection, o.debugLevel, o.name),
+ dialer(o.dialer) {}
+
+ ~CommCbFunPtrCallT() {}
+
virtual CallDialer* getDialer() { return &dialer; }
public:
protected:
inline virtual bool canFire();
inline virtual void fire();
+
+private:
+ CommCbFunPtrCallT & operator=(const CommCbFunPtrCallT &); // not defined. not permitted.
};
// Conveninece wrapper: It is often easier to call a templated function than
virtual ~ConfigOption() {}
virtual bool parse(char const *option, const char *value, int reconfiguring) = 0;
- virtual void dump (StoreEntry * e) const = 0;
+ virtual void dump(StoreEntry * e) const = 0;
};
class ConfigOptionVector : public ConfigOption
{
public:
- ConfigOptionAdapter(C& theObject, bool (C::*parseFP)(char const *option, const char *value, int reconfiguring), void (C::*dumpFP) (StoreEntry * e) const) : object(theObject), parser (parseFP), dumper(dumpFP) {}
+ ConfigOptionAdapter(C& theObject, bool (C::*parseFP)(char const *option, const char *value, int reconfiguring), void (C::*dumpFP)(StoreEntry * e) const) : object(theObject), parser(parseFP), dumper(dumpFP) {}
bool parse(char const *option, const char *value, int isaReconf) {
if (parser)
void dump(StoreEntry * e) const {
if (dumper)
- (object.*dumper) (e);
+ (object.*dumper)(e);
}
private:
C &object;
- bool (C::*parser) (char const *option, const char *value, int reconfiguring) ;
+ bool (C::*parser)(char const *option, const char *value, int reconfiguring) ;
void (C::*dumper)(StoreEntry * e) const;
};
return (NULL);
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(fileno(wordFile), O_TEXT);
-
#endif
fromFile = 1;
"this process: " << xstrerror());
} else {
cpu_set_t cpuSet;
- xmemcpy(&cpuSet, &theCpuSet, sizeof(cpuSet));
+ memcpy(&cpuSet, &theCpuSet, sizeof(cpuSet));
CPU_AND(&cpuSet, &cpuSet, &theOrigCpuSet);
if (CPU_COUNT(&cpuSet) <= 0) {
debugs(54, DBG_IMPORTANT, "ERROR: invalid CPU affinity for process "
void
CpuAffinitySet::set(const cpu_set_t &aCpuSet)
{
- xmemcpy(&theCpuSet, &aCpuSet, sizeof(theCpuSet));
+ memcpy(&theCpuSet, &aCpuSet, sizeof(theCpuSet));
}
extern FILE *debug_log;
-const size_t BuildPrefixInit();
+size_t BuildPrefixInit();
const char * SkipBuildPrefix(const char* path);
/* Debug stream */
AIODiskFile::open(int flags, mode_t mode, RefCount<IORequestor> callback)
{
/* Simulate async calls */
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
fd = aio_open(path.termedBuf(), flags);
#else
fd = file_open(path.termedBuf() , flags);
AIODiskFile::close ()
{
assert (!closed);
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
aio_close(fd);
#else
-
file_close(fd);
#endif
#include "comm.h"
#include "aio_win32.h"
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
VOID CALLBACK IoCompletionRoutine(DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
{
{
return aiocbp->aio_sigevent.sigev_signo;
}
-#endif /* _SQUID_WIN32_ */
+#endif /* _SQUID_WINDOWS_ */
#if USE_DISKIO_AIO
-#ifdef _SQUID_CYGWIN_
+#if _SQUID_CYGWIN_
#include "squid_windows.h"
#endif
#if USE_DISKIO_AIO
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#include "aio_win32.h"
#else
#if HAVE_AIO_H
debugs(79, 3, "DiskdFile::write: this " << (void *)this << ", buf " << (void *)aRequest->buf << ", off " << aRequest->offset << ", len " << aRequest->len);
ssize_t shm_offset;
char *sbuf = (char *)IO->shm.get(&shm_offset);
- xmemcpy(sbuf, aRequest->buf, aRequest->len);
+ memcpy(sbuf, aRequest->buf, aRequest->len);
if (aRequest->free_func)
aRequest->free_func(const_cast<char *>(aRequest->buf));
*/
#include "squid.h"
+#include "comm/Loops.h"
#include <sys/ipc.h>
#include <sys/msg.h>
fd_note(wfd, "squid -> diskd");
commSetTimeout(wfd, -1, NULL, NULL);
-
commSetNonBlocking(wfd);
-
- comm_quick_poll_required();
+ Comm::QuickPollRequired();
}
/*
fs = (file_state *)xcalloc(1, sizeof(*fs));
fs->id = r->id;
- fs->key = &fs->id; /* gack */
+ fs->key = &fs->id; /* gack */
fs->fd = fd;
hash_join(hash, (hash_link *) fs);
- DEBUG(2)
- fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n",
- (int) mypid,
- fs->id,
- fs->fd,
- fs);
+ DEBUG(2) {
+ fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n",
+ (int) mypid,
+ fs->id,
+ fs->fd,
+ fs);
+ }
return fd;
}
fd = fs->fd;
hash_remove_link(hash, (hash_link *) fs);
- DEBUG(2)
- fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n",
- (int) mypid,
- r->id,
- fs->fd,
- fs);
+ DEBUG(2) {
+ fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n",
+ (int) mypid,
+ r->id,
+ fs->fd,
+ fs);
+ }
xfree(fs);
return close(fd);
}
}
if (r->offset > -1 && r->offset != fs->offset) {
- DEBUG(2)
- fprintf(stderr, "seeking to %"PRId64"\n", (int64_t)r->offset);
+ DEBUG(2) {
+ fprintf(stderr, "seeking to %"PRId64"\n", (int64_t)r->offset);
+ }
if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
DEBUG(1) {
}
x = read(fs->fd, buf, readlen);
- DEBUG(2)
- fprintf(stderr, "%d READ %d,%d,%"PRId64" ret %d\n", (int) mypid,
- fs->fd, readlen, (int64_t)r->offset, x);
+ DEBUG(2) {
+ fprintf(stderr, "%d READ %d,%d,%"PRId64" ret %d\n", (int) mypid,
+ fs->fd, readlen, (int64_t)r->offset, x);
+ }
if (x < 0) {
DEBUG(1) {
}
}
- DEBUG(2)
- fprintf(stderr, "%d WRITE %d,%d,%"PRId64"\n", (int) mypid,
- fs->fd, wrtlen, (int64_t)r->offset);
+ DEBUG(2) {
+ fprintf(stderr, "%d WRITE %d,%d,%"PRId64"\n", (int) mypid,
+ fs->fd, wrtlen, (int64_t)r->offset);
+ }
x = write(fs->fd, buf, wrtlen);
if (x < 0) {
return -errno;
}
- DEBUG(2)
- fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf);
+ DEBUG(2) {
+ fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf);
+ }
return 0;
}
char *buf = NULL;
s->mtype = r->mtype;
s->id = r->id;
- s->seq_no = r->seq_no; /* optional, debugging */
+ s->seq_no = r->seq_no; /* optional, debugging */
s->callback_data = r->callback_data;
s->requestor = r->requestor;
- s->size = 0; /* optional, debugging */
- s->offset = 0; /* optional, debugging */
+ s->size = 0; /* optional, debugging */
+ s->offset = 0; /* optional, debugging */
s->shm_offset = r->shm_offset;
s->newstyle = r->newstyle;
for (;;) {
alarm(1);
memset(&rmsg, '\0', sizeof(rmsg));
- DEBUG(2)
- std::cerr << "msgrcv: " << rmsgid << ", "
- << &rmsg << ", " << diomsg::msg_snd_rcv_sz
- << ", " << 0 << ", " << 0 << std::endl;
+ DEBUG(2) {
+ std::cerr << "msgrcv: " << rmsgid << ", "
+ << &rmsg << ", " << diomsg::msg_snd_rcv_sz
+ << ", " << 0 << ", " << 0 << std::endl;
+ }
rlen = msgrcv(rmsgid, &rmsg, diomsg::msg_snd_rcv_sz, 0, 0);
if (rlen < 0) {
}
}
- DEBUG(2)
- fprintf(stderr, "%d diskd exiting\n", (int) mypid);
+ DEBUG(2) {
+ fprintf(stderr, "%d diskd exiting\n", (int) mypid);
+ }
if (msgctl(rmsgid, IPC_RMID, 0) < 0)
perror("msgctl IPC_RMID");
case _AIO_OP_STAT:
if (!cancelled && requestp->ret == 0)
-
- xmemcpy(requestp->statp, requestp->tmpstatp, sizeof(struct stat));
+ memcpy(requestp->statp, requestp->tmpstatp, sizeof(struct stat));
squidaio_xfree(requestp->tmpstatp, sizeof(struct stat));
case _AIO_OP_STAT:
if (!cancelled && requestp->ret == 0)
-
- xmemcpy(requestp->statp, requestp->tmpstatp, sizeof(struct stat));
+ memcpy(requestp->statp, requestp->tmpstatp, sizeof(struct stat));
squidaio_xfree(requestp->tmpstatp, sizeof(struct stat));
return *this;
}
-const int
+int
HelperChildConfig::needNew() const
{
/* during the startup and reconfigure use our special amount... */
* \retval N < 0 Error. No more helpers may be started.
* \retval N N more helpers may be started immediately.
*/
- const int needNew() const;
+ int needNew() const;
void parseConfig();
/* values from squid.conf */
{"max-age", (http_hdr_type)CC_MAX_AGE},
{"s-maxage", (http_hdr_type)CC_S_MAXAGE},
{"max-stale", (http_hdr_type)CC_MAX_STALE},
+ {"stale-if-error", (http_hdr_type)CC_STALE_IF_ERROR},
{"min-fresh", (http_hdr_type)CC_MIN_FRESH},
{"Other,", (http_hdr_type)CC_OTHER} /* ',' will protect from matches */
};
break;
+ case CC_STALE_IF_ERROR:
+ if (!p || !httpHeaderParseInt(p, &cc->stale_if_error)) {
+ debugs(65, 2, "cc: invalid stale-if-error specs near '" << item << "'");
+ cc->stale_if_error = -1;
+ EBIT_CLR(cc->mask, type);
+ }
+ break;
+
case CC_OTHER:
if (cc->other.size())
Packer p;
assert(sc);
/* remove old directives if any */
- delById(HDR_RANGE);
+ delById(HDR_SURROGATE_CONTROL);
/* pack into mb */
mb.init();
packerToMemInit(&p, &mb);
public:
MEMPROXY_CLASS(HttpHdrRangeSpec);
- typedef Range<int64_t> HttpRange;
+ typedef Range<int64_t, uint64_t> HttpRange;
static int64_t const UnknownPosition;
HttpHdrRangeSpec();
*/
return !httpHeaderHasConnDir(&header, "close");
} else {
- /*
- * Persistent connections in Netscape 3.x are allegedly broken,
- * return false if it is a browser connection. If there is a
- * VIA header, then we assume this is NOT a browser connection.
- */
- const char *agent = header.getStr(HDR_USER_AGENT);
-
- if (agent && !header.has(HDR_VIA)) {
- if (!strncasecmp(agent, "Mozilla/3.", 10))
- return 0;
-
- if (!strncasecmp(agent, "Netscape/3.", 11))
- return 0;
- }
-
/* for old versions of HTTP: persistent if has "keep-alive" */
return httpHeaderHasConnDir(&header, "keep-alive");
}
}
/*
- * Indicate whether or not we would usually expect an entity-body
+ * Indicate whether or not we would expect an entity-body
* along with this request
*/
bool
bool expectBody = false;
/*
- * GET and HEAD don't usually have bodies, but we should be prepared
- * to accept one if the request_entities directive is set
+ * Note: Checks for message validity is in clientIsContentLengthValid().
+ * this just checks if a entity-body is expected based on HTTP message syntax
*/
-
- if (method == METHOD_GET || method == METHOD_HEAD)
- expectBody = Config.onoff.request_entities ? true : false;
- else if (method == METHOD_PUT || method == METHOD_POST)
- expectBody = true;
- else if (header.chunked())
+ if (header.chunked()) {
expectBody = true;
- else if (content_length >= 0)
+ theSize = -1;
+ } else if (content_length >= 0) {
expectBody = true;
- else
+ theSize = content_length;
+ } else {
expectBody = false;
-
- if (expectBody) {
- if (header.chunked())
- theSize = -1;
- else if (content_length >= 0)
- theSize = content_length;
- else
- theSize = -1;
+ // theSize undefined
}
return expectBody;
MemBlob.h \
MemBlob.cc
-SNMP_ALL_SOURCE = \
- snmp_core.cc \
- snmp_agent.cc
-if USE_SNMP
-SNMP_SOURCE = $(SNMP_ALL_SOURCE)
-else
-SNMP_SOURCE =
-endif
-
LOADABLE_MODULES_SOURCES = \
LoadableModule.h \
LoadableModule.cc \
SSL_LOCAL_LIBS =
endif
+SNMP_ALL_SOURCE = \
+ snmp_core.h \
+ snmp_core.cc \
+ snmp_agent.cc
+if ENABLE_SNMP
+SNMP_SOURCE = $(SNMP_ALL_SOURCE)
+SUBDIRS += snmp
+SNMP_LIBS = snmp/libsnmp.la $(SNMPLIB)
+else
+SNMP_SOURCE =
+endif
+
if USE_ADAPTATION
SUBDIRS += adaptation
endif
$(SHELL) $(srcdir)/DiskIO/modules.sh $(DISK_MODULES) > DiskIO/DiskIOModules_gen.cc
-squid_COMMSOURCES = \
- comm_select.cc \
- comm_select.h \
- comm_select_win32.cc \
- comm_poll.cc \
- comm_poll.h \
- comm_devpoll.cc \
- comm_epoll.cc \
- comm_epoll.h \
- comm_kqueue.cc \
- comm_kqueue.h
-
-
# common library for all the binaries and tests. This is kindof a catch all
# and smaller libraries split from this are encouraged. Using lt convenience
# libraries, dependencies should not be a problem either.
CommIO.h \
CompletionDispatcher.cc \
CompletionDispatcher.h \
- $(squid_COMMSOURCES) \
CommRead.h \
ConfigOption.cc \
ConfigParser.cc \
PingData.h \
protos.h \
redirect.cc \
- referer.cc \
refresh.cc \
RemovalPolicy.cc \
RemovalPolicy.h \
URLScheme.cc \
URLScheme.h \
urn.cc \
- useragent.cc \
wccp.cc \
wccp2.cc \
whois.cc \
$(DISK_OS_LIBS) \
$(CRYPTLIB) \
$(REGEXLIB) \
- $(SNMPLIB) \
- ${ADAPTATION_LIBS} \
+ $(ADAPTATION_LIBS) \
$(ESI_LIBS) \
$(SSL_LIBS) \
+ $(SNMP_LIBS) \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
$(DISK_LIBS) \
$(DISK_LINKOBJS) \
$(REPL_OBJS) \
- $(SNMPLIB) \
- ${ADAPTATION_LIBS} \
+ $(ADAPTATION_LIBS) \
$(ESI_LOCAL_LIBS) \
$(SSL_LIBS) \
$(COMMON_LIBS)
$(REPL_OBJS) \
$(CRYPTLIB) \
$(REGEXLIB) \
- $(SNMPLIB) \
$(SSLLIB) \
$(COMPAT_LIB) \
$(EPOLL_LIBS) \
# Make location configure settings available to the code
DEFS += -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\" -DDEFAULT_SQUID_DATA_DIR=\"$(datadir)\" -DDEFAULT_SQUID_CONFIG_DIR=\"$(sysconfdir)\"
-snmp_core.o snmp_agent.o: ../snmplib/libsnmp.a $(top_srcdir)/include/cache_snmp.h
+snmp_core.o snmp_agent.o: ../snmplib/libsnmplib.a $(top_srcdir)/include/cache_snmp.h
globals.cc: globals.h mk-globals-c.awk
$(AWK) -f $(srcdir)/mk-globals-c.awk < $(srcdir)/globals.h > $@ || ($(RM) -f $@ && exit 1)
sed \
-e "s%[@]DEFAULT_HTTP_PORT[@]%$(DEFAULT_HTTP_PORT)%g" \
-e "s%[@]DEFAULT_ICP_PORT[@]%$(DEFAULT_ICP_PORT)%g" \
- -e "s%[@]DEFAULT_CACHE_EFFECTIVE_USER[@]%${CACHE_EFFECTIVE_USER}%g" \
+ -e "s%[@]DEFAULT_CACHE_EFFECTIVE_USER[@]%$(CACHE_EFFECTIVE_USER)%g" \
-e "s%[@]DEFAULT_MIME_TABLE[@]%$(DEFAULT_MIME_TABLE)%g" \
-e "s%[@]DEFAULT_DNSSERVER[@]%$(DEFAULT_DNSSERVER)%g" \
-e "s%[@]DEFAULT_SSL_CRTD[@]%$(DEFAULT_SSL_CRTD)%g" \
nodist_tests_testACLMaxUserIP_SOURCES= \
$(TESTSOURCES)
tests_testACLMaxUserIP_LDADD= \
- $(COMMON_LIBS) \
+ auth/libacls.la \
+ ident/libident.la \
+ acl/libacls.la \
+ eui/libeui.la \
+ acl/libstate.la \
+ auth/libauth.la \
+ acl/libapi.la \
+ base/libbase.la \
+ libsquid.la \
+ ip/libip.la \
+ fs/libfs.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
tests/testCacheManager.h \
tests/testMain.cc \
tests/stub_main_cc.cc \
+ tests/stub_ipc_Forwarder.cc \
time.cc \
BodyPipe.cc \
cache_manager.cc \
client_side_request.cc \
ClientInfo.h \
clientStream.cc \
- $(squid_COMMSOURCES) \
ConfigOption.cc \
ConfigParser.cc \
CpuAffinityMap.cc \
peer_sourcehash.cc \
peer_userhash.cc \
redirect.cc \
- referer.cc \
refresh.cc \
RemovalPolicy.cc \
Server.cc \
url.cc \
URLScheme.cc \
urn.cc \
- useragent.cc \
wccp2.cc \
whois.cc \
FadingCounter.cc \
$(BUILT_SOURCES)
# comm.cc only requires comm/libcomm.la until fdc_table is dead.
tests_testCacheManager_LDADD = \
- $(COMMON_LIBS) \
+ auth/libacls.la \
+ ident/libident.la \
+ acl/libacls.la \
+ eui/libeui.la \
+ acl/libstate.la \
+ auth/libauth.la \
+ acl/libapi.la \
+ base/libbase.la \
+ libsquid.la \
+ ip/libip.la \
+ fs/libfs.la \
+ ipc/libipc.la \
+ mgr/libmgr.la \
+ $(SNMP_LIBS) \
comm/libcomm.la \
icmp/libicmp.la icmp/libicmp-core.la \
log/liblog.la \
$(REPL_OBJS) \
- ${ADAPTATION_LIBS} \
+ $(ADAPTATION_LIBS) \
$(ESI_LIBS) \
$(SSL_LIBS) \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
$(REGEXLIB) \
- $(SNMPLIB) \
$(SQUID_CPPUNIT_LIBS) \
$(SQUID_CPPUNIT_LA) \
$(SSLLIB) \
SquidConfig.o \
CommCalls.o \
DnsLookupDetails.o \
- $(COMMON_LIBS) \
+ auth/libacls.la \
+ ident/libident.la \
+ acl/libacls.la \
+ eui/libeui.la \
+ acl/libstate.la \
+ auth/libauth.la \
+ base/libbase.la \
+ libsquid.la \
+ ip/libip.la \
+ fs/libfs.la \
$(REPL_OBJS) \
$(DISK_LIBS) \
$(DISK_OS_LIBS) \
acl/libapi.la \
+ mgr/libmgr.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
tests/testEvent.h \
tests/testMain.cc \
tests/stub_main_cc.cc \
+ tests/stub_ipc_Forwarder.cc \
time.cc \
BodyPipe.cc \
cache_manager.cc \
client_side_request.cc \
ClientInfo.h \
clientStream.cc \
- $(squid_COMMSOURCES) \
ConfigOption.cc \
ConfigParser.cc \
CpuAffinityMap.cc \
peer_sourcehash.cc \
peer_userhash.cc \
redirect.cc \
- referer.cc \
refresh.cc \
Server.cc \
$(SNMP_SOURCE) \
url.cc \
URLScheme.cc \
urn.cc \
- useragent.cc \
wccp2.cc \
whois.cc \
FadingCounter.cc \
$(BUILT_SOURCES)
tests_testEvent_LDADD = \
$(COMMON_LIBS) \
+ $(SNMP_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
$(REPL_OBJS) \
- ${ADAPTATION_LIBS} \
+ $(ADAPTATION_LIBS) \
$(ESI_LIBS) \
$(SSL_LIBS) \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
$(REGEXLIB) \
- $(SNMPLIB) \
$(SQUID_CPPUNIT_LIBS) \
$(SQUID_CPPUNIT_LA) \
$(SSLLIB) \
tests/testEventLoop.h \
tests/testMain.cc \
tests/stub_main_cc.cc \
+ tests/stub_ipc_Forwarder.cc \
time.cc \
BodyPipe.cc \
cache_manager.cc \
client_side_request.cc \
ClientInfo.h \
clientStream.cc \
- $(squid_COMMSOURCES) \
ConfigOption.cc \
ConfigParser.cc \
CpuAffinityMap.cc \
peer_sourcehash.cc \
peer_userhash.cc \
redirect.cc \
- referer.cc \
refresh.cc \
Server.cc \
$(SNMP_SOURCE) \
url.cc \
URLScheme.cc \
urn.cc \
- useragent.cc \
wccp2.cc \
whois.cc \
FadingCounter.cc \
$(BUILT_SOURCES)
tests_testEventLoop_LDADD = \
$(COMMON_LIBS) \
+ $(SNMP_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
$(REPL_OBJS) \
- ${ADAPTATION_LIBS} \
+ $(ADAPTATION_LIBS) \
$(ESI_LIBS) \
$(SSL_LIBS) \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
$(REGEXLIB) \
- $(SNMPLIB) \
$(SQUID_CPPUNIT_LIBS) \
$(SQUID_CPPUNIT_LA) \
$(SSLLIB) \
client_side_request.cc \
ClientInfo.h \
clientStream.cc \
- $(squid_COMMSOURCES) \
ConfigOption.cc \
ConfigParser.cc \
CpuAffinityMap.cc \
CpuAffinitySet.cc \
CpuAffinitySet.h \
tests/stub_main_cc.cc \
+ tests/stub_ipc_Forwarder.cc \
debug.cc \
$(DELAY_POOL_SOURCE) \
disk.cc \
peer_userhash.cc \
pconn.cc \
redirect.cc \
- referer.cc \
refresh.cc \
RemovalPolicy.cc \
Server.cc \
url.cc \
URLScheme.cc \
urn.cc \
- useragent.cc \
wccp2.cc \
whois.cc \
FadingCounter.cc \
$(BUILT_SOURCES)
tests_test_http_range_LDADD = \
$(COMMON_LIBS) \
+ $(SNMP_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
$(REPL_OBJS) \
- ${ADAPTATION_LIBS} \
+ $(ADAPTATION_LIBS) \
$(ESI_LIBS) \
$(SSL_LIBS) \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
$(REGEXLIB) \
- $(SNMPLIB) \
$(SQUID_CPPUNIT_LIBS) \
$(SQUID_CPPUNIT_LA) \
$(SSLLIB) \
tests/testHttpRequestMethod.cc \
tests/testMain.cc \
tests/stub_main_cc.cc \
+ tests/stub_ipc_Forwarder.cc \
time.cc \
BodyPipe.cc \
cache_manager.cc \
client_side_request.cc \
ClientInfo.h \
clientStream.cc \
- $(squid_COMMSOURCES) \
ConfigOption.cc \
ConfigParser.cc \
CpuAffinityMap.cc \
peer_sourcehash.cc \
peer_userhash.cc \
redirect.cc \
- referer.cc \
refresh.cc \
RemovalPolicy.cc \
Server.cc \
url.cc \
URLScheme.cc \
urn.cc \
- useragent.cc \
wccp2.cc \
whois.cc \
FadingCounter.cc \
$(BUILT_SOURCES)
tests_testHttpRequest_LDADD = \
$(COMMON_LIBS) \
+ $(SNMP_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
$(REPL_OBJS) \
- ${ADAPTATION_LIBS} \
+ $(ADAPTATION_LIBS) \
$(ESI_LIBS) \
$(SSL_LIBS) \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
$(REGEXLIB) \
- $(SNMPLIB) \
$(SQUID_CPPUNIT_LIBS) \
$(SQUID_CPPUNIT_LA) \
$(SSLLIB) \
nodist_tests_testString_SOURCES = \
$(TESTSOURCES)
tests_testString_LDADD = \
- $(COMMON_LIBS) \
+ base/libbase.la \
+ libsquid.la \
+ ip/libip.la \
$(top_builddir)/lib/libmiscutil.la \
$(REGEXLIB) \
$(SQUID_CPPUNIT_LIBS) \
tests/testMain.cc \
tests/stub_debug.cc \
tests/stub_main_cc.cc \
+ tests/stub_ipc_Forwarder.cc \
time.cc \
BodyPipe.cc \
cache_manager.cc \
client_side_request.cc \
ClientInfo.h \
clientStream.cc \
- $(squid_COMMSOURCES) \
ConfigOption.cc \
ConfigParser.cc \
CpuAffinityMap.cc \
peer_sourcehash.cc \
peer_userhash.cc \
redirect.cc \
- referer.cc \
refresh.cc \
Server.cc \
$(SNMP_SOURCE) \
tunnel.cc \
SwapDir.cc \
urn.cc \
- useragent.cc \
wccp2.cc \
whois.cc \
FadingCounter.cc \
$(BUILT_SOURCES)
tests_testURL_LDADD = \
$(COMMON_LIBS) \
+ $(SNMP_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
$(REGEXLIB) \
$(REPL_OBJS) \
- ${ADAPTATION_LIBS} \
+ $(ADAPTATION_LIBS) \
$(ESI_LIBS) \
$(SSL_LIBS) \
- $(SNMPLIB) \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
* by MemPools via memAllocString.
*/
MemBlob::size_type
-MemBlob::calcAllocSize(const size_type size) const
+MemBlob::calcAllocSize(const size_type sz) const
{
- if (size <= 36) return 36;
- if (size <= 128) return 128;
- if (size <= 512) return 512;
- if (size <= 4096) return RoundTo(size, 512);
+ if (sz <= 36) return 36;
+ if (sz <= 128) return 128;
+ if (sz <= 512) return 512;
+ if (sz <= 4096) return RoundTo(sz, 512);
// XXX: recover squidSystemPageSize functionality. It's easy for
// the main squid, harder for tests
#if 0
- return RoundTo(size, squidSystemPageSize);
+ return RoundTo(sz, squidSystemPageSize);
#else
- return RoundTo(size, 4096);
+ return RoundTo(sz, 4096);
#endif
}
PROF_start(MemBuf_consume);
if (shiftSize > 0) {
if (shiftSize < cSize)
- xmemmove(buf, buf + shiftSize, cSize - shiftSize);
+ memmove(buf, buf + shiftSize, cSize - shiftSize);
size -= shiftSize;
grow(size + sz + 1);
assert(size + sz <= capacity); /* paranoid */
-
- xmemcpy(space(), newContent, sz);
-
+ memcpy(space(), newContent, sz);
appended(sz);
}
PROF_stop(MemBuf_append);
SquidMD5Init(&M);
SquidMD5Update(&M, (unsigned char *) url, strlen(url));
SquidMD5Final(digest, &M);
- xmemcpy(&ck, digest, sizeof(ck));
+ memcpy(&ck, digest, sizeof(ck));
return ck;
}
};
void
-MemObject::stat (MemBuf * mb) const
+MemObject::stat(MemBuf * mb) const
{
mb->Printf("\t%s %s\n",
RequestMethodStr(method), log_url);
+ if (vary_headers)
+ mb->Printf("\tvary_headers: %s\n", vary_headers);
mb->Printf("\tinmem_lo: %"PRId64"\n", inmem_lo);
mb->Printf("\tinmem_hi: %"PRId64"\n", data_hdr.endOffset());
mb->Printf("\tswapout: %"PRId64" bytes queued\n",
static void
xprof_sorthist(TimersArray * xprof_list)
{
- int i;
-
- for (i = 0; i < XPROF_LAST; i++) {
+ for (int i = 0; i < XPROF_LAST; i++) {
sortlist[i] = xprof_list[i];
}
- qsort(&sortlist[XPROF_hash_lookup], XPROF_LAST - XPROF_hash_lookup, sizeof(xprof_stats_node *), (QS *) xprof_comp);
+ qsort(&sortlist[XPROF_PROF_UNACCOUNTED+1], XPROF_LAST - XPROF_PROF_UNACCOUNTED+1, sizeof(xprof_stats_node *), (QS *) xprof_comp);
}
static double time_frame;
*/
#include "squid.h"
+#include "comm.h"
#include "ProtoPort.h"
#if HAVE_LIMITS
#include <limits>
#endif
-http_port_list::http_port_list(const char *aProtocol)
+http_port_list::http_port_list(const char *aProtocol) :
+ listenFd(-1)
#if USE_SSL
- :
- http(*this), dynamicCertMemCacheSize(std::numeric_limits<size_t>::max())
+ , http(*this)
+ , dynamicCertMemCacheSize(std::numeric_limits<size_t>::max())
#endif
{
protocol = xstrdup(aProtocol);
http_port_list::~http_port_list()
{
- delete listener;
+ if (listenFd >= 0) {
+ comm_close(listenFd);
+ listenFd = -1;
+ }
safe_free(name);
safe_free(defaultsite);
#ifndef SQUID_PROTO_PORT_H
#define SQUID_PROTO_PORT_H
-//#include "typedefs.h"
#include "cbdata.h"
-#include "comm/ListenStateData.h"
#if USE_SSL
#include "ssl/gadgets.h"
} tcp_keepalive;
/**
- * The FD listening socket handler.
- * If not NULL we are actively listening for client requests.
- * delete to close the socket.
+ * The FD listening socket.
+ * If >= 0 we are actively listening for client requests.
+ * use comm_close(listenFd) to stop.
*/
- Comm::ListenStateData *listener;
+ int listenFd;
#if USE_SSL
// XXX: temporary hack to ease move of SSL options to http_port
return b ? ((int) (100.0 * a / b + 0.5)) : 0;
}
+int64_t
+Math::int64Percent(const int64_t a, const int64_t b)
+{
+ return b ? ((int64_t) (100.0 * a / b + 0.5)) : 0;
+}
+
double
Math::doublePercent(const double a, const double b)
{
{
extern int intPercent(const int a, const int b);
+extern int64_t int64Percent(const int64_t a, const int64_t b);
extern double doublePercent(const double, const double);
extern int intAverage(const int, const int, int, const int);
extern double doubleAverage(const double, const double, int, const int);
virtual void tick();
};
+namespace Time
+{
+
+/** Display time as a formatted human-readable string.
+ * Time syntax is
+ * "YYYY/MM/DD hh:mm:ss"
+ *
+ * Output is only valid until next call to this function.
+ */
+const char *FormatStrf(time_t t);
+
+/** Display time as a formatted human-readable string.
+ * Time string syntax used is that of Apache httpd.
+ * "DD/MMM/YYYY:hh:mm:ss zzzz"
+ *
+ * Output is only valid until next call to this function.
+ */
+const char *FormatHttpd(time_t t);
+
+} // namespace Time
+
#endif /* SQUID_TIME_H */
static int statHistBin(const StatHist * H, double v);
static double statHistVal(const StatHist * H, int bin);
static StatHistBinDumper statHistBinDumper;
-#if !defined(_SQUID_HPUX_) || !defined(__GNUC__)
-/*
- * HP-UX and GCC (2.8?) give strange errors when these simple
- * functions are static.
- */
-static hbase_f Log;
-static hbase_f Exp;
-static hbase_f Null;
-#endif
+
+namespace Math
+{
+hbase_f Log;
+hbase_f Exp;
+hbase_f Null;
+};
/* low level init, higher level functions has less params */
static void
(long int) (Dest->capacity * sizeof(*Dest->bins)) << " bytes to " <<
Dest->bins << " from " << Orig->bins);
- xmemcpy(Dest->bins, Orig->bins, Dest->capacity * sizeof(*Dest->bins));
+ memcpy(Dest->bins, Orig->bins, Dest->capacity * sizeof(*Dest->bins));
}
/*
}
/* log based histogram */
-#if !defined(_SQUID_HPUX_) || !defined(__GNUC__)
-static
-#endif
double
-Log(double x)
+Math::Log(double x)
{
assert((x + 1.0) >= 0.0);
return log(x + 1.0);
}
-#if !defined(_SQUID_HPUX_) || !defined(__GNUC__)
-static
-#endif
double
-Exp(double x)
+Math::Exp(double x)
{
return exp(x) - 1.0;
}
void
statHistLogInit(StatHist * H, int capacity, double min, double max)
{
- statHistInit(H, capacity, Log, Exp, min, max);
+ statHistInit(H, capacity, Math::Log, Math::Exp, min, max);
}
/* linear histogram for enums */
/* we want to be have [-1,last_enum+1] range to track out of range enums */
-#if !defined(_SQUID_HPUX_) || !defined(__GNUC__)
-static
-#endif
double
-Null(double x)
+Math::Null(double x)
{
return x;
}
void
statHistEnumInit(StatHist * H, int last_enum)
{
- statHistInit(H, last_enum + 3, Null, Null, (double) -1, (double) (last_enum + 1 + 1));
+ statHistInit(H, last_enum + 3, Math::Null, Math::Null, (double) -1, (double) (last_enum + 1 + 1));
}
void
void
statHistIntInit(StatHist * H, int n)
{
- statHistInit(H, n, Null, Null, (double) 0, (double) n - 1);
+ statHistInit(H, n, Math::Null, Math::Null, (double) 0, (double) n - 1);
}
void
* The maximum size the store will support in normal use. Inaccuracy is permitted,
* but may throw estimates for memory etc out of whack.
*/
- virtual size_t maxSize() const = 0;
+ virtual uint64_t maxSize() const = 0;
/** The minimum size the store will shrink to via normal housekeeping */
- virtual size_t minSize() const = 0;
+ virtual uint64_t minSize() const = 0;
/**
* Output stats to the provided store entry.
SQUIDCEXTERN void storeAppendPrintf(StoreEntry *, const char *,...) PRINTF_FORMAT_ARG2;
/// \ingroup StoreAPI
-SQUIDCEXTERN void storeAppendVPrintf(StoreEntry *, const char *, va_list ap);
+extern void storeAppendVPrintf(StoreEntry *, const char *, va_list ap);
/// \ingroup StoreAPI
SQUIDCEXTERN int storeTooManyDiskFilesOpen(void);
\par
* The storage types live in \em src/fs/. Each subdirectory corresponds
* to the name of the storage type. When a new storage type is implemented
- * configure.in must be updated to autogenerate a Makefile in
+ * configure.ac must be updated to autogenerate a Makefile in
* \em src/fs/foo/ from a Makefile.in file.
*
- \todo DOCS: add template addition to configure.in for storage module addition.
+ \todo DOCS: add template addition to configure.ac for storage module addition.
\todo DOCS: add template Makefile.am for storage module addition.
*
\par
virtual void sync();
- virtual size_t maxSize() const;
+ virtual uint64_t maxSize() const;
- virtual size_t minSize() const;
+ virtual uint64_t minSize() const;
virtual void stat(StoreEntry&) const;
result->length = len;
result->value = xmalloc(len);
- xmemcpy(result->value, value, len);
+ memcpy(result->value, value, len);
return result;
}
void
StoreMetaUnpacker::getBufferLength()
{
- xmemcpy(hdr_len, &buf[1], sizeof(int));
+ memcpy(hdr_len, &buf[1], sizeof(int));
}
StoreMetaUnpacker::StoreMetaUnpacker (char const *aBuffer, ssize_t aLen, int *anInt) : buf (aBuffer), buflen(aLen), hdr_len(anInt), position(1 + sizeof(int))
void
StoreMetaUnpacker::getLength()
{
- xmemcpy(&length, &buf[position], sizeof(int));
+ memcpy(&length, &buf[position], sizeof(int));
position += sizeof(int);
}
assert(this && str);
allocBuffer(len + 1);
len_ = len;
- xmemcpy(buf_, str, len);
+ memcpy(buf_, str, len);
buf_[len] = '\0';
PROF_stop(StringAllocAndFill);
}
snew.allocBuffer(snew.len_ + 1);
if (len_)
- xmemcpy(snew.buf_, rawBuf(), len_);
+ memcpy(snew.buf_, rawBuf(), len_);
if (len)
- xmemcpy(snew.buf_ + len_, str, len);
+ memcpy(snew.buf_ + len_, str, len);
snew.buf_[snew.len_] = '\0';
}
void
-
-StringRegistry::add
-(String const *entry)
+StringRegistry::add(String const *entry)
{
entries.insert(entry, ptrcmp);
}
void
-
-StringRegistry::remove
-(String const *entry)
+StringRegistry::remove(String const *entry)
{
entries.remove(entry, ptrcmp);
}
void
String::cut(String::size_type newLength)
{
- if (newLength < 0 || newLength > len_) return;
+ // size_type is size_t, unsigned. No need to check for newLength <0
+ if (newLength > len_) return;
len_ = newLength;
void
SwapDir::maintain() {}
-size_t
+uint64_t
SwapDir::minSize() const
{
- return (size_t) (((float) maxSize() *
- (float) Config.Swap.lowWaterMark) / 100.0);
+ return ((maxSize() * Config.Swap.lowWaterMark) / 100);
}
void
{
ConfigOptionVector *result = new ConfigOptionVector;
result->options.push_back(new ConfigOptionAdapter<SwapDir>(*const_cast<SwapDir *>(this), &SwapDir::optionReadOnlyParse, &SwapDir::optionReadOnlyDump));
- result->options.push_back(new ConfigOptionAdapter<SwapDir>(*const_cast<SwapDir *>(this), &SwapDir::optionMaxSizeParse, &SwapDir::optionMaxSizeDump));
+ result->options.push_back(new ConfigOptionAdapter<SwapDir>(*const_cast<SwapDir *>(this), &SwapDir::optionObjectSizeParse, &SwapDir::optionObjectSizeDump));
return result;
}
}
bool
-SwapDir::optionMaxSizeParse(char const *option, const char *value, int isaReconfig)
+SwapDir::optionObjectSizeParse(char const *option, const char *value, int isaReconfig)
{
- if (strcmp(option, "max-size") != 0)
+ int64_t *val;
+ if (strcmp(option, "max-size") == 0) {
+ val = &max_objsize;
+ } else if (strcmp(option, "min-size") == 0) {
+ val = &min_objsize;
+ } else
return false;
if (!value)
int64_t size = strtoll(value, NULL, 10);
- if (isaReconfig && max_objsize != size)
- debugs(3, 1, "Cache dir '" << path << "' max object size now " << size);
+ if (isaReconfig && *val != size)
+ debugs(3, 1, "Cache dir '" << path << "' object " << option << " now " << size);
- max_objsize = size;
+ *val = size;
return true;
}
void
-SwapDir::optionMaxSizeDump(StoreEntry * e) const
+SwapDir::optionObjectSizeDump(StoreEntry * e) const
{
+ if (min_objsize != 0)
+ storeAppendPrintf(e, " min-size=%"PRId64, min_objsize);
+
if (max_objsize != -1)
storeAppendPrintf(e, " max-size=%"PRId64, max_objsize);
}
* but the parent child relationship isn't implemented yet
*/
StoreEntry *
-
-SwapDir::get
-(const cache_key *key)
+SwapDir::get(const cache_key *key)
{
return Store::Root().get(key);
}
void
-
-SwapDir::get
-(String const key, STOREGETCLIENT aCallback, void *aCallbackData)
+SwapDir::get(String const key, STOREGETCLIENT aCallback, void *aCallbackData)
{
fatal("not implemented");
}
virtual void maintain(); /* perform regular maintenance should be private and self registered ... */
- virtual size_t maxSize() const;
+ virtual uint64_t maxSize() const;
- virtual size_t minSize() const;
+ virtual uint64_t minSize() const;
virtual void stat(StoreEntry &) const;
{
public:
- SwapDir(char const *aType) : theType (aType), cur_size(0), max_size(0), max_objsize (-1), cleanLog(NULL) {
+ SwapDir(char const *aType) : theType (aType), cur_size(0), max_size(0), min_objsize(0), max_objsize(-1), cleanLog(NULL) {
fs.blksize = 1024;
path = NULL;
}
virtual void get(String const, STOREGETCLIENT, void * cbdata);
- virtual size_t maxSize() const { return max_size;}
+ virtual uint64_t maxSize() const { return max_size;}
- virtual size_t minSize() const;
+ virtual uint64_t minSize() const;
virtual void stat (StoreEntry &anEntry) const;
virtual StoreSearch *search(String const url, HttpRequest *) = 0;
private:
bool optionReadOnlyParse(char const *option, const char *value, int reconfiguring);
void optionReadOnlyDump(StoreEntry * e) const;
- bool optionMaxSizeParse(char const *option, const char *value, int reconfiguring);
- void optionMaxSizeDump(StoreEntry * e) const;
+ bool optionObjectSizeParse(char const *option, const char *value, int reconfiguring);
+ void optionObjectSizeDump(StoreEntry * e) const;
char const *theType;
public:
- size_t cur_size;
- size_t max_size;
+ uint64_t cur_size; ///< currently used space in the storage area
+ uint64_t max_size; ///< maximum allocatable size of the storage area
char *path;
int index; /* This entry's index into the swapDirs array */
+ int64_t min_objsize;
int64_t max_objsize;
RemovalPolicy *repl;
int removals;
* Next, copy the left over data, from s to s + leftoversz to the
* beginning of the buffer
*/
- xmemmove(buf, s, leftoversz);
+ memmove(buf, s, leftoversz);
/*
* Next, update our offset and reqofs, and kick off a copy if required
*/
#include "config.h"
-#ifdef _SQUID_CYGWIN_
+#if _SQUID_CYGWIN_
#include <squid_windows.h>
#endif
#include "squid.h"
}
bool
-ACLSslErrorData::match(ssl_error_t toFind)
+ACLSslErrorData::match(Ssl::ssl_error_t toFind)
{
return values->findAndTune (toFind);
}
/* explicit instantiation required for some systems */
/** \cond AUTODOCS-IGNORE */
// AYJ: 2009-05-20 : Removing. clashes with template <int> instantiation for other ACLs.
-// template cbdata_type CbDataList<ssl_error_t>::CBDATA_CbDataList;
+// template cbdata_type CbDataList<Ssl::ssl_error_t>::CBDATA_CbDataList;
/** \endcond */
wordlist *
ACLSslErrorData::dump()
{
wordlist *W = NULL;
- CbDataList<ssl_error_t> *data = values;
+ CbDataList<Ssl::ssl_error_t> *data = values;
while (data != NULL) {
- wordlistAdd(&W, sslFindErrorString(data->element));
+ wordlistAdd(&W, Ssl::getErrorName(data->element));
data = data->next;
}
void
ACLSslErrorData::parse()
{
- CbDataList<ssl_error_t> **Tail;
+ CbDataList<Ssl::ssl_error_t> **Tail;
char *t = NULL;
for (Tail = &values; *Tail; Tail = &((*Tail)->next));
while ((t = strtokFile())) {
- CbDataList<ssl_error_t> *q = new CbDataList<ssl_error_t>(sslParseErrorString(t));
+ CbDataList<Ssl::ssl_error_t> *q = new CbDataList<Ssl::ssl_error_t>(Ssl::parseErrorString(t));
*(Tail) = q;
Tail = &q->next;
}
return values == NULL;
}
-ACLData<ssl_error_t> *
+ACLData<Ssl::ssl_error_t> *
ACLSslErrorData::clone() const
{
/* Splay trees don't clone yet. */
#include "acl/Data.h"
#include "CbDataList.h"
#include "ssl/support.h"
+#include "ssl/ErrorDetail.h"
-class ACLSslErrorData : public ACLData<ssl_error_t>
+class ACLSslErrorData : public ACLData<Ssl::ssl_error_t>
{
public:
ACLSslErrorData(ACLSslErrorData const &);
ACLSslErrorData &operator= (ACLSslErrorData const &);
virtual ~ACLSslErrorData();
- bool match(ssl_error_t);
+ bool match(Ssl::ssl_error_t);
wordlist *dump();
void parse();
bool empty() const;
- virtual ACLData<ssl_error_t> *clone() const;
+ virtual ACLData<Ssl::ssl_error_t> *clone() const;
- CbDataList<ssl_error_t> *values;
+ CbDataList<Ssl::ssl_error_t> *values;
};
MEMPROXY_CLASS_INLINE(ACLSslErrorData);
if (when != last_when) {
last_when = when;
-
- xmemcpy(&tm, localtime(&when), sizeof(struct tm));
+ memcpy(&tm, localtime(&when), sizeof(struct tm));
}
t = (time_t) (tm.tm_hour * 60 + tm.tm_min);
bool
Adaptation::ServiceConfig::parse()
{
- char *method_point = NULL;
+ String method_point;
ConfigParser::ParseString(&key);
ConfigParser::ParseString(&method_point);
- method = parseMethod(method_point);
- point = parseVectPoint(method_point);
+ method = parseMethod(method_point.termedBuf());
+ point = parseVectPoint(method_point.termedBuf());
// reset optional parameters in case we are reconfiguring
bypass = routing = false;
#include "base/TextException.h"
#include "adaptation/ecap/ServiceRep.h"
#include "adaptation/ecap/Host.h"
+#include "adaptation/ecap/MessageRep.h"
+#include "HttpRequest.h"
+#include "HttpReply.h"
const libecap::Name Adaptation::Ecap::protocolInternal("internal", libecap::Name::NextId());
const libecap::Name Adaptation::Ecap::protocolCacheObj("cache_object", libecap::Name::NextId());
Debug::finishDebug();
}
+
+Adaptation::Ecap::Host::MessagePtr
+Adaptation::Ecap::Host::newRequest() const
+{
+ return MessagePtr(new Adaptation::Ecap::MessageRep(new HttpRequest));
+}
+
+Adaptation::Ecap::Host::MessagePtr
+Adaptation::Ecap::Host::newResponse() const
+{
+ return MessagePtr(new Adaptation::Ecap::MessageRep(new HttpReply));
+}
+
void
Adaptation::Ecap::Host::Register()
{
virtual std::ostream *openDebug(libecap::LogVerbosity lv);
virtual void closeDebug(std::ostream *debug);
+ // Message creation
+ typedef libecap::shared_ptr<libecap::Message> MessagePtr;
+ virtual MessagePtr newRequest() const;
+ virtual MessagePtr newResponse() const;
+
static void Register(); ///< register adaptation host
private:
}
}
- {
+ if (proxyingVb == opOn) {
BodyPipe::Pointer body_pipe = theVirginRep.raw().body_pipe;
if (body_pipe != NULL) {
Must(body_pipe->stillConsuming(this));
#include "icap_log.h"
#include "AccessLogEntry.h"
#include "log/File.h"
+#include "log/Formats.h"
int IcapLogfileStatus = LOG_DISABLE;
customlog *log;
for (log = Config.Log.icaplogs; log; log = log->next) {
- if (log->type == CLF_NONE)
+ if (log->type == Log::Format::CLF_NONE)
continue;
- if (log->type == CLF_AUTO)
- log->type = CLF_ICAP_SQUID;
-
log->logfile = logfileOpen(log->filename, MAX_URL << 1, 1);
IcapLogfileStatus = LOG_ENABLE;
} else {
debugs(29, 0, "AuthNegotiateConfig::parse: unrecognised negotiate auth scheme parameter '" << param_str << "'");
}
-
- /*
- * disable client side request pipelining. There is a race with
- * Negotiate when the client sends a second request on an Negotiate
- * connection before the authenticate challenge is sent. With
- * this patch, the client may fail to authenticate, but squid's
- * state will be preserved. Caveats: this should be a post-parse
- * test, but that can wait for the modular parser to be integrated.
- */
- if (authenticate)
- Config.onoff.pipeline_prefetch = 0;
}
const char *
} else {
debugs(29, 0, "AuthNTLMConfig::parse: unrecognised ntlm auth scheme parameter '" << param_str << "'");
}
-
- /*
- * disable client side request pipelining. There is a race with
- * NTLM when the client sends a second request on an NTLM
- * connection before the authenticate challenge is sent. With
- * this patch, the client may fail to authenticate, but squid's
- * state will be preserved. Caveats: this should be a post-parse
- * test, but that can wait for the modular parser to be integrated.
- */
- if (authenticate)
- Config.onoff.pipeline_prefetch = 0;
}
const char *
os << "(?" << this << "?)";
}
+void
+AsyncCall::dequeue(AsyncCall::Pointer &head, AsyncCall::Pointer &prev)
+{
+ if (prev != NULL)
+ prev->setNext(Next());
+ else
+ head = Next();
+ setNext(NULL);
+}
+
bool
ScheduleCall(const char *fileName, int fileLine, AsyncCall::Pointer &call)
{
void print(std::ostream &os);
+ /// remove us from the queue; we are head unless we are queued after prev
+ void dequeue(AsyncCall::Pointer &head, AsyncCall::Pointer &prev);
+
void setNext(AsyncCall::Pointer aNext) {
theNext = aNext;
}
private:
const char *isCanceled; // set to the cancelation reason by cancel()
+
+ // not implemented to prevent nil calls from being passed around and unknowingly scheduled, for now.
+ AsyncCall();
+ AsyncCall(const AsyncCall &);
};
inline
const Dialer &aDialer): AsyncCall(aDebugSection, aDebugLevel, aName),
dialer(aDialer) {}
+ AsyncCallT(const AsyncCallT<Dialer> &o):
+ AsyncCall(o.debugSection, o.debugLevel, o.name),
+ dialer(o.dialer) {}
+
+ ~AsyncCallT() {}
+
CallDialer *getDialer() { return &dialer; }
protected:
virtual void fire() { dialer.dial(*this); }
Dialer dialer;
+
+private:
+ AsyncCallT & operator=(const AsyncCallT &); // not defined. call assignments not permitted.
};
template <class Dialer>
public:
/// Must be passed an object. nil pointers are not permitted.
explicit CallSubscription(const RefCount<Call_> &aCall) : call(aCall) { assert(aCall != NULL); }
- virtual AsyncCall::Pointer callback() const { return new Call_(call); }
+ virtual AsyncCall::Pointer callback() const { return new Call_(*call); }
private:
const RefCount<Call_> call; ///< gets copied to create callback calls
/// Delete callback.
typedef void DCB (T *t);
TidyPointer(T *t = NULL)
- : raw(t), deAllocator(DeAllocator) {}
+ : raw(t) {}
public:
bool operator !() const { return !raw; }
/// Returns raw and possibly NULL pointer
/// Deallocate raw pointer. Become a nil pointer.
void deletePointer() {
if (raw) {
- deAllocator(raw);
+ DeAllocator(raw);
}
raw = NULL;
}
T *raw; ///< pointer to T object or NULL
- DCB *deAllocator; ///< cleanup function
};
/// DeAllocator for pointers that need free(3) from the std C library
#include "adaptation/ecap/Config.h"
#endif
#if USE_SSL
+#include "ssl/support.h"
#include "ssl/Config.h"
#endif
#include "auth/Config.h"
static const char *const list_sep = ", \t\n\r";
-static void parse_logformat(logformat ** logformat_definitions);
static void parse_access_log(customlog ** customlog_definitions);
static int check_null_access_log(customlog *customlog_definitions);
-
-static void dump_logformat(StoreEntry * entry, const char *name, logformat * definitions);
static void dump_access_log(StoreEntry * entry, const char *name, customlog * definitions);
-static void free_logformat(logformat ** definitions);
static void free_access_log(customlog ** definitions);
static void update_maxobjsize(void);
if (fp == NULL)
fatalf("Unable to open configuration file: %s: %s", file_name, xstrerror());
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
setmode(fileno(fp), O_TEXT);
-
#endif
SetConfigFilename(file_name, bool(is_pipe));
}
#endif
+
+ // prevent infinite fetch loops in the request parser
+ // due to buffer full but not enough data recived to finish parse
+ if (Config.maxRequestBufferSize <= Config.maxRequestHeaderSize) {
+ fatalf("Client request buffer of %u bytes cannot hold a request with %u bytes of headers." \
+ " Change client_request_buffer_max or request_header_max_size limits.",
+ (uint32_t)Config.maxRequestBufferSize, (uint32_t)Config.maxRequestHeaderSize);
+ }
+
+ /*
+ * disable client side request pipelining. There is a race with
+ * Negotiate and NTLM when the client sends a second request on an
+ * connection before the authenticate challenge is sent. With
+ * pipelining OFF, the client may fail to authenticate, but squid's
+ * state will be preserved.
+ */
+ if (Config.onoff.pipeline_prefetch) {
+ AuthConfig *nego = AuthConfig::Find("Negotiate");
+ AuthConfig *ntlm = AuthConfig::Find("NTLM");
+ if ((nego && nego->active()) || (ntlm && ntlm->active())) {
+ debugs(3, DBG_IMPORTANT, "WARNING: pipeline_prefetch breaks NTLM and Negotiate authentication. Forced OFF.");
+ Config.onoff.pipeline_prefetch = 0;
+ }
+ }
}
/** Parse a line containing an obsolete directive.
(int) (100.0 * head->pct + 0.5),
(int) head->max / 60);
+ if (head->max_stale >= 0)
+ storeAppendPrintf(entry, " max-stale=%d", head->max_stale);
+
if (head->flags.refresh_ims)
storeAppendPrintf(entry, " refresh-ims");
time_t max = 0;
int refresh_ims = 0;
int store_stale = 0;
+ int max_stale = -1;
#if USE_HTTP_VIOLATIONS
refresh_ims = 1;
} else if (!strcmp(token, "store-stale")) {
store_stale = 1;
+ } else if (!strncmp(token, "max-stale=", 10)) {
+ max_stale = atoi(token + 10);
#if USE_HTTP_VIOLATIONS
} else if (!strcmp(token, "override-expire"))
#endif
} else
- debugs(22, 0, "redreshAddToList: Unknown option '" << pattern << "': " << token);
+ debugs(22, 0, "refreshAddToList: Unknown option '" << pattern << "': " << token);
}
if ((errcode = regcomp(&comp, pattern, flags)) != 0) {
if (store_stale)
t->flags.store_stale = 1;
+ t->max_stale = max_stale;
+
#if USE_HTTP_VIOLATIONS
if (override_expire)
if (s->name)
storeAppendPrintf(e, " name=%s", s->name);
-#if !USE_HTTP_VIOLATIONS
+#if USE_HTTP_VIOLATIONS
if (!s->accel && s->ignore_cc)
storeAppendPrintf(e, " ignore-cc");
#endif
configFreeMemory(void)
{
free_all();
+#if USE_SSL
+ SSL_CTX_free(Config.ssl_client.sslContext);
+#endif
}
void
}
#include "AccessLogEntry.h"
-/* TODO: split out parsing somehow ...*/
-static void
-parse_logformat(logformat ** logformat_definitions)
-{
- logformat *nlf;
- char *name, *def;
-
- if ((name = strtok(NULL, w_space)) == NULL)
- self_destruct();
-
- if ((def = strtok(NULL, "\r\n")) == NULL) {
- self_destruct();
- return;
- }
-
- debugs(3, 2, "Logformat for '" << name << "' is '" << def << "'");
-
- nlf = (logformat *)xcalloc(1, sizeof(logformat));
-
- nlf->name = xstrdup(name);
-
- if (!accessLogParseLogFormat(&nlf->format, def)) {
- self_destruct();
- return;
- }
-
- nlf->next = *logformat_definitions;
-
- *logformat_definitions = nlf;
-}
static void
parse_access_log(customlog ** logs)
}
if (strcmp(filename, "none") == 0) {
- cl->type = CLF_NONE;
+ cl->type = Log::Format::CLF_NONE;
goto done;
}
if ((logdef_name = strtok(NULL, w_space)) == NULL)
- logdef_name = "auto";
+ logdef_name = "squid";
debugs(3, 9, "Log definition name '" << logdef_name << "' file '" << filename << "'");
cl->filename = xstrdup(filename);
/* look for the definition pointer corresponding to this name */
- lf = Config.Log.logformats;
+ lf = Log::TheConfig.logformats;
while (lf != NULL) {
debugs(3, 9, "Comparing against '" << lf->name << "'");
}
if (lf != NULL) {
- cl->type = CLF_CUSTOM;
+ cl->type = Log::Format::CLF_CUSTOM;
cl->logFormat = lf;
} else if (strcmp(logdef_name, "auto") == 0) {
- cl->type = CLF_AUTO;
+ debugs(0,0, "WARNING: Log format 'auto' no longer exists. Using 'squid' instead.");
+ cl->type = Log::Format::CLF_SQUID;
} else if (strcmp(logdef_name, "squid") == 0) {
- cl->type = CLF_SQUID;
+ cl->type = Log::Format::CLF_SQUID;
} else if (strcmp(logdef_name, "common") == 0) {
- cl->type = CLF_COMMON;
+ cl->type = Log::Format::CLF_COMMON;
+ } else if (strcmp(logdef_name, "combined") == 0) {
+ cl->type = Log::Format::CLF_COMBINED;
#if ICAP_CLIENT
} else if (strcmp(logdef_name, "icap_squid") == 0) {
- cl->type = CLF_ICAP_SQUID;
+ cl->type = Log::Format::CLF_ICAP_SQUID;
#endif
+ } else if (strcmp(logdef_name, "useragent") == 0) {
+ cl->type = Log::Format::CLF_USERAGENT;
+ } else if (strcmp(logdef_name, "referrer") == 0) {
+ cl->type = Log::Format::CLF_REFERER;
} else {
debugs(3, 0, "Log format '" << logdef_name << "' is not defined");
self_destruct();
return customlog_definitions == NULL;
}
-static void
-dump_logformat(StoreEntry * entry, const char *name, logformat * definitions)
-{
- accessLogDumpLogFormat(entry, name, definitions);
-}
-
static void
dump_access_log(StoreEntry * entry, const char *name, customlog * logs)
{
switch (log->type) {
- case CLF_CUSTOM:
+ case Log::Format::CLF_CUSTOM:
storeAppendPrintf(entry, "%s %s", log->filename, log->logFormat->name);
break;
- case CLF_NONE:
+ case Log::Format::CLF_NONE:
storeAppendPrintf(entry, "none");
break;
- case CLF_SQUID:
+ case Log::Format::CLF_SQUID:
storeAppendPrintf(entry, "%s squid", log->filename);
break;
- case CLF_COMMON:
- storeAppendPrintf(entry, "%s squid", log->filename);
+ case Log::Format::CLF_COMBINED:
+ storeAppendPrintf(entry, "%s combined", log->filename);
break;
+
+ case Log::Format::CLF_COMMON:
+ storeAppendPrintf(entry, "%s common", log->filename);
+ break;
+
#if ICAP_CLIENT
- case CLF_ICAP_SQUID:
+ case Log::Format::CLF_ICAP_SQUID:
storeAppendPrintf(entry, "%s icap_squid", log->filename);
break;
#endif
- case CLF_AUTO:
-
- if (log->aclList)
- storeAppendPrintf(entry, "%s auto", log->filename);
- else
- storeAppendPrintf(entry, "%s", log->filename);
+ case Log::Format::CLF_USERAGENT:
+ storeAppendPrintf(entry, "%s useragent", log->filename);
+ break;
+ case Log::Format::CLF_REFERER:
+ storeAppendPrintf(entry, "%s referrer", log->filename);
break;
- case CLF_UNKNOWN:
+ case Log::Format::CLF_UNKNOWN:
break;
}
}
}
-static void
-free_logformat(logformat ** definitions)
-{
- while (*definitions) {
- logformat *format = *definitions;
- *definitions = format->next;
- safe_free(format->name);
- accessLogFreeLogFormat(&format->format);
- xfree(format);
- }
-}
-
static void
free_access_log(customlog ** definitions)
{
*definitions = log->next;
log->logFormat = NULL;
- log->type = CLF_UNKNOWN;
+ log->type = Log::Format::CLF_UNKNOWN;
if (log->aclList)
aclDestroyAclList(&log->aclList);
CacheEntry *e = xcalloc(1, sizeof(CacheEntry));
assert(s);
/* e->s = *s; */
- xmemcpy(e->key_arr, s->key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(e->key_arr, s->key, SQUID_MD5_DIGEST_LENGTH);
e->key = &e->key_arr[0];
return e;
}
return 0;
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(fileno(file), O_BINARY);
-
#endif
scanned_count = cacheIndexScan(idx, fname, file);
void
CacheManager::ParseHeaders(const HttpRequest * request, Mgr::ActionParams ¶ms)
{
- const char *basic_cookie; /* base 64 _decoded_ user:passwd pair */
- const char *passwd_del;
assert(request);
params.httpMethod = request->method.id();
params.httpFlags = request->flags;
- basic_cookie = request->header.getAuth(HDR_AUTHORIZATION, "Basic");
+#if HAVE_AUTH_MODULE_BASIC
+ // TODO: use the authentication system decode to retrieve these details properly.
+
+ /* base 64 _decoded_ user:passwd pair */
+ const char *basic_cookie = request->header.getAuth(HDR_AUTHORIZATION, "Basic");
if (!basic_cookie)
return;
+ const char *passwd_del;
if (!(passwd_del = strchr(basic_cookie, ':'))) {
debugs(16, DBG_IMPORTANT, "CacheManager::ParseHeaders: unknown basic_cookie format '" << basic_cookie << "'");
return;
params.userName.limitInit(basic_cookie, passwd_del - basic_cookie);
params.password = passwd_del + 1;
- /* warning: this prints decoded password which maybe not what you want to do @?@ @?@ */
+ /* warning: this prints decoded password which maybe not be what you want to do @?@ @?@ */
debugs(16, 9, "CacheManager::ParseHeaders: got user: '" <<
params.userName << "' passwd: '" << params.password << "'");
+#endif
}
/**
errorStateFree(errState);
+#if HAVE_AUTH_MODULE_BASIC
/*
* add Authenticate header using action name as a realm because
* password depends on the action
*/
rep->header.putAuth("Basic", actionName);
+#endif
/* store the reply */
entry->replaceHttpReply(rep);
acl aclname maxconn number
# This will be matched when the client's IP address has
- # more than <number> HTTP connections established. [fast]
+ # more than <number> TCP connections established. [fast]
+ # NOTE: This only measures direct TCP links so X-Forwarded-For
+ # indirect clients are not counted.
acl aclname max_user_ip [-s] number
# This will be matched when the user attempts to log in from more
Controls whether the indirect client address
(see follow_x_forwarded_for) is used instead of the
direct client address in acl matching.
+
+ NOTE: maxconn ACL considers direct TCP links and indirect
+ clients will always have zero. So no match.
DOC_END
NAME: delay_pool_uses_indirect_client
an additional ACL needs to be used which ensures the IPv6-bound traffic
is never forced or permitted out the IPv4 interface.
+ # IPv6 destination test along with a dummy access control to perofrm the required DNS
+ # This MUST be place before any ALLOW rules.
acl to_ipv6 dst ipv6
- tcp_outgoing_address 2002::c001 good_service_net to_ipv6
+ http_access deny ipv6 !all
+
+ tcp_outgoing_address 2001:db8::c001 good_service_net to_ipv6
tcp_outgoing_address 10.1.0.2 good_service_net !to_ipv6
- tcp_outgoing_address 2002::beef normal_service_net to_ipv6
+ tcp_outgoing_address 2001:db8::beef normal_service_net to_ipv6
tcp_outgoing_address 10.1.0.1 normal_service_net !to_ipv6
- tcp_outgoing_address 2002::1 to_ipv6
+ tcp_outgoing_address 2001:db8::1 to_ipv6
tcp_outgoing_address 10.1.0.3 !to_ipv6
WARNING:
no-store, no new objects should be stored to this cache_dir
- max-size=n, refers to the max object size this storedir supports.
- It is used to initially choose the storedir to dump the object.
+ min-size=n, refers to the min object size in bytes this cache_dir
+ will accept. It's used to restrict a cache_dir to only store
+ large objects (e.g. aufs) while other storedirs are optimized
+ for smaller objects (e.g. COSS). Defaults to 0.
+
+ max-size=n, refers to the max object size in bytes this cache_dir
+ supports. It is used to select the cache_dir to store the object.
Note: To make optimal use of the max-size limits you should order
the cache_dir lines with the smallest max-size value first and the
ones with no max-size specification last.
NAME: logformat
TYPE: logformat
-LOC: Config.Log.logformats
+LOC: Log::TheConfig
DEFAULT: none
DOC_START
Usage:
>a Client source IP address
>A Client FQDN
>p Client source port
+ >eui Client EUI (MAC address, EUI-48 or EUI-64 identifier)
<A Server IP address or peer name
la Local IP address (http_port)
lp Local port number (http_port)
The default formats available (which do not need re-defining) are:
-logformat squid %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %un %Sh/%<A %mt
-logformat squidmime %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %un %Sh/%<A %mt [%>h] [%<h]
-logformat common %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %<st %Ss:%Sh
-logformat combined %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %<st "%{Referer}>h" "%{User-Agent}>h" %Ss:%Sh
+logformat squid %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %un %Sh/%<A %mt
+logformat common %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %<st %Ss:%Sh
+logformat combined %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %>Hs %<st "%{Referer}>h" "%{User-Agent}>h" %Ss:%Sh
+logformat referrer %ts.%03tu %>a %{Referer}>h %ru
+logformat useragent %>a [%tl] "%{User-Agent}>h"
+
+ When the log_mime_hdrs directive is set to ON. The squid, common and combined
+ formats have a safely encoded copy of the mime headers appended to each line
+ within a pair of brackets.
+
+ The common and combined formats are not quite true to the Apache definition.
+ The logs from Squid contain an extra status and hierarchy code appended.
DOC_END
NAME: access_log cache_access_log
L<data>\n - logfile data
R\n - rotate file
T\n - truncate file
- O\n - repoen file
+ O\n - reopen file
F\n - flush file
r<n>\n - set rotate count to <n>
b<n>\n - 1 = buffer output, 0 = don't buffer output
DOC_END
NAME: emulate_httpd_log
-COMMENT: on|off
-TYPE: onoff
-DEFAULT: off
-LOC: Config.onoff.common_log
+TYPE: obsolete
DOC_START
- The Cache can emulate the log file format which many 'httpd'
- programs use. To disable/enable this emulation, set
- emulate_httpd_log to 'off' or 'on'. The default
- is to use the native log format since it includes useful
- information Squid-specific log analyzers use.
+ Replace this with an access_log directive using the format 'common' or 'combined'.
DOC_END
NAME: log_ip_on_direct
DOC_END
NAME: useragent_log
-TYPE: string
-LOC: Config.Log.useragent
-DEFAULT: none
-IFDEF: USE_USERAGENT_LOG
+TYPE: obsolete
DOC_START
- Squid will write the User-Agent field from HTTP requests
- to the filename specified here. By default useragent_log
- is disabled.
+ Replace this with an access_log directive using the format 'useragent'.
DOC_END
NAME: referer_log referrer_log
-TYPE: string
-LOC: Config.Log.referer
-DEFAULT: none
-IFDEF: USE_REFERER_LOG
+TYPE: obsolete
DOC_START
- Squid will write the Referer field from HTTP requests to the
- filename specified here. By default referer_log is disabled.
- Note that "referer" is actually a misspelling of "referrer"
- however the misspelt version has been accepted into the HTTP RFCs
- and we accept both.
+ Replace this with an access_log directive using the format 'referrer'.
DOC_END
NAME: pid_filename
DOC_END
NAME: forward_log
-IFDEF: WIP_FWD_LOG
-TYPE: string
-DEFAULT: none
-LOC: Config.Log.forward
+TYPE: obsolete
DOC_START
- Logs the server-side requests.
-
- This is currently work in progress.
+ Use a regular access.log with ACL limiting it to MISS events.
DOC_END
NAME: strip_query_terms
Requires ftp_passive to be ON (default) for any effect.
DOC_END
+NAME: ftp_eprt
+TYPE: onoff
+DEFAULT: on
+LOC: Config.Ftp.eprt
+DOC_START
+ FTP Protocol extensions permit the use of a special "EPRT" command.
+
+ This extension provides a protocol neutral alternative to the
+ IPv4-only PORT command. When supported it enables active FTP data
+ channels over IPv6 and efficient NAT handling.
+
+ Turning this OFF will prevent EPRT being attempted and will skip
+ straight to using PORT for IPv4 servers.
+
+ Some devices are known to not handle this extension correctly and
+ may result in crashes. Devices which suport EPRT enough to fail
+ cleanly will result in Squid attempting PORT anyway. This directive
+ should only be disabled when EPRT results in device failures.
+
+ WARNING: Doing so will convert Squid back to the old behavior with all
+ the related problems with external NAT devices/layers and IPv4-only FTP.
+DOC_END
+
NAME: ftp_sanitycheck
TYPE: onoff
DEFAULT: on
See http://wiki.squid-cache.org/SquidFaq/SquidAcl for details.
DOC_END
+NAME: max_stale
+COMMENT: time-units
+TYPE: time_t
+LOC: Config.maxStale
+DEFAULT: 1 week
+DOC_START
+ This option puts an upper limit on how stale content Squid
+ will serve from the cache if cache validation fails.
+ Can be overriden by the refresh_pattern max-stale option.
+DOC_END
+
NAME: refresh_pattern
TYPE: refreshpattern
LOC: Config.Refresh
ignore-must-revalidate
ignore-private
ignore-auth
+ max-stale=NN
refresh-ims
store-stale
not cache such responses because they usually can't be
reused. Note that such responses will be stale by default.
+ max-stale=NN provide a maximum staleness factor. Squid won't
+ serve objects more stale than this even if it failed to
+ validate the object. Default: use the max_stale global limit.
+
Basically a cached object is:
FRESH if expires < now, else STALE
be no limit imposed.
DOC_END
+NAME: client_request_buffer_max_size
+COMMENT: (bytes)
+TYPE: b_size_t
+DEFAULT: 512 KB
+LOC: Config.maxRequestBufferSize
+DOC_START
+ This specifies the maximum buffer size of a client request.
+ It prevents squid eating too much memory when somebody uploads
+ a large file.
+DOC_END
+
NAME: chunked_request_body_max_size
COMMENT: (bytes)
TYPE: b_int64_t
you may also specify them by your custom file name:
Example: deny_info ERR_CUSTOM_ACCESS_DENIED bad_guys
+ By defaut Squid will send "403 Forbidden". A different 4xx or 5xx
+ may be specified by prefixing the file name with the code and a colon.
+ e.g. 404:ERR_CUSTOM_ACCESS_DENIED
+
Alternatively you can tell Squid to reset the TCP connection
by specifying TCP_RESET.
Or you can specify an error URL or URL pattern. The browsers will
- get redirected (302) to the specified URL after formatting tags have
- been replaced.
+ get redirected to the specified URL after formatting tags have
+ been replaced. Redirect will be done with 302 or 307 according to
+ HTTP/1.1 specs. A different 3xx code may be specified by prefixing
+ the URL. e.g. 303:http://example.com/
URL FORMAT TAGS:
%a - username (if available. Password NOT included)
X-Forwarded-For header.
If set to "truncate", Squid will remove all existing
- X-Forwarded-For entries, and place itself as the sole entry.
+ X-Forwarded-For entries, and place the client IP as the sole entry.
DOC_END
NAME: cachemgr_passwd
Defaults to off for bandwidth management and access logging
reasons.
+
+ WARNING: pipelining breaks NTLM and Negotiate/Kerberos authentication.
DOC_END
NAME: high_response_time_warning
exit(1);
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(fileno(fp), O_TEXT);
#endif
exit(1);
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(fileno(fp), O_TEXT);
-
#endif
fprintf(fp,
exit(1);
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(fileno(fp), O_TEXT);
-
#endif
gen_conf(entries, fp, 1);
perror(conf_filename_short);
exit(1);
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(fileno(fp), O_TEXT);
#endif
gen_conf(entries, fp, 0);
define["USE_ICMP"]="--enable-icmp"
define["USE_IDENT"]="--enable-ident-lookups"
define["USE_LOADABLE_MODULES"]="--enable-loadable-modules"
- define["USE_REFERER_LOG"]="--enable-referer-log"
define["USE_SQUID_ESI"]="--enable-esi"
define["USE_SSL"]="--enable-ssl"
define["USE_UNLINKD"]="--enable-unlinkd"
- define["USE_USERAGENT_LOG"]="--enable-useragent-log"
define["USE_WCCP"]="--enable-wccp"
define["USE_WCCPv2"]="--enable-wccpv2"
define["USE_QOS_TOS"]="--enable-zph-qos"
#include "event.h"
#include "ClientInfo.h"
#include "ip/Address.h"
+#include "log/Tokens.h"
#include "mgr/Registration.h"
#include "SquidMath.h"
#include "SquidTime.h"
#include "acl/FilledChecklist.h"
#include "auth/UserRequest.h"
+#include "base/TextException.h"
#include "ChunkedCodingParser.h"
#include "client_side.h"
#include "client_side_reply.h"
#include "client_side_request.h"
+#if USE_DELAY_POOLS
+#include "ClientInfo.h"
+#endif
#include "ClientRequestContext.h"
#include "clientStream.h"
#include "comm.h"
+#include "CommCalls.h"
+#include "comm/Loops.h"
#include "comm/Write.h"
-#include "comm/ListenStateData.h"
-#include "base/TextException.h"
+#include "comm/TcpAcceptor.h"
#include "ConnectionDetail.h"
#include "eui/Config.h"
#include "fde.h"
#include "ident/Config.h"
#include "ident/Ident.h"
#include "ip/Intercept.h"
+#include "ipc/FdNotes.h"
#include "ipc/StartListening.h"
#include "MemBuf.h"
#include "MemObject.h"
#include "ProtoPort.h"
#include "rfc1738.h"
#include "SquidTime.h"
-#include "Store.h"
-
-#if USE_DELAY_POOLS
-#include "ClientInfo.h"
-#endif
-
#if USE_SSL
#include "ssl/context_storage.h"
#include "ssl/helper.h"
+#include "ssl/support.h"
#include "ssl/gadgets.h"
#endif
#if USE_SSL_CRTD
#include "ssl/crtd_message.h"
#include "ssl/certificate_db.h"
#endif
+#include "Store.h"
#if HAVE_LIMITS
#include <limits>
#define comm_close comm_lingering_close
#endif
-/// dials clientHttpConnectionOpened or clientHttpsConnectionOpened call
+/// dials clientListenerConnectionOpened call
class ListeningStartedDialer: public CallDialer, public Ipc::StartListeningCb
{
public:
- typedef void (*Handler)(int fd, int errNo, http_port_list *portCfg);
- ListeningStartedDialer(Handler aHandler, http_port_list *aPortCfg):
- handler(aHandler), portCfg(aPortCfg) {}
+ typedef void (*Handler)(int fd, int flags, int errNo, http_port_list *portCfg, const Ipc::FdNoteId note, const Subscription::Pointer &sub);
+ ListeningStartedDialer(Handler aHandler, int openFlags, http_port_list *aPortCfg, const Ipc::FdNoteId note, const Subscription::Pointer &aSub):
+ handler(aHandler), portCfg(aPortCfg), portTypeNote(note), commOpenListenerFlags(openFlags), sub(aSub) {}
virtual void print(std::ostream &os) const {
startPrint(os) <<
}
virtual bool canDial(AsyncCall &) const { return true; }
- virtual void dial(AsyncCall &) { (handler)(fd, errNo, portCfg); }
+ virtual void dial(AsyncCall &) { (handler)(fd, commOpenListenerFlags, errNo, portCfg, portTypeNote, sub); }
public:
Handler handler;
private:
- http_port_list *portCfg; ///< from Config.Sockaddr.http
+ http_port_list *portCfg; ///< from Config.Sockaddr.http
+ Ipc::FdNoteId portTypeNote; ///< Type of IPC socket being opened
+ int commOpenListenerFlags; ///< flags used by comm_open_listener
+ Subscription::Pointer sub; ///< The handler to be subscribed for this connetion listener
};
-
-static void clientHttpConnectionOpened(int fd, int errNo, http_port_list *s);
-#if USE_SSL
-static void clientHttpsConnectionOpened(int fd, int errNo, http_port_list *s);
-#endif
+static void clientListenerConnectionOpened(int fd, int flags, int errNo, http_port_list *s, const Ipc::FdNoteId portTypeNote, const Subscription::Pointer &sub);
/* our socket-related context */
debugs(33, 4, "clientReadSomeData: FD " << fd << ": reading request...");
- makeSpaceAvailable();
+ if (!maybeMakeSpaceAvailable())
+ return;
typedef CommCbMemFunT<ConnStateData, CommIoCbParams> Dialer;
reader = JobCallback(33, 5,
{
switch (r->method.id()) {
- case METHOD_PUT:
-
- case METHOD_POST:
- /* PUT/POST requires a request entity */
- return (r->content_length >= 0);
-
case METHOD_GET:
case METHOD_HEAD:
* intersection of "have" and "need" ranges must not be empty
*/
assert(http->out.offset < i->currentSpec()->offset + i->currentSpec()->length);
- assert(http->out.offset + available.size() > i->currentSpec()->offset);
+ assert(http->out.offset + (int64_t)available.size() > i->currentSpec()->offset);
/*
* put boundary and headers at the beginning of a range in a
/* adjust for not to be transmitted bytes */
http->out.offset = nextOffset;
- if (available.size() <= skip)
+ if (available.size() <= (uint64_t)skip)
return;
available.start += skip;
return result;
}
-void
-ConnStateData::makeSpaceAvailable()
+bool
+ConnStateData::maybeMakeSpaceAvailable()
{
if (getAvailableBufferLength() < 2) {
- in.buf = (char *)memReallocBuf(in.buf, in.allocatedSize * 2, &in.allocatedSize);
+ size_t newSize;
+ if (in.allocatedSize >= Config.maxRequestBufferSize) {
+ debugs(33, 4, "request buffer full: client_request_buffer_max_size=" << Config.maxRequestBufferSize);
+ return false;
+ }
+ if ((newSize=in.allocatedSize * 2) > Config.maxRequestBufferSize) {
+ newSize=Config.maxRequestBufferSize;
+ }
+ in.buf = (char *)memReallocBuf(in.buf, newSize, &in.allocatedSize);
debugs(33, 2, "growing request buffer: notYetUsed=" << in.notYetUsed << " size=" << in.allocatedSize);
}
+ return true;
}
void
*/
if (conn->in.notYetUsed > 0)
- xmemmove(conn->in.buf, conn->in.buf + byteCount,
- conn->in.notYetUsed);
+ memmove(conn->in.buf, conn->in.buf + byteCount, conn->in.notYetUsed);
}
/// respond with ERR_TOO_BIG if request header exceeds request_header_max_size
connStripBufferWhitespace (ConnStateData * conn)
{
while (conn->in.notYetUsed > 0 && xisspace(conn->in.buf[0])) {
- xmemmove(conn->in.buf, conn->in.buf + 1, conn->in.notYetUsed - 1);
+ memmove(conn->in.buf, conn->in.buf + 1, conn->in.notYetUsed - 1);
--conn->in.notYetUsed;
}
}
char *current_buf = in.addressToReadInto();
if (buf != current_buf)
- xmemmove(current_buf, buf, size);
+ memmove(current_buf, buf, size);
in.notYetUsed += size;
void
ConnStateData::noteMoreBodySpaceAvailable(BodyPipe::Pointer )
{
- handleRequestBodyData();
+ if (!handleRequestBodyData())
+ return;
+
+ readSomeData();
}
void
/*
* Aha, but we don't want a read handler!
*/
- commSetSelect(io.fd, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(io.fd, COMM_SELECT_READ, NULL, NULL, 0);
}
#else
/** Handle a new connection on HTTP socket. */
void
-httpAccept(int sock, int newfd, ConnectionDetail *details,
- comm_err_t flag, int xerrno, void *data)
+httpAccept(int, int newfd, ConnectionDetail *details, comm_err_t flag, int xerrno, void *data)
{
http_port_list *s = (http_port_list *)data;
ConnStateData *connState = NULL;
if (flag != COMM_OK) {
- debugs(33, 1, "httpAccept: FD " << sock << ": accept failure: " << xstrerr(xerrno));
+ // Its possible the call was still queued when the client disconnected
+ debugs(33, 2, "httpAccept: FD " << s->listenFd << ": accept failure: " << xstrerr(xerrno));
return;
}
switch (ssl_error) {
case SSL_ERROR_WANT_READ:
- commSetSelect(fd, COMM_SELECT_READ, clientNegotiateSSL, conn, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, clientNegotiateSSL, conn, 0);
return;
case SSL_ERROR_WANT_WRITE:
- commSetSelect(fd, COMM_SELECT_WRITE, clientNegotiateSSL, conn, 0);
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, clientNegotiateSSL, conn, 0);
return;
case SSL_ERROR_SYSCALL:
/** handle a new HTTPS connection */
static void
-httpsAccept(int sock, int newfd, ConnectionDetail *details,
- comm_err_t flag, int xerrno, void *data)
+httpsAccept(int, int newfd, ConnectionDetail *details, comm_err_t flag, int xerrno, void *data)
{
https_port_list *s = (https_port_list *)data;
SSL_CTX *sslContext = s->staticSslContext.get();
if (flag != COMM_OK) {
- errno = xerrno;
- debugs(33, 1, "httpsAccept: FD " << sock << ": accept failure: " << xstrerr(xerrno));
+ // Its possible the call was still queued when the client disconnected
+ debugs(33, 2, "httpsAccept: FD " << s->listenFd << ": accept failure: " << xstrerr(xerrno));
return;
}
commSetTcpKeepalive(newfd, s->http.tcp_keepalive.idle, s->http.tcp_keepalive.interval, s->http.tcp_keepalive.timeout);
}
- commSetSelect(newfd, COMM_SELECT_READ, clientNegotiateSSL, connState, 0);
+ Comm::SetSelect(newfd, COMM_SELECT_READ, clientNegotiateSSL, connState, 0);
clientdbEstablished(details->peer, 1);
// commSetTimeout() was called for this request before we switched.
// Disable the client read handler until peer selection is complete
- commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
-
- commSetSelect(fd, COMM_SELECT_READ, clientNegotiateSSL, this, 0);
-
+ Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, clientNegotiateSSL, this, 0);
switchedToHttps_ = true;
return true;
}
/// check FD after clientHttp[s]ConnectionOpened, adjust HttpSockets as needed
static bool
-OpenedHttpSocket(int fd, const char *msgIfFail)
+OpenedHttpSocket(int fd, const Ipc::FdNoteId portType)
{
if (fd < 0) {
Must(NHttpSockets > 0); // we tried to open some
Must(HttpSockets[NHttpSockets] < 0); // no extra fds received
if (!NHttpSockets) // we could not open any listen sockets at all
- fatal(msgIfFail);
+ fatalf("Unable to open %s",FdNote(portType));
return false;
}
const int openFlags = COMM_NONBLOCKING |
(s->spoof_client_ip ? COMM_TRANSPARENT : 0);
- AsyncCall::Pointer callback = asyncCall(33,2,
- "clientHttpConnectionOpened",
- ListeningStartedDialer(&clientHttpConnectionOpened, s));
- Ipc::StartListening(SOCK_STREAM, IPPROTO_TCP, s->s, openFlags,
- Ipc::fdnHttpSocket, callback);
+ // setup the subscriptions such that new connections accepted by listenConn are handled by HTTP
+ typedef CommCbFunPtrCallT<CommAcceptCbPtrFun> AcceptCall;
+ RefCount<AcceptCall> subCall = commCbCall(5, 5, "httpAccept", CommAcceptCbPtrFun(httpAccept, s));
+ Subscription::Pointer sub = new CallSubscription<AcceptCall>(subCall);
+
+ AsyncCall::Pointer listenCall = asyncCall(33,2, "clientListenerConnectionOpened",
+ ListeningStartedDialer(&clientListenerConnectionOpened, openFlags, s, Ipc::fdnHttpSocket, sub));
+ Ipc::StartListening(SOCK_STREAM, IPPROTO_TCP, s->s, openFlags, Ipc::fdnHttpSocket, listenCall);
- HttpSockets[NHttpSockets++] = -1; // set in clientHttpConnectionOpened
+ HttpSockets[NHttpSockets++] = -1; // set in clientListenerConnectionOpened
}
#if USE_SSL
/// process clientHttpConnectionsOpen result
static void
-clientHttpConnectionOpened(int fd, int, http_port_list *s)
+clientListenerConnectionOpened(int fd, int flags, int errNo, http_port_list *s, const Ipc::FdNoteId portTypeNote, const Subscription::Pointer &sub)
{
- if (!OpenedHttpSocket(fd, "Cannot open HTTP Port"))
+ s->listenFd = fd;
+ if (!OpenedHttpSocket(s->listenFd, portTypeNote))
return;
Must(s);
+ Must(s->listenFd >= 0);
- AsyncCall::Pointer call = commCbCall(5,5, "SomeCommAcceptHandler(httpAccept)",
- CommAcceptCbPtrFun(httpAccept, s));
+ // TCP: setup a job to handle accept() with subscribed handler
+ AsyncJob::Start(new Comm::TcpAcceptor(s->listenFd, s->s, flags, FdNote(portTypeNote), sub));
- s->listener = new Comm::ListenStateData(fd, call, true);
-
- debugs(1, 1, "Accepting " <<
+ debugs(1, 1, "Accepting" <<
(s->intercepted ? " intercepted" : "") <<
(s->spoof_client_ip ? " spoofing" : "") <<
(s->sslBump ? " bumpy" : "") <<
(s->accel ? " accelerated" : "")
- << " HTTP connections at " << s->s
- << ", FD " << fd << "." );
+ << FdNote(portTypeNote) << " connections at "
+ << " FD " << s->listenFd << " on " << s->s);
- Must(AddOpenedHttpSocket(fd)); // otherwise, we have received a fd we did not ask for
+ Must(AddOpenedHttpSocket(s->listenFd)); // otherwise, we have received a fd we did not ask for
}
#if USE_SSL
continue;
}
- AsyncCall::Pointer call = asyncCall(33, 2, "clientHttpsConnectionOpened",
- ListeningStartedDialer(&clientHttpsConnectionOpened, &s->http));
-
- Ipc::StartListening(SOCK_STREAM, IPPROTO_TCP, s->http.s, COMM_NONBLOCKING,
- Ipc::fdnHttpsSocket, call);
-
- HttpSockets[NHttpSockets++] = -1;
- }
-}
-
-/// process clientHttpsConnectionsOpen result
-static void
-clientHttpsConnectionOpened(int fd, int, http_port_list *s)
-{
- if (!OpenedHttpSocket(fd, "Cannot open HTTPS Port"))
- return;
-
- Must(s);
+ const int openFlags = COMM_NONBLOCKING |
+ (s->spoof_client_ip ? COMM_TRANSPARENT : 0);
- AsyncCall::Pointer call = commCbCall(5,5, "SomeCommAcceptHandler(httpsAccept)",
- CommAcceptCbPtrFun(httpsAccept, s));
+ // setup the subscriptions such that new connections accepted by listenConn are handled by HTTPS
+ typedef CommCbFunPtrCallT<CommAcceptCbPtrFun> AcceptCall;
+ RefCount<AcceptCall> subCall = commCbCall(5, 5, "httpsAccept", CommAcceptCbPtrFun(httpsAccept, s));
+ Subscription::Pointer sub = new CallSubscription<AcceptCall>(subCall);
- s->listener = new Comm::ListenStateData(fd, call, true);
+ AsyncCall::Pointer listenCall = asyncCall(33, 2, "clientListenerConnectionOpened",
+ ListeningStartedDialer(&clientListenerConnectionOpened, openFlags,
+ &s->http, Ipc::fdnHttpsSocket, sub));
- debugs(1, 1, "Accepting HTTPS connections at " << s->s << ", FD " << fd << ".");
+ Ipc::StartListening(SOCK_STREAM, IPPROTO_TCP, s->s, openFlags, Ipc::fdnHttpsSocket, listenCall);
- Must(AddOpenedHttpSocket(fd)); // otherwise, we have received a fd we did not ask for
+ HttpSockets[NHttpSockets++] = -1;
+ }
}
-
#endif
void
clientHttpConnectionsClose(void)
{
for (http_port_list *s = Config.Sockaddr.http; s; s = s->next) {
- if (s->listener) {
- debugs(1, 1, "FD " << s->listener->fd << " Closing HTTP connection");
- delete s->listener;
- s->listener = NULL;
+ if (s->listenFd >= 0) {
+ debugs(1, 1, "FD " << s->listenFd << " Closing HTTP connection");
+ comm_close(s->listenFd);
+ s->listenFd = -1;
}
}
#if USE_SSL
for (http_port_list *s = Config.Sockaddr.https; s; s = s->next) {
- if (s->listener) {
- debugs(1, 1, "FD " << s->listener->fd << " Closing HTTPS connection");
- delete s->listener;
- s->listener = NULL;
+ if (s->listenFd >= 0) {
+ debugs(1, 1, "FD " << s->listenFd << " Closing HTTPS connection");
+ comm_close(s->listenFd);
+ s->listenFd = -1;
}
}
#endif
class ChunkedCodingParser;
class HttpParser;
-template <class T>
-class Range;
-
class ClientSocketContext : public RefCountable
{
void freeAllContexts();
void notifyAllContexts(const int xerrno); ///< tell everybody about the err
void readNextRequest();
- void makeSpaceAvailable();
+ bool maybeMakeSpaceAvailable();
ClientSocketContext::Pointer getCurrentContext() const;
void addContextToQueue(ClientSocketContext * context);
int getConcurrentRequestCount() const;
#include "HttpReply.h"
#include "HttpRequest.h"
#include "ip/QosConfig.h"
+#include "log/Tokens.h"
#include "MemObject.h"
#include "SquidTime.h"
#include "StoreClient.h"
void
clientReplyContext::processConditional(StoreIOBuffer &result)
{
- StoreEntry *e = http->storeEntry();
+ StoreEntry *const e = http->storeEntry();
if (e->getReply()->sline.status != HTTP_OK) {
debugs(88, 4, "clientReplyContext::processConditional: Reply code " <<
if (!r.flags.ims) {
// RFC 2616: if If-None-Match matched and there is no IMS,
- // reply with 412 Precondition Failed
- sendPreconditionFailedError();
+ // reply with 304 Not Modified or 412 Precondition Failed
+ sendNotModifiedOrPreconditionFailedError();
return;
}
- // otherwise check IMS below to decide if we reply with 412
+ // otherwise check IMS below to decide if we reply with 304 or 412
matchedIfNoneMatch = true;
}
}
if (matchedIfNoneMatch) {
- // If-None-Match matched, reply with 412 Precondition Failed
- sendPreconditionFailedError();
+ // If-None-Match matched, reply with 304 Not Modified or
+ // 412 Precondition Failed
+ sendNotModifiedOrPreconditionFailedError();
return;
}
// otherwise reply with 304 Not Modified
- const time_t timestamp = e->timestamp;
- HttpReply *const temprep = e->getReply()->make304();
- http->logType = LOG_TCP_IMS_HIT;
- removeClientStoreReference(&sc, http);
- createStoreEntry(http->request->method, request_flags());
- e = http->storeEntry();
- // Copy timestamp from the original entry so the 304
- // reply has a meaningful Age: header.
- e->timestamp = timestamp;
- e->replaceHttpReply(temprep);
- e->complete();
- /*
- * TODO: why put this in the store and then serialise it and
- * then parse it again. Simply mark the request complete in
- * our context and write the reply struct to the client side.
- */
- triggerInitialStoreRead();
+ sendNotModified();
}
}
startError(err);
}
+/// send 304 (Not Modified) to client
+void
+clientReplyContext::sendNotModified()
+{
+ StoreEntry *e = http->storeEntry();
+ const time_t timestamp = e->timestamp;
+ HttpReply *const temprep = e->getReply()->make304();
+ http->logType = LOG_TCP_IMS_HIT;
+ removeClientStoreReference(&sc, http);
+ createStoreEntry(http->request->method, request_flags());
+ e = http->storeEntry();
+ // Copy timestamp from the original entry so the 304
+ // reply has a meaningful Age: header.
+ e->timestamp = timestamp;
+ e->replaceHttpReply(temprep);
+ e->complete();
+ /*
+ * TODO: why put this in the store and then serialise it and
+ * then parse it again. Simply mark the request complete in
+ * our context and write the reply struct to the client side.
+ */
+ triggerInitialStoreRead();
+}
+
+/// send 304 (Not Modified) or 412 (Precondition Failed) to client
+/// depending on request method
+void
+clientReplyContext::sendNotModifiedOrPreconditionFailedError()
+{
+ if (http->request->method == METHOD_GET ||
+ http->request->method == METHOD_HEAD)
+ sendNotModified();
+ else
+ sendPreconditionFailedError();
+}
+
void
clientReplyContext::processReplyAccess ()
{
if (buf != result.data) {
/* we've got to copy some data */
assert(result.length <= next()->readBuffer.length);
- xmemcpy(buf, result.data, result.length);
+ memcpy(buf, result.data, result.length);
body_buf = buf;
}
void sendBodyTooLargeError();
void sendPreconditionFailedError();
+ void sendNotModified();
+ void sendNotModifiedOrPreconditionFailedError();
StoreEntry *old_entry;
store_client *old_sc; /* ... for entry to be validated */
#include "HttpReply.h"
#include "HttpRequest.h"
#include "ip/QosConfig.h"
+#include "log/Tokens.h"
#include "MemObject.h"
#include "ProtoPort.h"
#include "Store.h"
#include "SquidTime.h"
#include "wordlist.h"
#include "err_detail_type.h"
+#if USE_SSL
+#include "ssl/support.h"
+#endif
#if LINGERING_CLOSE
s.clean();
}
- /**
- \todo --enable-useragent-log and --enable-referer-log. We should
- probably drop those two as the custom log formats accomplish pretty much the same thing..
- */
-#if USE_USERAGENT_LOG
- if ((str = req_hdr->getStr(HDR_USER_AGENT)))
- logUserAgent(fqdnFromAddr(http->getConn()->log_addr), str);
-
-#endif
-#if USE_REFERER_LOG
-
- if ((str = req_hdr->getStr(HDR_REFERER)))
- logReferer(fqdnFromAddr(http->getConn()->log_addr), str, http->log_uri);
-
-#endif
#if USE_FORW_VIA_DB
if (req_hdr->has(HDR_X_FORWARDED_FOR)) {
{
clearAdaptation(virginHeadSource);
assert(!adaptedBodySource);
- handleAdaptationFailure(ERR_DETAIL_ICAP_REQMOD_ABORT, !final);
+ handleAdaptationFailure(ERR_DETAIL_CLT_REQMOD_ABORT, !final);
}
void
{
assert(!virginHeadSource);
stopConsumingFrom(adaptedBodySource);
- handleAdaptationFailure(ERR_DETAIL_ICAP_RESPMOD_CLT_SIDE_BODY);
+
+ debugs(85,3, HERE << "REQMOD body production failed");
+ if (request_satisfaction_mode) { // too late to recover or serve an error
+ request->detailError(ERR_ICAP_FAILURE, ERR_DETAIL_CLT_REQMOD_RESP_BODY);
+ const int fd = getConn()->fd;
+ Must(fd >= 0);
+ comm_close(fd); // drastic, but we may be writing a response already
+ } else {
+ handleAdaptationFailure(ERR_DETAIL_CLT_REQMOD_REQ_BODY);
+ }
}
void
#include "comm/AcceptLimiter.h"
#include "comm/comm_internal.h"
#include "comm/IoCallback.h"
+#include "comm/Loops.h"
#include "comm/Write.h"
-#include "comm/ListenStateData.h"
+#include "comm/TcpAcceptor.h"
#include "CommIO.h"
#include "CommRead.h"
#include "ConnectionDetail.h"
#include "ip/QosConfig.h"
#include "ip/tools.h"
#include "ClientInfo.h"
+#if USE_SSL
+#include "ssl/support.h"
+#endif
#include "cbdata.h"
-#if defined(_SQUID_CYGWIN_)
+#if _SQUID_CYGWIN_
#include <sys/ioctl.h>
#endif
#ifdef HAVE_NETINET_TCP_H
bool
isOpen(const int fd)
{
- return fd_table[fd].flags.open != 0;
+ return fd >= 0 && fd_table[fd].flags.open != 0;
}
/**
}
/* Nope, register for some more IO */
- commSetSelect(fd, COMM_SELECT_READ, commHandleRead, data, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, commHandleRead, data, 0);
}
/**
/* Queue the read */
ccb->setCallback(Comm::IOCB_READ, callback, (char *)buf, NULL, size);
- commSetSelect(fd, COMM_SELECT_READ, commHandleRead, ccb, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, commHandleRead, ccb, 0);
}
/**
cb->cancel("old comm_read_cancel");
/* And the IO event */
- commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
}
void
cb->cancel("comm_read_cancel");
/* And the IO event */
- commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
}
F->local_addr.FreeAddrInfo(AI);
return 0;
}
- commResetSelect(fd);
+ Comm::ResetSelect(fd);
close(fd2);
case COMM_INPROGRESS:
debugs(5, 5, HERE << "FD " << fd << ": COMM_INPROGRESS");
- commSetSelect(fd, COMM_SELECT_WRITE, ConnectStateData::Connect, this, 0);
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, ConnectStateData::Connect, this, 0);
break;
case COMM_OK:
fd_note(fd, "lingering close");
commSetTimeout(fd, 10, commLingerTimeout, NULL);
- commSetSelect(fd, COMM_SELECT_READ, commLingerClose, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, commLingerClose, NULL, 0);
}
#endif
// notify read/write handlers after canceling select reservations, if any
if (COMMIO_FD_WRITECB(fd)->active()) {
- commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
COMMIO_FD_WRITECB(fd)->finish(COMM_ERR_CLOSING, errno);
}
if (COMMIO_FD_READCB(fd)->active()) {
- commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
COMMIO_FD_READCB(fd)->finish(COMM_ERR_CLOSING, errno);
}
debugs(5, 5, "comm_remove_close_handler: FD " << fd << ", handler=" <<
handler << ", data=" << data);
- AsyncCall::Pointer p;
- for (p = fd_table[fd].closeHandler; p != NULL; p = p->Next()) {
+ AsyncCall::Pointer p, prev = NULL;
+ for (p = fd_table[fd].closeHandler; p != NULL; prev = p, p = p->Next()) {
typedef CommCbFunPtrCallT<CommCloseCbPtrFun> Call;
const Call *call = dynamic_cast<const Call*>(p.getRaw());
if (!call) // method callbacks have their own comm_remove_close_handler
}
// comm_close removes all close handlers so our handler may be gone
- if (p != NULL)
+ if (p != NULL) {
+ p->dequeue(fd_table[fd].closeHandler, prev);
p->cancel("comm_remove_close_handler");
- // TODO: should we remove the handler from the close handlers list?
+ }
}
// remove method-based close handler
debugs(5, 5, "comm_remove_close_handler: FD " << fd << ", AsyncCall=" << call);
// comm_close removes all close handlers so our handler may be gone
- // TODO: should we remove the handler from the close handlers list?
-#if 0
- // Check to see if really exist the given AsyncCall in comm_close handlers
- // TODO: optimize: this slow code is only needed for the assert() below
- AsyncCall::Pointer p;
- for (p = fd_table[fd].closeHandler; p != NULL && p != call; p = p->Next());
- assert(p == call);
-#endif
+ AsyncCall::Pointer p, prev = NULL;
+ for (p = fd_table[fd].closeHandler; p != NULL && p != call; prev = p, p = p->Next());
+ if (p != NULL)
+ p->dequeue(fd_table[fd].closeHandler, prev);
call->cancel("comm_remove_close_handler");
}
int flags;
int dummy = 0;
#endif
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
int nonblocking = TRUE;
-#ifdef _SQUID_CYGWIN_
-
+#if _SQUID_CYGWIN_
if (fd_table[fd].type != FD_PIPE) {
#endif
return COMM_ERROR;
}
-#ifdef _SQUID_CYGWIN_
-
+#if _SQUID_CYGWIN_
} else {
#endif
#endif
}
#endif
-#ifdef _SQUID_CYGWIN_
-
+#if _SQUID_CYGWIN_
}
-
#endif
fd_table[fd].flags.nonblocking = 1;
conn_close_pool = memPoolCreate("close_handler", sizeof(close_handler));
TheHalfClosed = new DescriptorSet;
+
+ /* setup the select loop module */
+ Comm::SelectLoopInit();
}
void
!fd_table[head].closing()) {
// wait for the head descriptor to become ready for writing
- commSetSelect(head, COMM_SELECT_WRITE, Comm::HandleWrite, ccb, 0);
+ Comm::SetSelect(head, COMM_SELECT_WRITE, Comm::HandleWrite, ccb, 0);
clientInfo->selectWaiting = true;
return;
}
if (writeTimedOut(fd)) {
// We have an active write callback and we are timed out
debugs(5, 5, "checkTimeouts: FD " << fd << " auto write timeout");
- commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
COMMIO_FD_WRITECB(fd)->finish(COMM_ERROR, ETIMEDOUT);
} else if (AlreadyTimedOut(F))
continue;
fd_open(DoneFD, FD_PIPE, "async-io completetion event: threads");
commSetNonBlocking(DoneReadFD);
commSetNonBlocking(DoneFD);
- commSetSelect(DoneReadFD, COMM_SELECT_READ, NULLFDHandler, NULL, 0);
+ Comm::SetSelect(DoneReadFD, COMM_SELECT_READ, NULLFDHandler, NULL, 0);
Initialised = true;
}
CommIO::NULLFDHandler(int fd, void *data)
{
FlushPipe();
- commSetSelect(fd, COMM_SELECT_READ, NULLFDHandler, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, NULLFDHandler, NULL, 0);
}
void
checkTimeouts();
}
- switch (comm_select(timeout)) {
+ switch (Comm::DoSelect(timeout)) {
case COMM_OK:
SQUIDCEXTERN int comm_openex(int, int, Ip::Address &, int, tos_t tos, nfmark_t nfmark, const char *);
SQUIDCEXTERN u_short comm_local_port(int fd);
-SQUIDCEXTERN void commSetSelect(int, unsigned int, PF *, void *, time_t);
-SQUIDCEXTERN void commResetSelect(int);
-
SQUIDCEXTERN int comm_udp_sendto(int sock, const Ip::Address &to, const void *buf, int buflen);
SQUIDCEXTERN void commCallCloseHandlers(int fd);
SQUIDCEXTERN int commSetTimeout(int fd, int, PF *, void *);
SQUIDCEXTERN void checkTimeouts(void);
-/*
- * comm_select.c
- */
-SQUIDCEXTERN void comm_select_init(void);
-SQUIDCEXTERN comm_err_t comm_select(int);
-SQUIDCEXTERN void comm_quick_poll_required(void);
-
class ConnectionDetail;
typedef void IOACB(int fd, int nfd, ConnectionDetail *details, comm_err_t flag, int xerrno, void *data);
extern void comm_add_close_handler(int fd, PF *, void *);
#include "config.h"
#include "comm/AcceptLimiter.h"
-#include "comm/ListenStateData.h"
+#include "comm/TcpAcceptor.h"
#include "fde.h"
Comm::AcceptLimiter Comm::AcceptLimiter::Instance_;
}
void
-Comm::AcceptLimiter::defer(Comm::ListenStateData *afd)
+Comm::AcceptLimiter::defer(Comm::TcpAcceptor *afd)
{
afd->isLimited++;
debugs(5, 5, HERE << "FD " << afd->fd << " x" << afd->isLimited);
deferred.push_back(afd);
}
+void
+Comm::AcceptLimiter::removeDead(const Comm::TcpAcceptor *afd)
+{
+ for (unsigned int i = 0; i < deferred.size() && afd->isLimited > 0; i++) {
+ if (deferred[i] == afd) {
+ deferred[i]->isLimited--;
+ deferred[i] = NULL; // fast. kick() will skip empty entries later.
+ debugs(5, 5, HERE << "FD " << afd->fd << " x" << afd->isLimited);
+ }
+ }
+}
+
void
Comm::AcceptLimiter::kick()
{
+ // TODO: this could be optimized further with an iterator to search
+ // looking for first non-NULL, followed by dumping the first N
+ // with only one shift()/pop_front operation
+
debugs(5, 5, HERE << " size=" << deferred.size());
- if (deferred.size() > 0 && fdNFree() >= RESERVED_FD) {
- debugs(5, 5, HERE << " doing one.");
+ while (deferred.size() > 0 && fdNFree() >= RESERVED_FD) {
/* NP: shift() is equivalent to pop_front(). Giving us a FIFO queue. */
- ListenStateData *temp = deferred.shift();
- temp->isLimited--;
- temp->acceptNext();
+ TcpAcceptor *temp = deferred.shift();
+ if (temp != NULL) {
+ debugs(5, 5, HERE << " doing one.");
+ temp->isLimited--;
+ temp->acceptNext();
+ break;
+ }
}
}
namespace Comm
{
-class ListenStateData;
+class TcpAcceptor;
/**
* FIFO Queue holding listener socket handlers which have been activated
static AcceptLimiter &Instance();
/** delay accepting a new client connection. */
- void defer(Comm::ListenStateData *afd);
+ void defer(Comm::TcpAcceptor *afd);
+
+ /** remove all records of an acceptor. Only to be called by the ConnAcceptor::swanSong() */
+ void removeDead(const Comm::TcpAcceptor *afd);
/** try to accept and begin processing any delayed client connections. */
void kick();
static AcceptLimiter Instance_;
/** FIFO queue */
- Vector<Comm::ListenStateData*> deferred;
+ Vector<Comm::TcpAcceptor*> deferred;
};
}; // namepace Comm
#include "config.h"
#include "ClientInfo.h"
#include "comm/IoCallback.h"
+#include "comm/Loops.h"
#include "comm/Write.h"
#include "CommCalls.h"
#include "fde.h"
}
#endif
- commSetSelect(fd, COMM_SELECT_WRITE, Comm::HandleWrite, this, 0);
+ SetSelect(fd, COMM_SELECT_WRITE, Comm::HandleWrite, this, 0);
}
void
#ifndef _SQUID_COMM_IOCALLBACK_H
#define _SQUID_COMM_IOCALLBACK_H
-#include "config.h"
#include "base/AsyncCall.h"
#include "comm_err_t.h"
+++ /dev/null
-#ifndef SQUID_LISTENERSTATEDATA_H
-#define SQUID_LISTENERSTATEDATA_H
-
-#include "base/AsyncCall.h"
-#include "comm.h"
-#if HAVE_MAP
-#include <map>
-#endif
-
-class ConnectionDetail;
-
-namespace Comm
-{
-
-class ListenStateData
-{
-
-public:
- ListenStateData(int fd, AsyncCall::Pointer &call, bool accept_many);
- ListenStateData(const ListenStateData &r); // not implemented.
- ~ListenStateData();
-
- void subscribe(AsyncCall::Pointer &call);
- void acceptNext();
- void notify(int newfd, comm_err_t flag, const ConnectionDetail &details);
-
- int fd;
-
- /// errno code of the last accept() or listen() action if one occurred.
- int errcode;
-
- /// whether this socket is delayed and on the AcceptLimiter queue.
- int32_t isLimited;
-
-private:
- /// Method to test if there are enough file escriptors to open a new client connection
- /// if not the accept() will be postponed
- static bool okToAccept();
-
- /// Method callback for whenever an FD is ready to accept a client connection.
- static void doAccept(int fd, void *data);
-
- void acceptOne();
- int oldAccept(ConnectionDetail &details);
-
- AsyncCall::Pointer theCallback;
- bool mayAcceptMore;
-
- void setListen();
-};
-
-} // namespace Comm
-
-#endif /* SQUID_LISTENERSTATEDATA_H */
--- /dev/null
+#ifndef _SQUID_SRC_COMM_LOOPS_H
+#define _SQUID_SRC_COMM_LOOPS_H
+
+#include "comm_err_t.h"
+
+/* Comm layer select loops API.
+ *
+ * These API functions must be implemented by all FD IO loops used by Squid.
+ * Defines are provided short-term for legacy code. These will disappear soon.
+ */
+
+namespace Comm
+{
+
+/// Initialize the module on Squid startup
+extern void SelectLoopInit(void);
+
+/// Mark an FD to be watched for its IO status.
+extern void SetSelect(int, unsigned int, PF *, void *, time_t);
+
+/// reset/undo/unregister the watch for an FD which was set by Comm::SetSelect()
+extern void ResetSelect(int);
+
+/** Perform a select() or equivalent call.
+ * This is used by the main select loop engine to check for FD with IO available.
+ */
+extern comm_err_t DoSelect(int);
+
+extern void QuickPollRequired(void);
+
+} // namespace Comm
+
+#endif /* _SQUID_SRC_COMM_LOOPS_H */
libcomm_la_SOURCES= \
AcceptLimiter.cc \
AcceptLimiter.h \
- ListenStateData.cc \
- ListenStateData.h \
+ Loops.h \
+ ModDevPoll.cc \
+ ModEpoll.cc \
+ ModKqueue.cc \
+ ModPoll.cc \
+ ModSelect.cc \
+ ModSelectWin32.cc \
+ TcpAcceptor.cc \
+ TcpAcceptor.h \
\
IoCallback.cc \
IoCallback.h \
* Last modified 2010-10-08
*/
-
-#include "squid.h"
-
/*
* There are several poll types in Squid, ALL of which are compiled and linked
* in. Thus conditional compile-time flags are used to prevent the different
* modules from creating several versions of the same function simultaneously.
*/
+#include "config.h"
+
#if USE_DEVPOLL
-#include "Store.h"
+#include "squid.h"
+#include "comm/Loops.h"
#include "fde.h"
#include "mgr/Registration.h"
#include "SquidTime.h"
+#include "Store.h"
#if HAVE_SYS_DEVPOLL_H
/* Solaris /dev/poll support, see "man -s 7D poll" */
* Allocates memory, opens /dev/poll device handle.
*/
void
-comm_select_init(void)
+Comm::SelectLoopInit(void)
{
/* allocate memory first before attempting to open poll device */
/* This tracks the FD devpoll offset+state */
* @param timeout if non-zero then timeout relative to now
*/
void
-commSetSelect(int fd, unsigned int type, PF * handler,
- void *client_data, time_t timeout)
+Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
{
assert(fd >= 0);
debugs(
* @param fd file descriptor to clear polling on
*/
void
-commResetSelect(int fd)
+Comm::ResetSelect(int fd)
{
- commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
- commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+ SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
+ SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
}
* @param msec milliseconds to poll for (limited by max_poll_time)
*/
comm_err_t
-comm_select(int msec)
+Comm::DoSelect(int msec)
{
int num, i;
fde *F;
HERE << "no read handler for FD " << fd
);
// remove interest since no handler exist for this event.
- commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+ SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
}
}
HERE << "no write handler for FD " << fd
);
// remove interest since no handler exist for this event.
- commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
+ SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
}
}
}
return COMM_OK;
}
-
void
-comm_quick_poll_required(void)
+Comm::QuickPollRequired(void)
{
max_poll_time = 10;
}
*
*/
+#include "config.h"
+
+#if USE_EPOLL
+
#include "squid.h"
-#include "comm_epoll.h"
-#include "mgr/Registration.h"
-#include "Store.h"
+#include "comm/Loops.h"
#include "fde.h"
+#include "mgr/Registration.h"
#include "SquidTime.h"
-
-#if USE_EPOLL
+#include "Store.h"
#define DEBUG_EPOLL 0
/*
- * comm_select_init
- *
* This is a needed exported function which will be called to initialise
* the network loop code.
*/
void
-comm_select_init(void)
+Comm::SelectLoopInit(void)
{
-
pevents = (struct epoll_event *) xmalloc(SQUID_MAXFD * sizeof(struct epoll_event));
if (!pevents) {
}
}
-/*
- * comm_setselect
- *
+/**
* This is a needed exported function which will be called to register
* and deregister interest in a pending IO state for a given FD.
- *
*/
void
-commSetSelect(int fd, unsigned int type, PF * handler,
- void *client_data, time_t timeout)
+Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
{
fde *F = &fd_table[fd];
int epoll_ctl_type = 0;
struct epoll_event ev;
assert(fd >= 0);
- debugs(5, DEBUG_EPOLL ? 0 : 8, "commSetSelect(FD " << fd << ",type=" << type <<
- ",handler=" << handler << ",client_data=" << client_data <<
- ",timeout=" << timeout << ")");
+ debugs(5, DEBUG_EPOLL ? 0 : 8, HERE << "FD " << fd << ", type=" << type <<
+ ", handler=" << handler << ", client_data=" << client_data <<
+ ", timeout=" << timeout);
if (RUNNING_ON_VALGRIND) {
/* Keep valgrind happy.. complains about uninitialized bytes otherwise */
F->epoll_state = ev.events;
if (epoll_ctl(kdpfd, epoll_ctl_type, fd, &ev) < 0) {
- debugs(5, DEBUG_EPOLL ? 0 : 8, "commSetSelect: epoll_ctl(," << epolltype_atoi(epoll_ctl_type) <<
+ debugs(5, DEBUG_EPOLL ? 0 : 8, HERE << "epoll_ctl(," << epolltype_atoi(epoll_ctl_type) <<
",,): failed on FD " << fd << ": " << xstrerror());
}
}
}
void
-commResetSelect(int fd)
+Comm::ResetSelect(int fd)
{
fde *F = &fd_table[fd];
F->epoll_state = 0;
- commSetSelect(fd, 0, NULL, NULL, 0);
+ SetSelect(fd, 0, NULL, NULL, 0);
}
statHistDump(&f->select_fds_hist, sentry, statHistIntDumper);
}
-/*
- * comm_select
+/**
* Check all connections for new connections and input data that is to be
* processed. Also check for connections with data queued and whether we can
* write it out.
* comm_setselect and fd_table[] and calls callbacks for IO ready
* events.
*/
-
comm_err_t
-comm_select(int msec)
+Comm::DoSelect(int msec)
{
int num, i,fd;
fde *F;
for (i = 0, cevents = pevents; i < num; i++, cevents++) {
fd = cevents->data.fd;
F = &fd_table[fd];
- debugs(5, DEBUG_EPOLL ? 0 : 8, "comm_select(): got FD " << fd << " events=" <<
+ debugs(5, DEBUG_EPOLL ? 0 : 8, HERE << "got FD " << fd << " events=" <<
std::hex << cevents->events << " monitoring=" << F->epoll_state <<
" F->read_handler=" << F->read_handler << " F->write_handler=" << F->write_handler);
if (cevents->events & (EPOLLIN|EPOLLHUP|EPOLLERR) || F->flags.read_pending) {
if ((hdl = F->read_handler) != NULL) {
- debugs(5, DEBUG_EPOLL ? 0 : 8, "comm_select(): Calling read handler on FD " << fd);
+ debugs(5, DEBUG_EPOLL ? 0 : 8, HERE << "Calling read handler on FD " << fd);
PROF_start(comm_write_handler);
F->flags.read_pending = 0;
F->read_handler = NULL;
PROF_stop(comm_write_handler);
statCounter.select_fds++;
} else {
- debugs(5, DEBUG_EPOLL ? 0 : 8, "comm_select(): no read handler for FD " << fd);
+ debugs(5, DEBUG_EPOLL ? 0 : 8, HERE << "no read handler for FD " << fd);
// remove interest since no handler exist for this event.
- commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+ SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
}
}
if (cevents->events & (EPOLLOUT|EPOLLHUP|EPOLLERR)) {
if ((hdl = F->write_handler) != NULL) {
- debugs(5, DEBUG_EPOLL ? 0 : 8, "comm_select(): Calling write handler on FD " << fd);
+ debugs(5, DEBUG_EPOLL ? 0 : 8, HERE << "Calling write handler on FD " << fd);
PROF_start(comm_read_handler);
F->write_handler = NULL;
hdl(fd, F->write_data);
PROF_stop(comm_read_handler);
statCounter.select_fds++;
} else {
- debugs(5, DEBUG_EPOLL ? 0 : 8, "comm_select(): no write handler for FD " << fd);
+ debugs(5, DEBUG_EPOLL ? 0 : 8, HERE << "no write handler for FD " << fd);
// remove interest since no handler exist for this event.
- commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
+ SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
}
}
}
}
void
-comm_quick_poll_required(void)
+Comm::QuickPollRequired(void)
{
max_poll_time = 10;
}
* so deferred reads aren't required.
* -- adrian
*/
-
-#include "squid.h"
+#include "config.h"
#if USE_KQUEUE
-#include "comm_kqueue.h"
-#include "Store.h"
+#include "squid.h"
+#include "comm/Loops.h"
#include "fde.h"
+#include "Store.h"
#include "SquidTime.h"
#if HAVE_SYS_EVENT_H
* the network loop code.
*/
void
-comm_select_init(void)
+Comm::SelectLoopInit(void)
{
kq = kqueue();
* and deregister interest in a pending IO state for a given FD.
*/
void
-commSetSelect(int fd, unsigned int type, PF * handler,
- void *client_data, time_t timeout)
+Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
{
fde *F = &fd_table[fd];
assert(fd >= 0);
}
void
-commResetSelect(int fd)
+Comm::ResetSelect(int fd)
{
fde *F = &fd_table[fd];
if (F->read_handler) {
*/
comm_err_t
-comm_select(int msec)
+Comm::DoSelect(int msec)
{
int num, i;
}
void
-comm_quick_poll_required(void)
+Comm::QuickPollRequired(void)
{
max_poll_time = 10;
}
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
+#include "config.h"
+
+#if USE_POLL
#include "squid.h"
-#include "comm_poll.h"
+#include "comm/Loops.h"
+#include "fde.h"
#include "mgr/Registration.h"
#include "SquidTime.h"
#include "Store.h"
-#include "fde.h"
-
-#if USE_POLL
#if HAVE_POLL_H
#include <poll.h>
#endif
#endif
-static int MAX_POLL_TIME = 1000; /* see also comm_quick_poll_required() */
+static int MAX_POLL_TIME = 1000; /* see also Comm::QuickPollRequired() */
#ifndef howmany
#define howmany(x, y) (((x)+((y)-1))/(y))
void
-commSetSelect(int fd, unsigned int type, PF * handler, void *client_data,
- time_t timeout)
+Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
{
fde *F = &fd_table[fd];
assert(fd >= 0);
}
void
-commResetSelect(int fd)
+Comm::ResetSelect(int fd)
{
}
/* poll all sockets; call handlers for those that are ready. */
comm_err_t
-comm_select(int msec)
+Comm::DoSelect(int msec)
{
-
struct pollfd pfds[SQUID_MAXFD];
PF *hdl = NULL;
}
void
-comm_select_init(void)
+Comm::SelectLoopInit(void)
{
commPollRegisterWithCacheManager();
}
/* Called by async-io or diskd to speed up the polling */
void
-comm_quick_poll_required(void)
+Comm::QuickPollRequired(void)
{
MAX_POLL_TIME = 10;
}
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
+#include "config.h"
+
+#if USE_SELECT
#include "squid.h"
-#include "comm_select.h"
+#include "comm/Loops.h"
#include "mgr/Registration.h"
#include "SquidTime.h"
-
-#if USE_SELECT
#include "Store.h"
#include "fde.h"
-static int MAX_POLL_TIME = 1000; /* see also comm_quick_poll_required() */
+static int MAX_POLL_TIME = 1000; /* see also Comm::QuickPollRequired() */
#ifndef howmany
#define howmany(x, y) (((x)+((y)-1))/(y))
#define commCheckHTTPIncoming (++http_io_events > (incoming_http_interval>> INCOMING_FACTOR))
void
-commSetSelect(int fd, unsigned int type, PF * handler, void *client_data,
- time_t timeout)
+Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
{
fde *F = &fd_table[fd];
assert(fd >= 0);
assert(F->flags.open);
- debugs(5, 5, "commSetSelect: FD " << fd << " type " << type);
+ debugs(5, 5, HERE << "FD " << fd << " type " << type);
if (type & COMM_SELECT_READ) {
F->read_handler = handler;
}
void
-commResetSelect(int fd)
+Comm::ResetSelect(int fd)
{
}
#define DEBUG_FDBITS 0
/* Select on all sockets; call handlers for those that are ready. */
comm_err_t
-comm_select(int msec)
+Comm::DoSelect(int msec)
{
fd_set readfds;
fd_set pendingfds;
maxfd = Biggest_FD + 1;
- xmemcpy(&readfds, &global_readfds,
- howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES);
+ memcpy(&readfds, &global_readfds,
+ howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES);
- xmemcpy(&writefds, &global_writefds,
- howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES);
+ memcpy(&writefds, &global_writefds,
+ howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES);
/* remove stalled FDs, and deal with pending descriptors */
pending = 0;
statHistCount(&statCounter.comm_dns_incoming, nevents);
}
-static void
-commSelectRegisterWithCacheManager(void)
-{
- Mgr::RegisterAction("comm_select_incoming",
- "comm_incoming() stats",
- commIncomingStats, 0, 1);
-}
-
void
-comm_select_init(void)
+Comm::SelectLoopInit(void)
{
zero_tv.tv_sec = 0;
zero_tv.tv_usec = 0;
FD_ZERO(&global_writefds);
nreadfds = nwritefds = 0;
- commSelectRegisterWithCacheManager();
+ Mgr::RegisterAction("comm_select_incoming",
+ "comm_incoming() stats",
+ commIncomingStats, 0, 1);
}
/*
/* Called by async-io or diskd to speed up the polling */
void
-comm_quick_poll_required(void)
+Comm::QuickPollRequired(void)
{
MAX_POLL_TIME = 10;
}
*
*/
+#include "config.h"
+
+#if USE_SELECT_WIN32
+
#include "squid.h"
-#include "comm_select.h"
+#include "comm/Loops.h"
+#include "fde.h"
#include "mgr/Registration.h"
#include "SquidTime.h"
-
-#if USE_SELECT_WIN32
#include "Store.h"
-#include "fde.h"
-static int MAX_POLL_TIME = 1000; /* see also comm_quick_poll_required() */
+static int MAX_POLL_TIME = 1000; /* see also Comm::QuickPollRequired() */
#ifndef howmany
#define howmany(x, y) (((x)+((y)-1))/(y))
#define commCheckHTTPIncoming (++http_io_events > (incoming_http_interval>> INCOMING_FACTOR))
void
-commSetSelect(int fd, unsigned int type, PF * handler, void *client_data,
- time_t timeout)
+Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
{
fde *F = &fd_table[fd];
assert(fd >= 0);
}
void
-commResetSelect(int fd)
+Comm::ResetSelect(int fd)
{
}
#define DEBUG_FDBITS 0
/* Select on all sockets; call handlers for those that are ready. */
comm_err_t
-comm_select(int msec)
+Comm::DoSelect(int msec)
{
fd_set readfds;
fd_set pendingfds;
maxfd = Biggest_FD + 1;
- xmemcpy(&readfds, &global_readfds, sizeof(global_readfds));
+ memcpy(&readfds, &global_readfds, sizeof(global_readfds));
- xmemcpy(&writefds, &global_writefds, sizeof(global_writefds));
+ memcpy(&writefds, &global_writefds, sizeof(global_writefds));
- xmemcpy(&errfds, &global_writefds, sizeof(global_writefds));
+ memcpy(&errfds, &global_writefds, sizeof(global_writefds));
/* remove stalled FDs, and deal with pending descriptors */
pending = 0;
statHistCount(&statCounter.comm_dns_incoming, nevents);
}
-static void
-commSelectRegisterWithCacheManager(void)
-{
- Mgr::RegisterAction("comm_select_incoming",
- "comm_incoming() stats",
- commIncomingStats, 0, 1);
-}
-
void
-comm_select_init(void)
+Comm::SelectLoopInit(void)
{
zero_tv.tv_sec = 0;
zero_tv.tv_usec = 0;
FD_ZERO(&global_writefds);
nreadfds = nwritefds = 0;
- commSelectRegisterWithCacheManager();
+ Mgr::RegisterAction("comm_select_incoming",
+ "comm_incoming() stats",
+ commIncomingStats, 0, 1);
}
/*
/* Called by async-io or diskd to speed up the polling */
void
-comm_quick_poll_required(void)
+Comm::QuickPollRequired(void)
{
MAX_POLL_TIME = 10;
}
*/
#include "squid.h"
+#include "base/TextException.h"
#include "CommCalls.h"
#include "comm/AcceptLimiter.h"
#include "comm/comm_internal.h"
-#include "comm/ListenStateData.h"
+#include "comm/Loops.h"
+#include "comm/TcpAcceptor.h"
#include "ConnectionDetail.h"
#include "fde.h"
#include "protos.h"
#include "SquidTime.h"
+namespace Comm
+{
+CBDATA_CLASS_INIT(TcpAcceptor);
+};
+
+Comm::TcpAcceptor::TcpAcceptor(const int listenFd, const Ip::Address &laddr, int flags,
+ const char *note, const Subscription::Pointer &aSub) :
+ AsyncJob("Comm::TcpAcceptor"),
+ errcode(0),
+ fd(listenFd),
+ isLimited(0),
+ theCallSub(aSub),
+ local_addr(laddr)
+{}
+
+void
+Comm::TcpAcceptor::subscribe(const Subscription::Pointer &aSub)
+{
+ debugs(5, 5, HERE << status() << " AsyncCall Subscription: " << aSub);
+ unsubscribe("subscription change");
+ theCallSub = aSub;
+}
+
+void
+Comm::TcpAcceptor::unsubscribe(const char *reason)
+{
+ debugs(5, 5, HERE << status() << " AsyncCall Subscription " << theCallSub << " removed: " << reason);
+ theCallSub = NULL;
+}
+
+void
+Comm::TcpAcceptor::start()
+{
+ debugs(5, 5, HERE << status() << " AsyncCall Subscription: " << theCallSub);
+
+ Must(isOpen(fd));
+
+ setListen();
+
+ // if no error so far start accepting connections.
+ if (errcode == 0)
+ SetSelect(fd, COMM_SELECT_READ, doAccept, this, 0);
+}
+
+bool
+Comm::TcpAcceptor::doneAll() const
+{
+ // stop when FD is closed
+ if (!isOpen(fd)) {
+ return AsyncJob::doneAll();
+ }
+
+ // stop when handlers are gone
+ if (theCallSub == NULL) {
+ return AsyncJob::doneAll();
+ }
+
+ // open FD with handlers...keep accepting.
+ return false;
+}
+
+void
+Comm::TcpAcceptor::swanSong()
+{
+ debugs(5,5, HERE);
+ unsubscribe("swanSong");
+ fd = -1;
+ AcceptLimiter::Instance().removeDead(this);
+ AsyncJob::swanSong();
+}
+
+const char *
+Comm::TcpAcceptor::status() const
+{
+ static char ipbuf[MAX_IPSTRLEN] = {'\0'};
+ if (ipbuf[0] == '\0')
+ local_addr.ToHostname(ipbuf, MAX_IPSTRLEN);
+
+ static MemBuf buf;
+ buf.reset();
+ buf.Printf(" FD %d, %s",fd, ipbuf);
+
+ const char *jobStatus = AsyncJob::status();
+ buf.append(jobStatus, strlen(jobStatus));
+
+ return buf.content();
+}
+
/**
* New-style listen and accept routines
*
* accept()ed some time later.
*/
void
-Comm::ListenStateData::setListen()
+Comm::TcpAcceptor::setListen()
{
errcode = 0; // reset local errno copy.
if (listen(fd, Squid_MaxFD >> 2) < 0) {
- debugs(50, 0, HERE << "listen(FD " << fd << ", " << (Squid_MaxFD >> 2) << "): " << xstrerror());
+ debugs(50, DBG_CRITICAL, "ERROR: listen(" << status() << ", " << (Squid_MaxFD >> 2) << "): " << xstrerror());
errcode = errno;
return;
}
debugs(5, DBG_IMPORTANT, "Installing accept filter '" << Config.accept_filter << "' on FD " << fd);
xstrncpy(afa.af_name, Config.accept_filter, sizeof(afa.af_name));
if (setsockopt(fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0)
- debugs(5, DBG_CRITICAL, "SO_ACCEPTFILTER '" << Config.accept_filter << "': '" << xstrerror());
+ debugs(5, DBG_CRITICAL, "WARNING: SO_ACCEPTFILTER '" << Config.accept_filter << "': '" << xstrerror());
#elif defined(TCP_DEFER_ACCEPT)
int seconds = 30;
if (strncmp(Config.accept_filter, "data=", 5) == 0)
seconds = atoi(Config.accept_filter + 5);
if (setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &seconds, sizeof(seconds)) < 0)
- debugs(5, DBG_CRITICAL, "TCP_DEFER_ACCEPT '" << Config.accept_filter << "': '" << xstrerror());
+ debugs(5, DBG_CRITICAL, "WARNING: TCP_DEFER_ACCEPT '" << Config.accept_filter << "': '" << xstrerror());
#else
- debugs(5, DBG_CRITICAL, "accept_filter not supported on your OS");
+ debugs(5, DBG_CRITICAL, "WARNING: accept_filter not supported on your OS");
#endif
}
}
-Comm::ListenStateData::ListenStateData(int aFd, AsyncCall::Pointer &call, bool accept_many) :
- fd(aFd),
- theCallback(call),
- mayAcceptMore(accept_many)
-{
- assert(aFd >= 0);
- debugs(5, 5, HERE << "FD " << fd << " AsyncCall: " << call);
- assert(isOpen(aFd));
- setListen();
- commSetSelect(fd, COMM_SELECT_READ, doAccept, this, 0);
-}
-
-Comm::ListenStateData::~ListenStateData()
-{
- comm_close(fd);
- fd = -1;
-}
-
/**
* This private callback is called whenever a filedescriptor is ready
* to dupe itself and fob off an accept()ed connection
* done later when enough sockets become available.
*/
void
-Comm::ListenStateData::doAccept(int fd, void *data)
+Comm::TcpAcceptor::doAccept(int fd, void *data)
{
- debugs(5, 2, HERE << "New connection on FD " << fd);
+ try {
+ debugs(5, 2, HERE << "New connection on FD " << fd);
- assert(isOpen(fd));
- ListenStateData *afd = static_cast<ListenStateData*>(data);
+ Must(isOpen(fd));
+ TcpAcceptor *afd = static_cast<TcpAcceptor*>(data);
+
+ if (!okToAccept()) {
+ AcceptLimiter::Instance().defer(afd);
+ } else {
+ afd->acceptNext();
+ }
+ SetSelect(fd, COMM_SELECT_READ, Comm::TcpAcceptor::doAccept, afd, 0);
- if (!okToAccept()) {
- AcceptLimiter::Instance().defer(afd);
- } else {
- afd->acceptNext();
+ } catch (const std::exception &e) {
+ fatalf("FATAL: error while accepting new client connection: %s\n", e.what());
+ } catch (...) {
+ fatal("FATAL: error while accepting new client connection: [unkown]\n");
}
- commSetSelect(fd, COMM_SELECT_READ, Comm::ListenStateData::doAccept, afd, 0);
}
bool
-Comm::ListenStateData::okToAccept()
+Comm::TcpAcceptor::okToAccept()
{
static time_t last_warn = 0;
}
void
-Comm::ListenStateData::acceptOne()
+Comm::TcpAcceptor::acceptOne()
{
/*
* We don't worry about running low on FDs here. Instead,
*/
/* Accept a new connection */
- ConnectionDetail connDetails;
- int newfd = oldAccept(connDetails);
+ ConnectionDetail newConnDetails;
+ int newFd = -1;
+ const comm_err_t flag = oldAccept(newConnDetails, &newFd);
/* Check for errors */
- if (newfd < 0) {
+ if (!isOpen(newFd)) {
- if (newfd == COMM_NOMESSAGE) {
+ if (flag == COMM_NOMESSAGE) {
/* register interest again */
- debugs(5, 5, HERE << "try later: FD " << fd << " handler: " << theCallback);
- commSetSelect(fd, COMM_SELECT_READ, doAccept, this, 0);
+ debugs(5, 5, HERE << "try later: FD " << fd << " handler Subscription: " << theCallSub);
+ SetSelect(fd, COMM_SELECT_READ, doAccept, this, 0);
return;
}
// A non-recoverable error; notify the caller */
- debugs(5, 5, HERE << "non-recoverable error: FD " << fd << " handler: " << theCallback);
- notify(-1, COMM_ERROR, connDetails);
- mayAcceptMore = false;
+ debugs(5, 5, HERE << "non-recoverable error:" << status() << " handler Subscription: " << theCallSub);
+ notify(flag, newConnDetails, newFd);
+ mustStop("Listener socket closed");
return;
}
- debugs(5, 5, HERE << "accepted: FD " << fd <<
- " newfd: " << newfd << " from: " << connDetails.peer <<
- " handler: " << theCallback);
- notify(newfd, COMM_OK, connDetails);
+ debugs(5, 5, HERE << "Listener: FD " << fd <<
+ " accepted new connection from " << newConnDetails.peer <<
+ " handler Subscription: " << theCallSub);
+ notify(flag, newConnDetails, newFd);
}
void
-Comm::ListenStateData::acceptNext()
+Comm::TcpAcceptor::acceptNext()
{
- assert(isOpen(fd));
+ Must(isOpen(fd));
debugs(5, 2, HERE << "connection on FD " << fd);
acceptOne();
}
+// XXX: obsolete comment?
+// NP: can't be a const function because syncWithComm() side effects hit theCallSub->callback().
void
-Comm::ListenStateData::notify(int newfd, comm_err_t flag, const ConnectionDetail &connDetails)
+Comm::TcpAcceptor::notify(const comm_err_t flag, const ConnectionDetail &connDetails, int newFd) const
{
// listener socket handlers just abandon the port with COMM_ERR_CLOSING
// it should only happen when this object is deleted...
return;
}
- if (theCallback != NULL) {
- typedef CommAcceptCbParams Params;
- Params ¶ms = GetCommParams<Params>(theCallback);
+ if (theCallSub != NULL) {
+ AsyncCall::Pointer call = theCallSub->callback();
+ CommAcceptCbParams ¶ms = GetCommParams<CommAcceptCbParams>(call);
params.fd = fd;
- params.nfd = newfd;
+ params.nfd = newFd;
params.details = connDetails;
params.flag = flag;
params.xerrno = errcode;
- ScheduleCallHere(theCallback);
- if (!mayAcceptMore)
- theCallback = NULL;
+ ScheduleCallHere(call);
}
}
/**
* accept() and process
- * Wait for an incoming connection on FD.
+ * Wait for an incoming connection on our listener socket.
+ *
+ * \retval COMM_OK success. details parameter filled.
+ * \retval COMM_NOMESSAGE attempted accept() but nothing useful came in.
+ * \retval COMM_ERROR an outright failure occured.
+ * Or if this client has too many connections already.
*/
-int
-Comm::ListenStateData::oldAccept(ConnectionDetail &details)
+comm_err_t
+Comm::TcpAcceptor::oldAccept(ConnectionDetail &details, int *newFd)
{
PROF_start(comm_accept);
statCounter.syscalls.sock.accepts++;
PROF_stop(comm_accept);
if (ignoreErrno(errno)) {
- debugs(50, 5, HERE << "FD " << fd << ": " << xstrerror());
+ debugs(50, 5, HERE << status() << ": " << xstrerror());
return COMM_NOMESSAGE;
} else if (ENFILE == errno || EMFILE == errno) {
- debugs(50, 3, HERE << "FD " << fd << ": " << xstrerror());
+ debugs(50, 3, HERE << status() << ": " << xstrerror());
return COMM_ERROR;
} else {
- debugs(50, 1, HERE << "FD " << fd << ": " << xstrerror());
+ debugs(50, 1, HERE << status() << ": " << xstrerror());
return COMM_ERROR;
}
}
+ Must(sock >= 0);
+ *newFd = sock;
details.peer = *gai;
if ( Config.client_ip_max_connections >= 0) {
}
}
+ // lookup the local-end details of this new connection
details.me.InitAddrInfo(gai);
-
details.me.SetEmpty();
getsockname(sock, gai->ai_addr, &gai->ai_addrlen);
details.me = *gai;
-
- commSetCloseOnExec(sock);
+ details.me.FreeAddrInfo(gai);
/* fdstat update */
+ // XXX : these are not all HTTP requests. use a note about type and ip:port details->
+ // so we end up with a uniform "(HTTP|FTP-data|HTTPS|...) remote-ip:remote-port"
fd_open(sock, FD_SOCKET, "HTTP Request");
fdd_table[sock].close_file = NULL;
fde *F = &fd_table[sock];
details.peer.NtoA(F->ipaddr,MAX_IPSTRLEN);
F->remote_port = details.peer.GetPort();
- F->local_addr.SetPort(details.me.GetPort());
+ F->local_addr = details.me;
F->sock_family = details.me.IsIPv6()?AF_INET6:AF_INET;
- details.me.FreeAddrInfo(gai);
+ // set socket flags
+ commSetCloseOnExec(sock);
commSetNonBlocking(sock);
/* IFF the socket is (tproxy) transparent, pass the flag down to allow spoofing */
F->flags.transparent = fd_table[fd].flags.transparent;
PROF_stop(comm_accept);
- return sock;
+ return COMM_OK;
}
--- /dev/null
+#ifndef SQUID_COMM_TCPACCEPTOR_H
+#define SQUID_COMM_TCPACCEPTOR_H
+
+#include "base/AsyncCall.h"
+#include "base/Subscription.h"
+#include "CommCalls.h"
+#include "comm_err_t.h"
+#include "comm/TcpAcceptor.h"
+#include "ip/Address.h"
+
+#if HAVE_MAP
+#include <map>
+#endif
+
+namespace Comm
+{
+
+class AcceptLimiter;
+
+/**
+ * Listens on an FD for new incoming connections and
+ * emits an active FD descriptor for the new client.
+ *
+ * Handles all event limiting required to quash inbound connection
+ * floods within the global FD limits of available Squid_MaxFD and
+ * client_ip_max_connections.
+ *
+ * Fills the emitted connection with all connection details able to
+ * be looked up. Currently these are the local/remote IP:port details
+ * and the listening socket transparent-mode flag.
+ */
+class TcpAcceptor : public AsyncJob
+{
+private:
+ virtual void start();
+ virtual bool doneAll() const;
+ virtual void swanSong();
+ virtual const char *status() const;
+
+ TcpAcceptor(const TcpAcceptor &); // not implemented.
+
+public:
+ TcpAcceptor(const int listenFd, const Ip::Address &laddr, int flags,
+ const char *note, const Subscription::Pointer &aSub);
+
+ /** Subscribe a handler to receive calls back about new connections.
+ * Unsubscribes any existing subscribed handler.
+ */
+ void subscribe(const Subscription::Pointer &aSub);
+
+ /** Remove the currently waiting callback subscription.
+ * Already scheduled callbacks remain scheduled.
+ */
+ void unsubscribe(const char *reason);
+
+ /** Try and accept another connection (synchronous).
+ * If one is pending already the subscribed callback handler will be scheduled
+ * to handle it before this method returns.
+ */
+ void acceptNext();
+
+ /// Call the subscribed callback handler with details about a new connection.
+ void notify(const comm_err_t flags, const ConnectionDetail &newConnDetails, const int newFd) const;
+
+ /// errno code of the last accept() or listen() action if one occurred.
+ int errcode;
+
+ /// conn being listened on for new connections
+ /// Reserved for read-only use.
+ // NP: public only until we can hide it behind connection handles
+ int fd;
+
+protected:
+ friend class AcceptLimiter;
+ int32_t isLimited; ///< whether this socket is delayed and on the AcceptLimiter queue.
+
+private:
+ Subscription::Pointer theCallSub; ///< used to generate AsyncCalls handling our events.
+
+ /// IP Address and port being listened on
+ Ip::Address local_addr;
+
+ /// Method to test if there are enough file descriptors to open a new client connection
+ /// if not the accept() will be postponed
+ static bool okToAccept();
+
+ /// Method callback for whenever an FD is ready to accept a client connection.
+ static void doAccept(int fd, void *data);
+
+ void acceptOne();
+ comm_err_t oldAccept(ConnectionDetail &newConnDetails, int *fd);
+ void setListen();
+
+ CBDATA_CLASS2(TcpAcceptor);
+};
+
+} // namespace Comm
+
+#endif /* SQUID_COMM_TCPACCEPTOR_H */
#ifndef _SQUID_COMM_COMM_ERR_T_H
#define _SQUID_COMM_COMM_ERR_T_H
-#include "config.h"
-
typedef enum {
COMM_OK = 0,
COMM_ERROR = -1,
+++ /dev/null
-
-/*
- * $Id$
- *
- *
- * SQUID Web Proxy Cache http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from
- * the Internet community; see the CONTRIBUTORS file for full
- * details. Many organizations have provided support for Squid's
- * development; see the SPONSORS file for full details. Squid is
- * Copyrighted (C) 2001 by the Regents of the University of
- * California; see the COPYRIGHT file for full details. Squid
- * incorporates software developed and/or copyrighted by other
- * sources; see the CREDITS file for full details.
- *
- * 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, USA.
- *
- */
-
-#ifndef SQUID_COMM_KQUEUE_H
-#define SQUID_COMM_KQUEUE_H
-
-#endif /* SQUID_COMM_KQUEUE_H */
debug_log = stderr;
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(fileno(debug_log), O_TEXT);
-
#endif
}
std::ostringstream (*Debug::CurrentDebug)(NULL);
-const size_t
+size_t
BuildPrefixInit()
{
// XXX: This must be kept in sync with the actual debug.cc location
#define HTTP_REQBUF_SZ 4096
/* CygWin & Windows NT Port */
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#define _WIN_SQUID_SERVICE_CONTROL_STOP SERVICE_CONTROL_STOP
#define _WIN_SQUID_SERVICE_CONTROL_SHUTDOWN SERVICE_CONTROL_SHUTDOWN
#define _WIN_SQUID_SERVICE_CONTROL_INTERROGATE SERVICE_CONTROL_INTERROGATE
*/
#include "squid.h"
+#include "comm/Loops.h"
#include "fde.h"
#include "MemBuf.h"
static PF diskHandleRead;
static PF diskHandleWrite;
-#if defined(_SQUID_WIN32_) || defined(_SQUID_OS2_)
+#if _SQUID_WINDOWS_ || _SQUID_OS2_
static int
diskWriteIsComplete(int fd)
{
}
if (F->flags.write_daemon) {
-#if defined(_SQUID_WIN32_) || defined(_SQUID_OS2_)
+#if _SQUID_WINDOWS_ || _SQUID_OS2_
/*
* on some operating systems, you can not delete or rename
* open files, so we won't allow delayed close.
*/
-
while (!diskWriteIsComplete(fd))
diskHandleWrite(fd, NULL);
-
#else
-
F->flags.close_request = 1;
-
debugs(6, 2, "file_close: FD " << fd << ", delaying close");
-
PROF_stop(file_close);
-
return;
-
#endif
}
dwrite_q *q = fdd->write_q;
len = q->len - q->buf_offset;
- xmemcpy(wq->buf + wq->len, q->buf + q->buf_offset, len);
+ memcpy(wq->buf + wq->len, q->buf + q->buf_offset, len);
wq->len += len;
fdd->write_q = q->next;
if (q->free_func)
- (q->free_func) (q->buf);
+ q->free_func(q->buf);
memFree(q, MEM_DWRITE_Q);
};
fdd->write_q = q->next;
if (q->free_func)
- (q->free_func) (q->buf);
+ q->free_func(q->buf);
if (q) {
memFree(q, MEM_DWRITE_Q);
fdd->write_q = q->next;
if (q->free_func)
- (q->free_func) (q->buf);
+ q->free_func(q->buf);
if (q) {
memFree(q, MEM_DWRITE_Q);
} else {
/* another block is queued */
diskCombineWrites(fdd);
- commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0);
F->flags.write_daemon = 1;
}
if (len < 0) {
if (ignoreErrno(errno)) {
- commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0);
PROF_stop(diskHandleRead);
return;
}
xrename(const char *from, const char *to)
{
debugs(21, 2, "xrename: renaming " << from << " to " << to);
-#if defined (_SQUID_OS2_) || defined (_SQUID_WIN32_)
-
- remove
- (to);
-
+#if _SQUID_OS2_ || _SQUID_WINDOWS_
+ remove(to);
#endif
if (0 == rename(from, to))
-
/*
* $Id$
*
*
*/
-#include "config.h"
#include "squid.h"
+#include "comm.h"
+#include "comm/Loops.h"
+#include "comm/Write.h"
#include "event.h"
#include "SquidTime.h"
#include "Store.h"
-#include "comm.h"
-#include "comm/Write.h"
#include "fde.h"
#include "ip/tools.h"
#include "MemBuf.h"
using external DNS process.
*/
#if !USE_DNSSERVERS
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#include "squid_windows.h"
#define REG_TCPIP_PARA_INTERFACES "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"
#define REG_TCPIP_PARA "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"
#ifndef _SQUID_MSWIN_
static void idnsParseResolvConf(void);
#endif
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
static void idnsParseWIN32Registry(void);
static void idnsParseWIN32SearchList(const char *);
#endif
nameservers = (ns *)xcalloc(nns_alloc, sizeof(*nameservers));
if (oldptr && oldalloc)
- xmemcpy(nameservers, oldptr, oldalloc * sizeof(*nameservers));
+ memcpy(nameservers, oldptr, oldalloc * sizeof(*nameservers));
if (oldptr)
safe_free(oldptr);
searchpath = (sp *)xcalloc(npc_alloc, sizeof(*searchpath));
if (oldptr && oldalloc)
- xmemcpy(searchpath, oldptr, oldalloc * sizeof(*searchpath));
+ memcpy(searchpath, oldptr, oldalloc * sizeof(*searchpath));
if (oldptr)
safe_free(oldptr);
return;
}
-#if defined(_SQUID_CYGWIN_)
+#if _SQUID_CYGWIN_
setmode(fileno(fp), O_TEXT);
-
#endif
while (fgets(buf, RESOLV_BUFSZ, fp)) {
#endif
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
static void
idnsParseWIN32SearchList(const char * Separator)
{
// Always keep reading. This stops (or at least makes harder) several
// attacks on the DNS client.
- commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0);
/* BUG (UNRESOLVED)
* two code lines after returning from comm_udprecvfrom()
if (DnsSocketB >= 0) {
port = comm_local_port(DnsSocketB);
debugs(78, 1, "DNS Socket created at " << addrB << ", FD " << DnsSocketB);
- commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
+ Comm::SetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
}
if (DnsSocketA >= 0) {
port = comm_local_port(DnsSocketA);
debugs(78, 1, "DNS Socket created at " << addrA << ", FD " << DnsSocketA);
- commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
+ Comm::SetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
}
}
idnsParseResolvConf();
#endif
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
if (0 == nns)
idnsParseWIN32Registry();
-
#endif
if (0 == nns) {
debugs(78, 1, "Warning: Could not find any nameservers. Trying to use localhost");
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
debugs(78, 1, "Please check your TCP-IP settings or /etc/resolv.conf file");
#else
-
debugs(78, 1, "Please check your /etc/resolv.conf file");
#endif
CC_MAX_STALE,
CC_MIN_FRESH,
CC_ONLY_IF_CACHED,
+ CC_STALE_IF_ERROR,
CC_OTHER,
CC_ENUM_END
} http_hdr_cc_type;
/* CygWin & Windows NT Port */
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
/*
* Supported Windows OS types codes
*/
_WIN_OS_WINLON,
_WIN_OS_WIN7
};
-
-#endif
-
-typedef enum {
- CLF_UNKNOWN,
- CLF_AUTO,
- CLF_CUSTOM,
- CLF_SQUID,
- CLF_COMMON,
-#if ICAP_CLIENT
- CLF_ICAP_SQUID,
#endif
- CLF_NONE
-} customlog_type;
enum {
DISABLE_PMTU_OFF,
typedef enum {
ERR_DETAIL_NONE,
ERR_DETAIL_START = 100000, // to avoid clashes with most OS error numbers
- ERR_DETAIL_ICAP_REQMOD_ABORT = ERR_DETAIL_START, // transaction abort
- ERR_DETAIL_ICAP_RESPMOD_CLT_SIDE_BODY, // client-side detected body abort
+ ERR_DETAIL_CLT_REQMOD_ABORT = ERR_DETAIL_START, // client-side detected transaction abort
+ ERR_DETAIL_CLT_REQMOD_REQ_BODY, // client-side detected REQMOD request body adaptation failure
+ ERR_DETAIL_CLT_REQMOD_RESP_BODY, // client-side detected REQMOD satisfaction reply body failure
ERR_DETAIL_ICAP_RESPMOD_EARLY, // RESPMOD failed w/o store entry
ERR_DETAIL_ICAP_RESPMOD_LATE, // RESPMOD failed with a store entry
ERR_DETAIL_ICAP_XACT_START, // transaction start failure
/* ICAP Errors */
ERR_ICAP_FAILURE,
+ /* Squid problem */
+ ERR_GATEWAY_FAILURE,
+
/* Special Cases */
ERR_DIR_LISTING, /* Display of remote directory (FTP, Gopher) */
ERR_SQUID_SIGNATURE, /* not really an error */
typedef struct {
int id;
char *page_name;
+ http_status page_redirect;
} ErrorDynamicPageInfo;
/* local constant and vars */
ErrorDynamicPageInfo *info = ErrorDynamicPages.items[i - ERR_MAX];
assert(info && info->id == i && info->page_name);
- if (strchr(info->page_name, ':') == NULL) {
+ const char *pg = info->page_name;
+ if (info->page_redirect != HTTP_STATUS_NONE)
+ pg = info->page_name +4;
+
+ if (strchr(pg, ':') == NULL) {
/** But only if they are not redirection URL. */
- error_text[i] = errorLoadText(info->page_name);
+ error_text[i] = errorLoadText(pg);
}
}
}
ErrorDynamicPageInfo *info = new ErrorDynamicPageInfo;
info->id = id;
info->page_name = xstrdup(page_name);
+ info->page_redirect = static_cast<http_status>(atoi(page_name));
+
+ /* WARNING on redirection status:
+ * 2xx are permitted, but not documented officially.
+ * - might be useful for serving static files (PAC etc) in special cases
+ * 3xx require a URL suitable for Location: header.
+ * - the current design does not allow for a Location: URI as well as a local file template
+ * although this possibility is explicitly permitted in the specs.
+ * 4xx-5xx require a local file template.
+ * - sending Location: on these codes with no body is invalid by the specs.
+ * - current result is Squid crashing or XSS problems as dynamic deny_info load random disk files.
+ * - a future redesign of the file loading may result in loading remote objects sent inline as local body.
+ */
+ if (info->page_redirect == HTTP_STATUS_NONE)
+ ; // special case okay.
+ else if (info->page_redirect < 200 || info->page_redirect > 599) {
+ // out of range
+ debugs(0, DBG_CRITICAL, "FATAL: status " << info->page_redirect << " is not valid on '" << page_name << "'");
+ self_destruct();
+ } else if ( /* >= 200 && */ info->page_redirect < 300 && strchr(&(page_name[4]), ':')) {
+ // 2xx require a local template file
+ debugs(0, DBG_CRITICAL, "FATAL: status " << info->page_redirect << " is not valid on '" << page_name << "'");
+ self_destruct();
+ } else if (/* >= 300 && */ info->page_redirect <= 399 && !strchr(&(page_name[4]), ':')) {
+ // 3xx require an absolute URL
+ debugs(0, DBG_CRITICAL, "FATAL: status " << info->page_redirect << " is not valid on '" << page_name << "'");
+ self_destruct();
+ } else if (info->page_redirect >= 400 /* && <= 599 */ && strchr(&(page_name[4]), ':')) {
+ // 4xx/5xx require a local template file
+ debugs(0, DBG_CRITICAL, "FATAL: status " << info->page_redirect << " is not valid on '" << page_name << "'");
+ self_destruct();
+ }
+ // else okay.
+
return info;
}
err->err_language = NULL;
err->type = type;
err->httpStatus = status;
+ if (err->page_id >= ERR_MAX && ErrorDynamicPages.items[err->page_id - ERR_MAX]->page_redirect != HTTP_STATUS_NONE)
+ err->httpStatus = ErrorDynamicPages.items[err->page_id - ERR_MAX]->page_redirect;
if (request != NULL) {
err->request = HTTPMSGLOCK(request);
if (err->err_language != Config.errorDefaultLanguage)
#endif
safe_free(err->err_language);
+#if USE_SSL
+ delete err->detail;
+#endif
cbdataFree(err);
}
#define CVT_BUF_SZ 512
const char *
-ErrorState::Convert(char token, bool building_deny_info_url)
+ErrorState::Convert(char token, bool building_deny_info_url, bool allowRecursion)
{
static MemBuf mb;
const char *p = NULL; /* takes priority over mb if set */
p = errorPageName(type);
break;
+ case 'D':
+ if (!allowRecursion)
+ p = "%D"; // if recursion is not allowed, do not convert
+#if USE_SSL
+ // currently only SSL error details implemented
+ else if (detail) {
+ const String &errDetail = detail->toString();
+ MemBuf *detail_mb = ConvertText(errDetail.termedBuf(), false);
+ mb.append(detail_mb->content(), detail_mb->contentSize());
+ delete detail_mb;
+ do_quote = 0;
+ } else
+#endif
+ mb.Printf("[No Error Detail]");
+ break;
+
case 'e':
mb.Printf("%d", xerrno);
break;
case 'g':
if (building_deny_info_url) break;
- /* FTP SERVER MESSAGE */
- if (ftp.server_msg)
- wordlistCat(ftp.server_msg, &mb);
- else if (ftp.listing) {
+ /* FTP SERVER RESPONSE */
+ if (ftp.listing) {
mb.append(ftp.listing->content(), ftp.listing->contentSize());
do_quote = 0;
+ } else if (ftp.server_msg) {
+ wordlistCat(ftp.server_msg, &mb);
}
break;
break;
case 't':
- mb.Printf("%s", mkhttpdlogtime(&squid_curtime));
+ mb.Printf("%s", Time::FormatHttpd(squid_curtime));
break;
case 'T':
char const *p = m;
char const *t;
+ if (m[0] == '3')
+ m += 4; // skip "3xx:"
+
while ((p = strchr(m, '%'))) {
result.append(m, p - m); /* copy */
- t = Convert(*++p, true); /* convert */
+ t = Convert(*++p, true, true); /* convert */
result.Printf("%s", t); /* copy */
m = p + 1; /* advance */
}
const char *name = errorPageName(page_id);
/* no LMT for error pages; error pages expire immediately */
- if (strchr(name, ':')) {
+ if (name[0] == '3' || (name[0] != '4' && name[0] != '5' && strchr(name, ':'))) {
/* Redirection */
- rep->setHeaders(HTTP_MOVED_TEMPORARILY, NULL, "text/html", 0, 0, -1);
+ http_status status = HTTP_MOVED_TEMPORARILY;
+ // Use configured 3xx reply status if set.
+ if (name[0] == '3')
+ status = httpStatus;
+ else {
+ // Use 307 for HTTP/1.1 non-GET/HEAD requests.
+ if (request->method != METHOD_GET && request->method != METHOD_HEAD && request->http_ver >= HttpVersion(1,1))
+ status = HTTP_TEMPORARY_REDIRECT;
+ }
+
+ rep->setHeaders(status, NULL, "text/html", 0, 0, -1);
if (request) {
MemBuf redirect_location;
MemBuf *
ErrorState::BuildContent()
{
- MemBuf *content = new MemBuf;
const char *m = NULL;
- const char *p;
- const char *t;
assert(page_id > ERR_NONE && page_id < error_page_count);
String hdr;
char dir[256];
int l = 0;
+ const char *freePage = NULL;
/** error_directory option in squid.conf overrides translations.
* Custom errors are always found either in error_directory or the templates directory.
if (m) {
/* store the language we found for the Content-Language reply header */
err_language = xstrdup(reset);
+ freePage = m;
break;
} else if (Config.errorLogMissingLanguages) {
debugs(4, DBG_IMPORTANT, "WARNING: Error Pages Missing Language: " << reset);
debugs(4, 2, HERE << "No existing error page language negotiated for " << errorPageName(page_id) << ". Using default error file.");
}
+ MemBuf *result = ConvertText(m, true);
+#if USE_ERR_LOCALES
+ safe_free(freePage);
+#endif
+
+ return result;
+}
+
+MemBuf *ErrorState::ConvertText(const char *text, bool allowRecursion)
+{
+ MemBuf *content = new MemBuf;
+ const char *p;
+ const char *m = text;
assert(m);
content->init();
while ((p = strchr(m, '%'))) {
content->append(m, p - m); /* copy */
- t = Convert(*++p, false); /* convert */
+ const char *t = Convert(*++p, false, allowRecursion); /* convert */
content->Printf("%s", t); /* copy */
m = p + 1; /* advance */
}
#include "auth/UserRequest.h"
#include "cbdata.h"
#include "ip/Address.h"
+#if USE_SSL
+#include "ssl/ErrorDetail.h"
+#endif
/**
\defgroup ErrorPageAPI Error Pages API
B - URL with FTP %2f hack x
c - Squid error code x
d - seconds elapsed since request received x
+ D - Error details x
e - errno x
E - strerror() x
f - FTP request line x
*/
MemBuf *BuildContent(void);
+ /**
+ * Convert the given template string into textual output
+ *
+ * \param text The string to be converted
+ * \param allowRecursion Whether to convert codes which output may contain codes
+ */
+ MemBuf *ConvertText(const char *text, bool allowRecursion);
+
/**
* Generates the Location: header value for a deny_info error page
* to be used for this error.
*
* \param token The token following % which need to be converted
* \param building_deny_info_url Perform special deny_info actions, such as URL-encoding and token skipping.
+ * \ allowRecursion True if the codes which do recursions should converted
*/
- const char *Convert(char token, bool building_deny_info_url);
+ const char *Convert(char token, bool building_deny_info_url, bool allowRecursion);
/**
* CacheManager / Debug dump of the ErrorState object.
char *request_hdrs;
char *err_msg; /* Preformatted error message from the cache */
+#if USE_SSL
+ Ssl::ErrorDetail *detail;
+#endif
private:
CBDATA_CLASS2(ErrorState);
};
assert (len != 0 || rep != NULL);
if (len) {
- xmemcpy (next->readBuffer.data, &outbound->buf[outbound_offset], len);
+ memcpy(next->readBuffer.data, &outbound->buf[outbound_offset], len);
if (len + outbound_offset == outbound->len) {
ESISegment::Pointer temp = outbound->next;
&context->incoming->buf[context->incoming->len] <<
" because our buffer was not used");
- xmemcpy (&context->incoming->buf[context->incoming->len], receivedData.data, len);
+ memcpy(&context->incoming->buf[context->incoming->len], receivedData.data, len);
context->incoming->len += len;
if (context->incoming->len == HTTP_REQBUF_SZ) {
if (len != receivedData.length) {
/* capture the remnants */
- xmemcpy (context->incoming->buf, &receivedData.data[len], receivedData.length - len);
+ memcpy(context->incoming->buf, &receivedData.data[len], receivedData.length - len);
context->incoming->len = receivedData.length - len;
}
if (!count)
return;
- xmemmove (elements, &elements[count], (elementcount - count) * sizeof (ESIElement::Pointer));
+ memmove(elements, &elements[count], (elementcount - count) * sizeof (ESIElement::Pointer));
elementcount -= count;
}
typedef struct _stackmember stackmember;
-typedef int evaluate (stackmember * stack, int *depth, int whereAmI,
- stackmember * candidate);
+typedef int evaluate(stackmember * stack, int *depth, int whereAmI,
+ stackmember * candidate);
typedef enum {
ESI_EXPR_INVALID,
int precedence;
};
-static void cleanmember (stackmember *);
-static void stackpop (stackmember * s, int *depth);
+static void cleanmember(stackmember *);
+static void stackpop(stackmember * s, int *depth);
void
-cleanmember (stackmember * s)
+cleanmember(stackmember * s)
{
if (s->valuetype == ESI_EXPR_LITERAL
&& s->valuestored == ESI_LITERAL_STRING) {
- safe_free (s->value.string);
+ safe_free(s->value.string);
s->value.string = NULL;
}
}
void
-stackpop (stackmember * s, int *depth)
+stackpop(stackmember * s, int *depth)
{
if (!(*depth)--)
return;
- cleanmember (&s[*depth]);
+ cleanmember(&s[*depth]);
}
static evaluate evalnegate;
static evaluate evalstartexpr;
static evaluate evalendexpr;
static evaluate evalexpr;
-static void dumpstack (stackmember * stack, int depth);
-static int addmember (stackmember * stack, int *stackdepth,
- stackmember * candidate);
-static int membercompare (stackmember a, stackmember b);
-static char const *trim (char const *s);
-static stackmember getsymbol (const char *s, char const **endptr);
-static void printliteral (stackmember s);
-static void printmember (stackmember s);
+static void dumpstack(stackmember * stack, int depth);
+static int addmember(stackmember * stack, int *stackdepth,
+ stackmember * candidate);
+static int membercompare(stackmember a, stackmember b);
+static char const *trim(char const *s);
+static stackmember getsymbol(const char *s, char const **endptr);
+static void printliteral(stackmember s);
+static void printmember(stackmember s);
/* -2 = failed to compate
* -1 = a less than b
* 2 - a more than b
*/
int
-membercompare (stackmember a, stackmember b)
+membercompare(stackmember a, stackmember b)
{
/* we can compare: sub expressions to sub expressions ,
* literals to literals
return 1;
} else if (a.valuestored == ESI_LITERAL_STRING) {
if (b.valuestored == ESI_LITERAL_STRING) {
- int i =strcmp (a.value.string, b.value.string);
+ int i =strcmp(a.value.string, b.value.string);
if (i < 0)
return -1;
}
/* return 0 on success, 1 on failure */
-int evalnegate
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evalnegate(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
if (whereAmI != *depth - 2)
/* invalid stack */
stack[whereAmI] = stack[(*depth)];
- cleanmember (candidate);
+ cleanmember(candidate);
if (stack[whereAmI].value.integral == 1)
stack[whereAmI].value.integral = 0;
return 0;
}
-int evalliteral
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evalliteral(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
debugs(86, 1, "attempt to evaluate a literal");
/* literals can't be evaluated */
return 1;
}
-int evalexpr
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evalexpr(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
debugs(86, 1, "attempt to evaluate a sub-expression result");
/* sub-scpr's can't be evaluated */
}
-int evalor
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evalor(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
int rv;
stackmember srv;
/* invalid comparison */
return 1;
- stackpop (stack, depth); /* arg rhs */
+ stackpop(stack, depth); /* arg rhs */
- stackpop (stack, depth); /* me */
+ stackpop(stack, depth); /* me */
- stackpop (stack, depth); /* arg lhs */
+ stackpop(stack, depth); /* arg lhs */
srv.valuetype = ESI_EXPR_EXPR;
stack[(*depth)++] = srv;
/* we're out of way, try adding now */
- if (!addmember (stack, depth, candidate))
+ if (!addmember(stack, depth, candidate))
/* Something wrong upstream */
return 1;
return 0;
}
-int evaland
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evaland(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
int rv;
stackmember srv;
/* invalid comparison */
return 1;
- stackpop (stack, depth); /* arg rhs */
+ stackpop(stack, depth); /* arg rhs */
- stackpop (stack, depth); /* me */
+ stackpop(stack, depth); /* me */
- stackpop (stack, depth); /* arg lhs */
+ stackpop(stack, depth); /* arg lhs */
srv.valuetype = ESI_EXPR_EXPR;
stack[(*depth)++] = srv;
/* we're out of way, try adding now */
- if (!addmember (stack, depth, candidate))
+ if (!addmember(stack, depth, candidate))
/* Something wrong upstream */
return 1;
return 0;
}
-int evallesseq
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evallesseq(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
int rv;
stackmember srv;
/* invalid stack */
return 1;
- rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
+ rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
if (rv == -2)
/* invalid comparison */
return 1;
- stackpop (stack, depth); /* arg rhs */
+ stackpop(stack, depth); /* arg rhs */
- stackpop (stack, depth); /* me */
+ stackpop(stack, depth); /* me */
- stackpop (stack, depth); /* arg lhs */
+ stackpop(stack, depth); /* arg lhs */
srv.valuetype = ESI_EXPR_EXPR;
stack[(*depth)++] = srv;
/* we're out of way, try adding now */
- if (!addmember (stack, depth, candidate))
+ if (!addmember(stack, depth, candidate))
/* Something wrong upstream */
return 1;
}
-int evallessthan
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evallessthan(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
int rv;
stackmember srv;
/* invalid stack */
return 1;
- rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
+ rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
if (rv == -2)
/* invalid comparison */
return 1;
- stackpop (stack, depth); /* arg rhs */
+ stackpop(stack, depth); /* arg rhs */
- stackpop (stack, depth); /* me */
+ stackpop(stack, depth); /* me */
- stackpop (stack, depth); /* arg lhs */
+ stackpop(stack, depth); /* arg lhs */
srv.valuetype = ESI_EXPR_EXPR;
stack[(*depth)++] = srv;
/* we're out of way, try adding now */
- if (!addmember (stack, depth, candidate))
+ if (!addmember(stack, depth, candidate))
/* Something wrong upstream */
return 1;
}
-int evalmoreeq
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evalmoreeq(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
int rv;
stackmember srv;
/* invalid stack */
return 1;
- rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
+ rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
if (rv == -2)
/* invalid comparison */
return 1;
- stackpop (stack, depth); /* arg rhs */
+ stackpop(stack, depth); /* arg rhs */
- stackpop (stack, depth); /* me */
+ stackpop(stack, depth); /* me */
- stackpop (stack, depth); /* arg lhs */
+ stackpop(stack, depth); /* arg lhs */
srv.valuetype = ESI_EXPR_EXPR;
stack[(*depth)++] = srv;
/* we're out of way, try adding now */
- if (!addmember (stack, depth, candidate))
+ if (!addmember(stack, depth, candidate))
/* Something wrong upstream */
return 1;
}
-int evalmorethan
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evalmorethan(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
int rv;
stackmember srv;
/* invalid stack */
return 1;
- rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
+ rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
if (rv == -2)
/* invalid comparison */
return 1;
- stackpop (stack, depth); /* arg rhs */
+ stackpop(stack, depth); /* arg rhs */
- stackpop (stack, depth); /* me */
+ stackpop(stack, depth); /* me */
- stackpop (stack, depth); /* arg lhs */
+ stackpop(stack, depth); /* arg lhs */
srv.valuetype = ESI_EXPR_EXPR;
stack[(*depth)++] = srv;
/* we're out of way, try adding now */
- if (!addmember (stack, depth, candidate))
+ if (!addmember(stack, depth, candidate))
/* Something wrong upstream */
return 1;
}
int
-evalequals (stackmember * stack, int *depth, int whereAmI,
- stackmember * candidate)
+evalequals(stackmember * stack, int *depth, int whereAmI,
+ stackmember * candidate)
{
int rv;
stackmember srv;
/* invalid stack */
return 1;
- rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
+ rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
if (rv == -2)
/* invalid comparison */
return 1;
- stackpop (stack, depth); /* arg rhs */
+ stackpop(stack, depth); /* arg rhs */
- stackpop (stack, depth); /* me */
+ stackpop(stack, depth); /* me */
- stackpop (stack, depth); /* arg lhs */
+ stackpop(stack, depth); /* arg lhs */
srv.valuetype = ESI_EXPR_EXPR;
stack[(*depth)++] = srv;
/* we're out of way, try adding now */
- if (!addmember (stack, depth, candidate))
+ if (!addmember(stack, depth, candidate))
/* Something wrong upstream */
return 1;
return 0;
}
-int evalnotequals
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evalnotequals(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
int rv;
stackmember srv;
/* invalid stack */
return 1;
- rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
+ rv = membercompare(stack[whereAmI - 1], stack[whereAmI + 1]);
if (rv == -2)
/* invalid comparison */
return 1;
- stackpop (stack, depth); /* arg rhs */
+ stackpop(stack, depth); /* arg rhs */
- stackpop (stack, depth); /* me */
+ stackpop(stack, depth); /* me */
- stackpop (stack, depth); /* arg lhs */
+ stackpop(stack, depth); /* arg lhs */
srv.valuetype = ESI_EXPR_EXPR;
stack[(*depth)++] = srv;
/* we're out of way, try adding now */
- if (!addmember (stack, depth, candidate))
+ if (!addmember(stack, depth, candidate))
/* Something wrong upstream */
return 1;
return 0;
}
-int evalstartexpr
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evalstartexpr(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
/* debugs(86, 1, "?("); */
stack[whereAmI] = stack[(*depth)];
- cleanmember (candidate);
+ cleanmember(candidate);
return 0;
}
-int evalendexpr
-(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
+int
+evalendexpr(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
{
/* Can't evaluate ) brackets */
return 1;
}
char const *
-trim (char const *s)
+trim(char const *s)
{
while (*s == ' ')
++s;
}
stackmember
-getsymbol (const char *s, char const **endptr)
+getsymbol(const char *s, char const **endptr)
{
stackmember rv;
char *end;
char const *origs = s;
/* trim whitespace */
- s = trim (s);
+ s = trim(s);
rv.eval = NULL; /* A literal */
rv.valuetype = ESI_EXPR_INVALID;
rv.valuestored = ESI_LITERAL_INVALID;
rv.precedence = 1; /* A literal */
if (('0' <= *s && *s <= '9') || *s == '-') {
- size_t length = strspn (s, "0123456789.");
+ size_t length = strspn(s, "0123456789.");
char const *point;
- if ((point = strchr (s, '.')) && point - s < (ssize_t)length) {
+ if ((point = strchr(s, '.')) && point - s < (ssize_t)length) {
/* floating point */
errno=0; /* reset errno */
- rv.value.floating = strtod (s, &end);
+ rv.value.floating = strtod(s, &end);
if (s == end || errno) {
/* Couldn't convert to float */
debugs(86, 1, "failed to convert '" << s << "' to float ");
*endptr = origs;
} else {
- debugs (86,6, "found " << rv.value.floating << " of length " << end - s);
+ debugs(86,6, "found " << rv.value.floating << " of length " << end - s);
*endptr = end;
rv.eval = evalliteral;
rv.valuestored = ESI_LITERAL_FLOAT;
} else {
/* INT */
errno=0; /* reset errno */
- rv.value.integral = strtol (s, &end, 0);
+ rv.value.integral = strtol(s, &end, 0);
if (s == end || errno) {
/* Couldn't convert to int */
debugs(86, 1, "failed to convert '" << s << "' to int ");
*endptr = origs;
} else {
- debugs (86,6, "found " << rv.value.integral << " of length " << end - s);
+ debugs(86,6, "found " << rv.value.integral << " of length " << end - s);
*endptr = end;
rv.eval = evalliteral;
rv.valuestored = ESI_LITERAL_INT;
/* Special case for zero length strings */
if (t - s - 1)
- rv.value.string = xstrndup (s + 1, t - s - 1);
+ rv.value.string = xstrndup(s + 1, t - s - 1);
else
- rv.value.string = static_cast<char *>(xcalloc (1,1));
+ rv.value.string = static_cast<char *>(xcalloc(1,1));
rv.eval = evalliteral;
rv.precedence = 5;
rv.eval = evalmorethan;
}
- } else if (!strncmp (s, "false", 5)) {
+ } else if (!strncmp(s, "false", 5)) {
debugs(86, 5, "getsymbol: found variable result 'false'");
*endptr = s + 5;
rv.valuetype = ESI_EXPR_EXPR;
rv.value.integral = 0;
rv.precedence = 1;
rv.eval = evalexpr;
- } else if (!strncmp (s, "true", 4)) {
+ } else if (!strncmp(s, "true", 4)) {
debugs(86, 5, "getsymbol: found variable result 'true'");
*endptr = s + 4;
rv.valuetype = ESI_EXPR_EXPR;
}
void
-printliteral (stackmember s)
+printliteral(stackmember s)
{
switch (s.valuestored) {
case ESI_LITERAL_INVALID:
- old_debug(86, 1) ( " Invalid " );
+ old_debug(86, 1)( " Invalid " );
break;
case ESI_LITERAL_FLOAT:
- old_debug(86,1) ("%f", s.value.floating);
+ old_debug(86,1)("%f", s.value.floating);
break;
case ESI_LITERAL_STRING:
- old_debug(86,1) ("'%s'", s.value.string);
+ old_debug(86,1)("'%s'", s.value.string);
break;
case ESI_LITERAL_INT:
- old_debug(86,1) ("%d", s.value.integral);
+ old_debug(86,1)("%d", s.value.integral);
break;
case ESI_LITERAL_BOOL:
}
void
-printmember (stackmember s)
+printmember(stackmember s)
{
switch (s.valuetype) {
case ESI_EXPR_INVALID:
- old_debug(86,1) (" Invalid ");
+ old_debug(86,1)(" Invalid ");
break;
case ESI_EXPR_LITERAL:
- printliteral (s);
+ printliteral(s);
break;
case ESI_EXPR_EXPR:
- old_debug(86,1) ("%s", s.value.integral ? "true" : "false");
+ old_debug(86,1)("%s", s.value.integral ? "true" : "false");
break;
case ESI_EXPR_OR:
- old_debug(86,1) ("|");
+ old_debug(86,1)("|");
break;
case ESI_EXPR_AND:
- old_debug(86,1) ("&");
+ old_debug(86,1)("&");
break;
case ESI_EXPR_NOT:
- old_debug(86,1) ("!");
+ old_debug(86,1)("!");
break;
case ESI_EXPR_START:
- old_debug(86,1) ("(");
+ old_debug(86,1)("(");
break;
case ESI_EXPR_END:
- old_debug(86,1) (")");
+ old_debug(86,1)(")");
break;
case ESI_EXPR_EQ:
- old_debug(86,1) ("==");
+ old_debug(86,1)("==");
break;
case ESI_EXPR_NOTEQ:
- old_debug(86,1) ("!=");
+ old_debug(86,1)("!=");
break;
case ESI_EXPR_LESS:
- old_debug(86,1) ("<");
+ old_debug(86,1)("<");
break;
case ESI_EXPR_LESSEQ:
- old_debug(86,1) ("<=");
+ old_debug(86,1)("<=");
break;
case ESI_EXPR_MORE:
- old_debug(86,1) (">");
+ old_debug(86,1)(">");
break;
case ESI_EXPR_MOREEQ:
- old_debug(86,1) (">=");
+ old_debug(86,1)(">=");
break;
}
}
void
-dumpstack (stackmember * stack, int depth)
+dumpstack(stackmember * stack, int depth)
{
int i;
for (i = 0; i < depth; ++i)
- printmember (stack[i]);
+ printmember(stack[i]);
if (depth)
- old_debug(86,1) ("\n");
+ old_debug(86,1)("\n");
}
int
-addmember (stackmember * stack, int *stackdepth, stackmember * candidate)
+addmember(stackmember * stack, int *stackdepth, stackmember * candidate)
{
if (candidate->valuetype != ESI_EXPR_LITERAL && *stackdepth > 1) {
/* !(!(a==b))) is why thats safe */
if (stack[*stackdepth - 2].valuetype == ESI_EXPR_LITERAL ||
stack[*stackdepth - 2].valuetype == ESI_EXPR_INVALID ||
- stack[*stackdepth - 2].eval (stack, stackdepth,
- *stackdepth - 2, candidate)) {
+ stack[*stackdepth - 2].eval(stack, stackdepth,
+ *stackdepth - 2, candidate)) {
/* cleanup candidate and stack */
- dumpstack (stack, *stackdepth);
- cleanmember (candidate);
+ dumpstack(stack, *stackdepth);
+ cleanmember(candidate);
debugs(86, 1, "invalid expression");
return 0;
}
}
int
-ESIExpression::Evaluate (char const *s)
+ESIExpression::Evaluate(char const *s)
{
stackmember stack[20];
int stackdepth = 0;
PROF_start(esiExpressionEval);
while (*s) {
- stackmember candidate = getsymbol (s, &end);
+ stackmember candidate = getsymbol(s, &end);
if (candidate.valuetype != ESI_EXPR_INVALID) {
- assert (s != end);
+ assert(s != end);
- if (!addmember (stack, &stackdepth, &candidate)) {
+ if (!addmember(stack, &stackdepth, &candidate)) {
PROF_stop(esiExpressionEval);
return 0;
}
rv.precedence = 0;
if (stack[stackdepth - 2].
- eval (stack, &stackdepth, stackdepth - 2, &rv)) {
+ eval(stack, &stackdepth, stackdepth - 2, &rv)) {
/* special case - leading operator failed */
debugs(86, 1, "invalid expression");
PROF_stop(esiExpressionEval);
}
/* if we hit here, we think we have a valid result */
- assert (stackdepth == 1);
+ assert(stackdepth == 1);
- assert (stack[0].valuetype == ESI_EXPR_EXPR);
+ assert(stack[0].valuetype == ESI_EXPR_EXPR);
PROF_stop(esiExpressionEval);
if (receivedData.data != esiStream->localbuffer->buf) {
/* But not the start of it */
- xmemmove (esiStream->localbuffer->buf, receivedData.data, receivedData.length);
+ memmove(esiStream->localbuffer->buf, receivedData.data, receivedData.length);
}
esiStream->localbuffer->len = receivedData.length;
size_t pos = 0;
while (temp.getRaw()) {
- xmemcpy (&rv[pos], temp->buf, temp->len);
+ memcpy(&rv[pos], temp->buf, temp->len);
pos += temp->len;
temp = temp->next;
}
ESISegment::append(char const *appendBuffer, size_t appendLength)
{
size_t toCopy = min(appendLength, space());
- xmemcpy (&buf[len], appendBuffer, toCopy);
+ memcpy(&buf[len], appendBuffer, toCopy);
len += toCopy;
return toCopy;
}
and can be wrapped
*/
-#if _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
struct arpreq {
Ip::Address arp_pa; /* protocol address */
Eui::Eui48::lookup(Ip::Address &c)
{
struct arpreq arpReq;
-#if !_SQUID_WIN32_
+#if !_SQUID_WINDOWS_
struct sockaddr_in *sa = NULL;
-#endif /* !_SQUID_WIN32_ */
+#endif /* !_SQUID_WINDOWS_ */
Ip::Address ipAddr = c;
ipAddr.SetPort(0);
set(arpReq.arp_ha.sa_data, 6);
return true;
-#elif _SQUID_WIN32_
+#elif _SQUID_WINDOWS_
DWORD dwNetTable = 0;
#include "rfc1738.h"
#include "URLScheme.h"
#include "wordlist.h"
+#if USE_SSL
+#include "ssl/support.h"
+#endif
#ifndef DEFAULT_EXTERNAL_ACL_TTL
#define DEFAULT_EXTERNAL_ACL_TTL 1 * 60 * 60
public:
external_acl *next;
- void add
- (ExternalACLEntry *);
+ void add(ExternalACLEntry *);
void trimCache();
}
void
-
-external_acl::add
-(ExternalACLEntry *anEntry)
+external_acl::add(ExternalACLEntry *anEntry)
{
trimCache();
assert (anEntry->def == NULL);
ttl = entry->result == 1 ? def->ttl : def->negative_ttl;
ttl = (ttl * (100 - def->grace)) / 100;
- if (entry->date + ttl < squid_curtime)
+ if (entry->date + ttl <= squid_curtime)
return 1;
else
return 0;
entry->key = xstrdup(key);
entry->update (data);
- def->add
- (entry);
+ def->add(entry);
return entry;
}
*/
#include "squid.h"
+#include "comm/Loops.h"
#include "fde.h"
#include "SquidTime.h"
#include "Debug.h"
}
debugs(51, 3, "fd_close FD " << fd << " " << F->desc);
- commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
- commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
F->flags.open = 0;
fdUpdateBiggest(fd, 0);
Number_FD--;
debugs(8, 3, "file_map_grow: creating space for " << fm->max_n_files << " files");
fm->file_map = (unsigned long *)xcalloc(fm->nwords, sizeof(*fm->file_map));
debugs(8, 3, "copying " << old_sz << " old bytes");
- xmemcpy(fm->file_map, old_map, old_sz);
+ memcpy(fm->file_map, old_map, old_sz);
xfree(old_map);
/* XXX account fm->file_map */
}
#include "acl/FilledChecklist.h"
#include "acl/Gadgets.h"
#include "CacheManager.h"
+#include "comm/Loops.h"
#include "event.h"
#include "errorpage.h"
#include "fde.h"
#include "ip/Intercept.h"
#include "ip/tools.h"
#include "mgr/Registration.h"
+#if USE_SSL
+#include "ssl/support.h"
+#include "ssl/ErrorDetail.h"
+#endif
static PSC fwdStartCompleteWrapper;
static PF fwdServerClosedWrapper;
#define MAX_FWD_STATS_IDX 9
static int FwdReplyCodes[MAX_FWD_STATS_IDX + 1][HTTP_INVALID_HEADER + 1];
-#if WIP_FWD_LOG
-static void fwdLog(FwdState * fwdState);
-static Logfile *logfile = NULL;
-#endif
-
static PconnPool *fwdPconnPool = new PconnPool("server-side");
CBDATA_CLASS_INIT(FwdState);
entry->mem_obj->checkUrlChecksum();
#endif
-#if WIP_FWD_LOG
-
- log();
-#endif
if (entry->store_status == STORE_PENDING) {
if (entry->isEmpty()) {
switch (ssl_error) {
case SSL_ERROR_WANT_READ:
- commSetSelect(fd, COMM_SELECT_READ, fwdNegotiateSSLWrapper, this, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, fwdNegotiateSSLWrapper, this, 0);
return;
case SSL_ERROR_WANT_WRITE:
- commSetSelect(fd, COMM_SELECT_WRITE, fwdNegotiateSSLWrapper, this, 0);
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, fwdNegotiateSSLWrapper, this, 0);
return;
default:
anErr->xerrno = EACCES;
#endif
+ Ssl::ErrorDetail *errFromFailure = (Ssl::ErrorDetail *)SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail);
+ if (errFromFailure != NULL) {
+ // The errFromFailure is attached to the ssl object
+ // and will be released when ssl object destroyed.
+ // Copy errFromFailure to a new Ssl::ErrorDetail object
+ anErr->detail = new Ssl::ErrorDetail(*errFromFailure);
+ }
+
fail(anErr);
if (fs->_peer) {
FwdState::initModule()
{
memDataInit(MEM_FWD_SERVER, "FwdServer", sizeof(FwdServer), 0);
-
-#if WIP_FWD_LOG
-
- if (logfile)
- (void) 0;
- else if (NULL == Config.Log.forward)
- (void) 0;
- else
- logfile = logfileOpen(Config.Log.forward, 0, 1);
-
-#endif
-
RegisterWithCacheManager();
}
return aclMapNfmark(Ip::Qos::TheConfig.nfmarkToServer, &ch);
}
-
-
-/**** WIP_FWD_LOG *************************************************************/
-
-#if WIP_FWD_LOG
-void
-fwdUninit(void)
-{
- if (NULL == logfile)
- return;
-
- logfileClose(logfile);
-
- logfile = NULL;
-}
-
-void
-fwdLogRotate(void)
-{
- if (logfile)
- logfileRotate(logfile);
-}
-
-static void
-FwdState::log()
-{
- if (NULL == logfile)
- return;
-
- logfilePrintf(logfile, "%9d.%03d %03d %s %s\n",
- (int) current_time.tv_sec,
- (int) current_time.tv_usec / 1000,
- last_status,
- RequestMethodStr(request->method),
- request->canonical);
-}
-
-void
-FwdState::status(http_status s)
-{
- last_status = s;
-}
-
-#endif
ErrorState *makeConnectingError(const err_type type) const;
static void RegisterWithCacheManager(void);
-#if WIP_FWD_LOG
-
- void uninit /**DOCS_NOSEMI*/
- static void logRotate /**DOCS_NOSEMI*/
- void status() /**DOCS_NOSEMI*/
-#endif
-
public:
StoreEntry *entry;
HttpRequest *request;
time_t start_t;
int n_tries;
int origin_tries;
-#if WIP_FWD_LOG
-
- http_status last_status;
-#endif
struct {
unsigned int dont_retry:1;
/// \ingroup FQDNCacheInternal
static long fqdncache_high = 200;
+/// \ingroup FQDNCacheInternal
+inline int fqdncacheCount() { return fqdn_table ? fqdn_table->count : 0; }
+
int
fqdncache_entry::age() const
{
eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 10.0, 1);
for (m = lru_list.tail; m; m = prev) {
- if (memInUse(MEM_FQDNCACHE_ENTRY) < fqdncache_low)
+ if (fqdncacheCount() < fqdncache_low)
break;
prev = m->prev;
storeAppendPrintf(sentry, "FQDN Cache Statistics:\n");
- storeAppendPrintf(sentry, "FQDNcache Entries: %d\n",
+ storeAppendPrintf(sentry, "FQDNcache Entries In Use: %d\n",
memInUse(MEM_FQDNCACHE_ENTRY));
+ storeAppendPrintf(sentry, "FQDNcache Entries Cached: %d\n",
+ fqdncacheCount());
+
storeAppendPrintf(sentry, "FQDNcache Requests: %d\n",
FqdncacheStats.requests);
case FQDN_ENT:
Answer = snmp_var_new_integer(Var->name, Var->name_length,
- memInUse(MEM_FQDNCACHE_ENTRY),
+ fqdncacheCount(),
SMI_GAUGE32);
break;
cstate->readbuffer = (char *)xmalloc(cstate->st_size);
p = storeCossMemPointerFromDiskOffset(storeCossFilenoToDiskOffset(sio->swap_filen),
NULL);
- xmemcpy(cstate->readbuffer, p, cstate->st_size);
+ memcpy(cstate->readbuffer, p, cstate->st_size);
}
sio->offset_ += len;
- xmemcpy(cstate->requestbuf, &cstate->readbuffer[cstate->requestoffset],
- cstate->requestlen);
+ memcpy(cstate->requestbuf, &cstate->readbuffer[cstate->requestoffset],
+ cstate->requestlen);
rlen = (size_t) cstate->requestlen;
}
s.swap_file_sz = e.swap_file_sz;
s.refcount = e.refcount;
s.flags = e.flags;
- xmemcpy(&s.key, e.key, SQUID_MD5_DIGEST_LENGTH);
- xmemcpy(outbuf + outbuf_offset, &s, ss);
+ memcpy(&s.key, e.key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(outbuf + outbuf_offset, &s, ss);
outbuf_offset += ss;
/* buffered write */
/* rename */
if (state->fd >= 0) {
-#if defined(_SQUID_OS2_) || defined(_SQUID_WIN32_)
+#if _SQUID_OS2_ || _SQUID_WINDOWS_
file_close(state->fd);
state->fd = -1;
-
#endif
xrename(state->newLog, state->cur);
s->swap_file_sz = e.swap_file_sz;
s->refcount = e.refcount;
s->flags = e.flags;
- xmemcpy(s->key, e.key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(s->key, e.key, SQUID_MD5_DIGEST_LENGTH);
file_write(swaplog_fd,
-1,
s,
CossSwapDir::statfs(StoreEntry & sentry) const
{
storeAppendPrintf(&sentry, "\n");
- storeAppendPrintf(&sentry, "Maximum Size: %Zu KB\n", max_size);
- storeAppendPrintf(&sentry, "Current Size: %Zu KB\n", cur_size);
+ storeAppendPrintf(&sentry, "Maximum Size: %lu KB\n", max_size);
+ storeAppendPrintf(&sentry, "Current Size: %lu KB\n", cur_size);
storeAppendPrintf(&sentry, "Percent Used: %0.2f%%\n",
(100.0 * (double)cur_size / (double)max_size) );
storeAppendPrintf(&sentry, "Number of object collisions: %d\n", (int) numcollisions);
void
CossSwapDir::dump(StoreEntry &entry)const
{
- storeAppendPrintf(&entry, " %Zu", (max_size >> 10));
+ storeAppendPrintf(&entry, " %lu", (max_size >> 10));
dumpOptions(&entry);
}
if (p) {
cstate->readbuffer = (char *)xmalloc(cstate->st_size);
- xmemcpy(cstate->readbuffer, p, cstate->st_size);
+ memcpy(cstate->readbuffer, p, cstate->st_size);
StoreFScoss::GetInstance().stats.open_mem_hits++;
} else {
/* Do the allocation */
CossSwapDir *SD = (CossSwapDir *)INDEXSD(swap_dirn);
dest = SD->storeCossMemPointerFromDiskOffset(diskoffset, &membuf);
assert(dest != NULL);
- xmemcpy(dest, buf, size);
+ memcpy(dest, buf, size);
offset_ += size;
if (free_func)
int x;
storeAppendPrintf(&sentry, "First level subdirectories: %d\n", l1);
storeAppendPrintf(&sentry, "Second level subdirectories: %d\n", l2);
- storeAppendPrintf(&sentry, "Maximum Size: %Zu KB\n", max_size);
- storeAppendPrintf(&sentry, "Current Size: %Zu KB\n", cur_size);
+ storeAppendPrintf(&sentry, "Maximum Size: %"PRIu64" KB\n", max_size);
+ storeAppendPrintf(&sentry, "Current Size: %"PRIu64" KB\n", cur_size);
storeAppendPrintf(&sentry, "Percent Used: %0.2f%%\n",
(double)(100.0 * cur_size) / (double)max_size);
storeAppendPrintf(&sentry, "Filemap bits in use: %d of %d (%d%%)\n",
state->outbuf = (char *)xcalloc(CLEAN_BUF_SZ, 1);
state->outbuf_offset = 0;
/*copy the header */
- xmemcpy(state->outbuf, &header, sizeof(StoreSwapLogHeader));
+ memcpy(state->outbuf, &header, sizeof(StoreSwapLogHeader));
state->outbuf_offset += header.record_size;
state->walker = repl->WalkInit(repl);
s.swap_file_sz = e.swap_file_sz;
s.refcount = e.refcount;
s.flags = e.flags;
- xmemcpy(&s.key, e.key, SQUID_MD5_DIGEST_LENGTH);
- xmemcpy(outbuf + outbuf_offset, &s, ss);
+ memcpy(&s.key, e.key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(outbuf + outbuf_offset, &s, ss);
outbuf_offset += ss;
/* buffered write */
/* rename */
if (state->fd >= 0) {
-#if defined(_SQUID_OS2_) || defined (_SQUID_WIN32_)
+#if _SQUID_OS2_ || _SQUID_WINDOWS_
file_close(state->fd);
state->fd = -1;
-
#endif
xrename(state->newLog, state->cur);
s->swap_file_sz = e.swap_file_sz;
s->refcount = e.refcount;
s->flags = e.flags;
- xmemcpy(s->key, e.key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(s->key, e.key, SQUID_MD5_DIGEST_LENGTH);
file_write(swaplog_fd,
-1,
s,
void
UFSSwapDir::dump(StoreEntry & entry) const
{
- storeAppendPrintf(&entry, " %Zu %d %d", (max_size >> 10), l1, l2);
+ storeAppendPrintf(&entry, " %"PRIu64" %d %d", (max_size >> 10), l1, l2);
dumpOptions(&entry);
}
swapData.swap_file_sz = readData.swap_file_sz;
swapData.refcount = readData.refcount;
swapData.flags = readData.flags;
- xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
return true;
}
};
swapData.swap_file_sz = readData.swap_file_sz;
swapData.refcount = readData.refcount;
swapData.flags = readData.flags;
- xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
return true;
}
};
swapData.swap_file_sz = readData.swap_file_sz;
swapData.refcount = readData.refcount;
swapData.flags = readData.flags;
- xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
return true;
}
};
case STORE_META_KEY:
assert(x.length == SQUID_MD5_DIGEST_LENGTH);
- xmemcpy(index, x.value, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(index, x.value, SQUID_MD5_DIGEST_LENGTH);
break;
case STORE_META_STD:
case STORE_META_STD_LFS:
assert(x.length == STORE_HDR_METASIZE);
- xmemcpy(&what->timestamp, x.value, STORE_HDR_METASIZE);
+ memcpy(&what->timestamp, x.value, STORE_HDR_METASIZE);
break;
default:
#include "squid.h"
#include "comm.h"
+#include "CommCalls.h"
+#include "comm/TcpAcceptor.h"
#include "comm/Write.h"
-#include "comm/ListenStateData.h"
#include "compat/strtoll.h"
#include "ConnectionDetail.h"
#include "errorpage.h"
void clear(); /// just resets fd and close handler. does not close active connections.
- int fd; /// channel descriptor; \todo: remove because the closer has it
+ int fd; /// channel descriptor
- /** Current listening socket handler. delete on shutdown or abort.
- * FTP stores a copy of the FD in the field fd above.
- * Use close() to properly close the channel.
- */
- Comm::ListenStateData *listener;
+ Ip::Address local; ///< The local IP address:port this channel is using
+
+ int flags; ///< socket flags used when opening.
private:
AsyncCall::Pointer closer; /// Comm close handler callback
void completedListing(void);
void dataComplete();
void dataRead(const CommIoCbParams &io);
+
+ /// ignore timeout on CTRL channel. set read timeout on DATA channel.
+ void switchTimeoutToDataChannel();
+ /// create a data channel acceptor and start listening.
+ void listenForDataChannel(const int fd, const char *note);
+
int checkAuth(const HttpHeader * req_hdr);
void checkUrlpath();
void buildTitleUrl();
void
FtpStateData::ctrlClosed(const CommCloseCbParams &io)
{
+ debugs(9, 4, HERE);
ctrl.clear();
deleteThis("FtpStateData::ctrlClosed");
}
void
FtpStateData::dataClosed(const CommCloseCbParams &io)
{
- if (data.listener) {
- delete data.listener;
- data.listener = NULL;
- data.fd = -1;
+ debugs(9, 4, HERE);
+ if (data.fd >= 0) {
+ comm_close(data.fd);
+ // NP clear() does the: data.fd = -1;
}
data.clear();
failed(ERR_FTP_FAILURE, 0);
debugs(9, 9, HERE << ": OUT: login='" << login << "', escaped=" << escaped << ", user=" << user << ", password=" << password);
}
+void
+FtpStateData::switchTimeoutToDataChannel()
+{
+ commSetTimeout(ctrl.fd, -1, NULL, NULL);
+
+ typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
+ AsyncCall::Pointer timeoutCall = JobCallback(9, 5, TimeoutDialer, this, FtpStateData::ftpTimeout);
+ commSetTimeout(data.fd, Config.Timeout.read, timeoutCall);
+}
+
+void
+FtpStateData::listenForDataChannel(const int fd, const char *note)
+{
+ assert(data.fd < 0);
+
+ typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> AcceptDialer;
+ typedef AsyncCallT<AcceptDialer> AcceptCall;
+ RefCount<AcceptCall> call = static_cast<AcceptCall*>(JobCallback(11, 5, AcceptDialer, this, FtpStateData::ftpAcceptDataConnection));
+ Subscription::Pointer sub = new CallSubscription<AcceptCall>(call);
+
+ /* open the conn if its not already open */
+ int newFd = fd;
+ if (newFd < 0) {
+ newFd = comm_open_listener(SOCK_STREAM, IPPROTO_TCP, data.local, data.flags, note);
+ if (newFd < 0) {
+ debugs(5, DBG_CRITICAL, HERE << "comm_open_listener failed:" << data.local << " error: " << errno);
+ return;
+ }
+ debugs(9, 3, HERE << "Unconnected data socket created on FD " << newFd << ", " << data.local);
+ }
+
+ assert(newFd >= 0);
+ Comm::TcpAcceptor *tmp = new Comm::TcpAcceptor(newFd, data.local, data.flags, note, sub);
+ AsyncJob::Start(tmp);
+
+ // Ensure we have a copy of the FD opened for listening and a close handler on it.
+ data.opened(newFd, dataCloser());
+ switchTimeoutToDataChannel();
+}
+
void
FtpStateData::ftpTimeout(const CommTimeoutCbParams &io)
{
usable = end - sbuf;
- debugs(9, 3, HERE << "usable = " << usable);
+ debugs(9, 3, HERE << "usable = " << usable << " of " << len << " bytes.");
if (usable == 0) {
- debugs(9, 3, HERE << "didn't find end for " << entry->url() );
+ if (buf[0] == '\0' && len == 1) {
+ debugs(9, 3, HERE << "NIL ends data from " << entry->url() << " transfer problem?");
+ data.readBuf->consume(len);
+ } else {
+ debugs(9, 3, HERE << "didn't find end for " << entry->url());
+ debugs(9, 3, HERE << "buffer remains (" << len << " bytes) '" << rfc1738_do_escape(buf,0) << "'");
+ }
xfree(sbuf);
return;
}
* status code after the data command. FtpStateData was being
* deleted in the middle of dataRead().
*/
- scheduleReadControlReply(0);
+ /* AYJ: 2011-01-13: Bug 2581.
+ * 226 status is possibly waiting in the ctrl buffer.
+ * The connection will hang if we DONT send buffered_ok.
+ * This happens on all transfers which can be completly sent by the
+ * server before the 150 started status message is read in by Squid.
+ * ie all transfers of about one packet hang.
+ */
+ scheduleReadControlReply(1);
}
void
int
FtpStateData::checkAuth(const HttpHeader * req_hdr)
{
- const char *auth;
-
/* default username */
xstrncpy(user, "anonymous", MAX_URL);
+#if HAVE_AUTH_MODULE_BASIC
/* Check HTTP Authorization: headers (better than defaults, but less than URL) */
+ const char *auth;
if ( (auth = req_hdr->getAuth(HDR_AUTHORIZATION, "Basic")) ) {
flags.authenticated = 1;
loginParser(auth, FTP_LOGIN_NOT_ESCAPED);
}
/* we fail with authorization-required error later IFF the FTP server requests it */
+#endif
/* Test URL login syntax. Overrides any headers received. */
loginParser(request->login, FTP_LOGIN_ESCAPED);
* establish one on the control socket.
*/
- if (data.fd > -1) {
+ if (data.fd >= 0) {
AsyncCall::Pointer nullCall = NULL;
commSetTimeout(data.fd, -1, nullCall);
}
/* Got some data past the complete reply */
assert(bytes_used < ctrl.offset);
ctrl.offset -= bytes_used;
- xmemmove(ctrl.buf, ctrl.buf + bytes_used,
- ctrl.offset);
+ memmove(ctrl.buf, ctrl.buf + bytes_used, ctrl.offset);
}
/* Move the last line of the reply message to ctrl.last_reply */
HttpReply *newrep = err->BuildHttpReply();
errorStateFree(err);
+
+#if HAVE_AUTH_MODULE_BASIC
/* add Authenticate header */
newrep->header.putAuth("Basic", ftpRealm());
+#endif
// add it to the store entry for response....
entry->replaceHttpReply(newrep);
static int
ftpOpenListenSocket(FtpStateData * ftpState, int fallback)
{
- int fd;
- Ip::Address addr;
struct addrinfo *AI = NULL;
- int on = 1;
int x = 0;
/// Close old data channels, if any. We may open a new one below.
- ftpState->data.close();
+ if ((ftpState->data.flags & COMM_REUSEADDR))
+ // NP: in fact it points to the control channel. just clear it.
+ ftpState->data.clear();
+ else
+ ftpState->data.close();
/*
* Set up a listen socket on the same local address as the
* control connection.
*/
-
- addr.InitAddrInfo(AI);
-
+ ftpState->data.local.InitAddrInfo(AI);
x = getsockname(ftpState->ctrl.fd, AI->ai_addr, &AI->ai_addrlen);
-
- addr = *AI;
-
- addr.FreeAddrInfo(AI);
+ ftpState->data.local = *AI;
+ ftpState->data.local.FreeAddrInfo(AI);
if (x) {
debugs(9, DBG_CRITICAL, HERE << "getsockname(" << ftpState->ctrl.fd << ",..): " << xstrerror());
* used for both control and data.
*/
if (fallback) {
+ int on = 1;
setsockopt(ftpState->ctrl.fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
+ ftpState->ctrl.flags |= COMM_REUSEADDR;
+ ftpState->data.flags |= COMM_REUSEADDR;
} else {
/* if not running in fallback mode a new port needs to be retrieved */
- addr.SetPort(0);
+ ftpState->data.local.SetPort(0);
+ ftpState->data.flags = COMM_NONBLOCKING;
}
- fd = comm_open(SOCK_STREAM,
- IPPROTO_TCP,
- addr,
- COMM_NONBLOCKING | (fallback ? COMM_REUSEADDR : 0),
- ftpState->entry->url());
- debugs(9, 3, HERE << "Unconnected data socket created on FD " << fd );
-
- if (fd < 0) {
- debugs(9, DBG_CRITICAL, HERE << "comm_open failed");
- return -1;
- }
-
- typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
- AsyncCall::Pointer acceptCall = JobCallback(11, 5,
- acceptDialer, ftpState, FtpStateData::ftpAcceptDataConnection);
- ftpState->data.listener = new Comm::ListenStateData(fd, acceptCall, false);
-
- if (!ftpState->data.listener || ftpState->data.listener->errcode != 0) {
- comm_close(fd);
- return -1;
- }
-
- ftpState->data.opened(fd, ftpState->dataCloser());
- ftpState->data.port = comm_local_port(fd);
- ftpState->data.host = NULL;
- return fd;
+ ftpState->listenForDataChannel((fallback?ftpState->ctrl.fd:-1), ftpState->entry->url());
+ return ftpState->data.fd;
}
/// \ingroup ServerProtocolFTPInternal
static void
ftpSendEPRT(FtpStateData * ftpState)
{
- int fd;
- Ip::Address addr;
- struct addrinfo *AI = NULL;
- char buf[MAX_IPSTRLEN];
-
if (Config.Ftp.epsv_all && ftpState->flags.epsv_all_sent) {
debugs(9, DBG_IMPORTANT, "FTP does not allow EPRT method after 'EPSV ALL' has been sent.");
return;
}
+ if (!Config.Ftp.eprt) {
+ /* Disabled. Switch immediately to attempting old PORT command. */
+ debugs(9, 3, "EPRT disabled by local administrator");
+ ftpSendPORT(ftpState);
+ return;
+ }
+
+ int fd;
+ Ip::Address addr;
+ struct addrinfo *AI = NULL;
+ char buf[MAX_IPSTRLEN];
+
debugs(9, 3, HERE);
ftpState->flags.pasv_supported = 0;
fd = ftpOpenListenSocket(ftpState, 0);
+ debugs(9, 3, "Listening for FTP data connection with FD " << fd);
Ip::Address::InitAddrInfo(AI);
*/
void FtpStateData::ftpAcceptDataConnection(const CommAcceptCbParams &io)
{
- char ntoapeer[MAX_IPSTRLEN];
- debugs(9, 3, "ftpAcceptDataConnection");
-
- // one connection accepted. the handler has stopped listening. drop our local pointer to it.
- data.listener = NULL;
+ debugs(9, 3, HERE);
if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
abortTransaction("entry aborted when accepting data conn");
return;
}
+ if (io.flag != COMM_OK) {
+ data.close();
+ debugs(9, DBG_IMPORTANT, "FTP AcceptDataConnection: FD " << io.fd << ": " << xstrerr(io.xerrno));
+ /** \todo Need to send error message on control channel*/
+ ftpFail(this);
+ return;
+ }
+
+ /* data listening conn is no longer even open. abort. */
+ if (data.fd <= 0 || fd_table[data.fd].flags.open == 0) {
+ data.clear(); // ensure that it's cleared and not just closed.
+ return;
+ }
+
/** \par
* When squid.conf ftp_sanitycheck is enabled, check the new connection is actually being
* made by the remote client which is connected to the FTP control socket.
+ * Or the one which we were told to listen for by control channel messages (may differ under NAT).
* This prevents third-party hacks, but also third-party load balancing handshakes.
*/
if (Config.Ftp.sanitycheck) {
+ char ntoapeer[MAX_IPSTRLEN];
io.details.peer.NtoA(ntoapeer,MAX_IPSTRLEN);
- if (strcmp(fd_table[ctrl.fd].ipaddr, ntoapeer) != 0) {
+ if (strcmp(fd_table[ctrl.fd].ipaddr, ntoapeer) != 0 &&
+ strcmp(fd_table[data.fd].ipaddr, ntoapeer) != 0) {
debugs(9, DBG_IMPORTANT,
"FTP data connection from unexpected server (" <<
io.details.peer << "), expecting " <<
- fd_table[ctrl.fd].ipaddr);
+ fd_table[ctrl.fd].ipaddr << " or " << fd_table[data.fd].ipaddr);
- /* close the bad soures connection down ASAP. */
+ /* close the bad sources connection down ASAP. */
comm_close(io.nfd);
- /* we are ony accepting once, so need to re-open the listener socket. */
- typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
- AsyncCall::Pointer acceptCall = JobCallback(11, 5,
- acceptDialer, this, FtpStateData::ftpAcceptDataConnection);
- data.listener = new Comm::ListenStateData(data.fd, acceptCall, false);
+ /* drop the bad connection (io) by ignoring the attempt. */
return;
}
}
- if (io.flag != COMM_OK) {
- debugs(9, DBG_IMPORTANT, "ftpHandleDataAccept: FD " << io.nfd << ": " << xstrerr(io.xerrno));
- /** \todo XXX Need to set error message */
- ftpFail(this);
- return;
- }
-
/**\par
- * Replace the Listen socket with the accepted data socket */
+ * Replace the Listening socket with the accepted data socket */
data.close();
data.opened(io.nfd, dataCloser());
data.port = io.details.peer.GetPort();
- io.details.peer.NtoA(data.host,SQUIDHOSTNAMELEN);
+ data.host = xstrdup(fd_table[io.nfd].ipaddr);
debugs(9, 3, "ftpAcceptDataConnection: Connected data socket on " <<
"FD " << io.nfd << " to " << io.details.peer << " FD table says: " <<
"ctrl-peer= " << fd_table[ctrl.fd].ipaddr << ", " <<
"data-peer= " << fd_table[data.fd].ipaddr);
+ assert(haveControlChannel("ftpAcceptDataConnection"));
+ assert(ctrl.message == NULL);
- AsyncCall::Pointer nullCall = NULL;
- commSetTimeout(ctrl.fd, -1, nullCall);
-
- typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
- AsyncCall::Pointer timeoutCall = JobCallback(9, 5,
- TimeoutDialer, this, FtpStateData::ftpTimeout);
- commSetTimeout(data.fd, Config.Timeout.read, timeoutCall);
-
- /*\todo XXX We should have a flag to track connect state...
- * host NULL -> not connected, port == local port
- * host set -> connected, port == remote port
- */
- /* Restart state (SENT_NLST/LIST/RETR) */
- FTP_SM_FUNCS[state] (this);
+ // Ctrl channel operations will determine what happens to this data connection
}
/// \ingroup ServerProtocolFTPInternal
return;
}
- /*\par
- * When client status is 125, or 150 without a hostname, Begin data transfer. */
+ /* When client status is 125, or 150 without a hostname, Begin data transfer. */
debugs(9, 3, HERE << "starting data transfer");
+ switchTimeoutToDataChannel();
sendMoreRequestBody();
- /** \par
- * Cancel the timeout on the Control socket and
- * establish one on the data socket.
- */
- AsyncCall::Pointer nullCall = NULL;
- commSetTimeout(ctrl.fd, -1, nullCall);
-
- typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
- AsyncCall::Pointer timeoutCall = JobCallback(9, 5,
- TimeoutDialer, this, FtpStateData::ftpTimeout);
-
- commSetTimeout(data.fd, Config.Timeout.read, timeoutCall);
-
state = WRITING_DATA;
debugs(9, 3, HERE << "writing data channel");
} else if (code == 150) {
/*\par
- * When client code is 150 with a hostname, Accept data channel. */
+ * When client code is 150 without a hostname, Accept data channel. */
debugs(9, 3, "ftpReadStor: accepting data channel");
- typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
- AsyncCall::Pointer acceptCall = JobCallback(11, 5,
- acceptDialer, this, FtpStateData::ftpAcceptDataConnection);
-
- data.listener = new Comm::ListenStateData(data.fd, acceptCall, false);
+ listenForDataChannel(data.fd, data.host);
} else {
debugs(9, DBG_IMPORTANT, HERE << "Unexpected reply code "<< std::setfill('0') << std::setw(3) << code);
ftpFail(this);
if (code == 125 || (code == 150 && ftpState->data.host)) {
/* Begin data transfer */
- /* XXX what about Config.Timeout.read? */
+ debugs(9, 3, HERE << "begin data transfer from " << ftpState->data.host << " (" << ftpState->data.local << ")");
+ ftpState->switchTimeoutToDataChannel();
ftpState->maybeReadVirginBody();
ftpState->state = READING_DATA;
- /*
- * Cancel the timeout on the Control socket and establish one
- * on the data socket
- */
- AsyncCall::Pointer nullCall = NULL;
- commSetTimeout(ftpState->ctrl.fd, -1, nullCall);
return;
} else if (code == 150) {
/* Accept data channel */
- typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
- AsyncCall::Pointer acceptCall = JobCallback(11, 5,
- acceptDialer, ftpState, FtpStateData::ftpAcceptDataConnection);
-
- ftpState->data.listener = new Comm::ListenStateData(ftpState->data.fd, acceptCall, false);
- /*
- * Cancel the timeout on the Control socket and establish one
- * on the data socket
- */
- AsyncCall::Pointer nullCall = NULL;
- commSetTimeout(ftpState->ctrl.fd, -1, nullCall);
-
- typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
- AsyncCall::Pointer timeoutCall = JobCallback(9, 5,
- TimeoutDialer, ftpState,FtpStateData::ftpTimeout);
- commSetTimeout(ftpState->data.fd, Config.Timeout.read, timeoutCall);
+ debugs(9, 3, HERE << "accept data channel from " << ftpState->data.host << " (" << ftpState->data.local << ")");
+ ftpState->listenForDataChannel(ftpState->data.fd, ftpState->data.host);
return;
} else if (!ftpState->flags.tried_nlst && code > 300) {
ftpSendNlst(ftpState);
if (code == 125 || (code == 150 && ftpState->data.host)) {
/* Begin data transfer */
debugs(9, 3, HERE << "reading data channel");
- /* XXX what about Config.Timeout.read? */
+ ftpState->switchTimeoutToDataChannel();
ftpState->maybeReadVirginBody();
ftpState->state = READING_DATA;
- /*
- * Cancel the timeout on the Control socket and establish one
- * on the data socket
- */
- AsyncCall::Pointer nullCall = NULL;
- commSetTimeout(ftpState->ctrl.fd, -1, nullCall);
} else if (code == 150) {
/* Accept data channel */
- typedef CommCbMemFunT<FtpStateData, CommAcceptCbParams> acceptDialer;
- AsyncCall::Pointer acceptCall = JobCallback(11, 5,
- acceptDialer, ftpState, FtpStateData::ftpAcceptDataConnection);
- ftpState->data.listener = new Comm::ListenStateData(ftpState->data.fd, acceptCall, false);
- /*
- * Cancel the timeout on the Control socket and establish one
- * on the data socket
- */
- AsyncCall::Pointer nullCall = NULL;
- commSetTimeout(ftpState->ctrl.fd, -1, nullCall);
-
- typedef CommCbMemFunT<FtpStateData, CommTimeoutCbParams> TimeoutDialer;
- AsyncCall::Pointer timeoutCall = JobCallback(9, 5,
- TimeoutDialer, ftpState,FtpStateData::ftpTimeout);
- commSetTimeout(ftpState->data.fd, Config.Timeout.read, timeoutCall);
+ ftpState->listenForDataChannel(ftpState->data.fd, ftpState->data.host);
} else if (code >= 300) {
if (!ftpState->flags.try_slash_hack) {
/* Try this as a directory missing trailing slash... */
ErrorState *err = errorCon(ERR_CACHE_ACCESS_DENIED, HTTP_UNAUTHORIZED, request);
HttpReply *newrep = err->BuildHttpReply();
errorStateFree(err);
+#if HAVE_AUTH_MODULE_BASIC
/* add Authenticate header */
newrep->header.putAuth("Basic", realm);
+#endif
return newrep;
}
fd = aFd;
closer = aCloser;
comm_add_close_handler(fd, closer);
+
+ // grab the local IP address:port details for this connection
+ struct addrinfo *AI = NULL;
+ local.InitAddrInfo(AI);
+ getsockname(aFd, AI->ai_addr, &AI->ai_addrlen);
+ local = *AI;
+ local.FreeAddrInfo(AI);
}
/// planned close: removes the close handler and calls comm_close
FtpChannel::close()
{
// channels with active listeners will be closed when the listener handler dies.
- if (listener) {
- delete listener;
- listener = NULL;
- comm_remove_close_handler(fd, closer);
- closer = NULL;
- fd = -1;
- } else if (fd >= 0) {
- comm_remove_close_handler(fd, closer);
- closer = NULL;
+ if (fd >= 0) {
+ if (closer != NULL) {
+ comm_remove_close_handler(fd, closer);
+ closer = NULL;
+ }
comm_close(fd); // we do not expect to be called back
fd = -1;
}
//MOVED:structs.h extern SquidConfig2 Config2;
extern char *ConfigFile; /* NULL */
extern char *IcpOpcodeStr[];
- extern const char *log_tags[];
extern char tmp_error_buf[ERROR_BUF_SZ];
extern char ThisCache[RFC2181_MAXHOSTNAMELEN << 1];
extern char ThisCache2[RFC2181_MAXHOSTNAMELEN << 1];
extern unsigned int WIN32_Socks_initialized; /* 0 */
#endif
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
extern unsigned int WIN32_OS_version; /* 0 */
extern char *WIN32_OS_string; /* NULL */
extern char *WIN32_Service_name; /* NULL */
extern int ssl_ex_index_server; /* -1 */
extern int ssl_ctx_ex_index_dont_verify_domain; /* -1 */
extern int ssl_ex_index_cert_error_check; /* -1 */
+ extern int ssl_ex_index_ssl_error_detail; /* -1 */
extern const char *external_acl_message; /* NULL */
extern int opt_send_signal; /* -1 */
len = TEMP_BUF_SIZE - gopherState->len;
}
- xmemcpy(gopherState->buf + gopherState->len, inbuf, len);
+ memcpy(gopherState->buf + gopherState->len, inbuf, len);
gopherState->len += len;
return;
}
}
if (len > (pos - inbuf)) {
- xmemcpy(gopherState->buf, pos, len - (pos - inbuf));
+ memcpy(gopherState->buf, pos, len - (pos - inbuf));
gopherState->len = len - (pos - inbuf);
}
#include "squid.h"
#include "comm/Write.h"
#include "helper.h"
+#include "log/Gadgets.h"
#include "SquidMath.h"
#include "SquidTime.h"
#include "Store.h"
srv->flags.shutdown ? 'S' : ' ',
tt < 0.0 ? 0.0 : tt,
(int) srv->roffset,
- srv->requests[0] ? log_quote(srv->requests[0]->buf) : "(none)");
+ srv->requests[0] ? Log::QuoteMimeBlob(srv->requests[0]->buf) : "(none)");
}
storeAppendPrintf(sentry, "\nFlags key:\n\n");
srv->request ? (srv->request->placeholder ? 'P' : ' ') : ' ',
tt < 0.0 ? 0.0 : tt,
(int) srv->roffset,
- srv->request ? log_quote(srv->request->buf) : "(none)");
+ srv->request ? Log::QuoteMimeBlob(srv->request->buf) : "(none)");
}
storeAppendPrintf(sentry, "\nFlags key:\n\n");
*/
#include "squid.h"
-#include "htcp.h"
+#include "AccessLogEntry.h"
#include "acl/FilledChecklist.h"
#include "acl/Acl.h"
-#include "ip/tools.h"
-#include "SquidTime.h"
-#include "Store.h"
-#include "StoreClient.h"
-#include "HttpRequest.h"
#include "comm.h"
-#include "MemBuf.h"
+#include "comm/Loops.h"
+#include "htcp.h"
#include "http.h"
+#include "HttpRequest.h"
#include "icmp/net_db.h"
-#include "AccessLogEntry.h"
#include "ipc/StartListening.h"
+#include "ip/tools.h"
+#include "MemBuf.h"
+#include "SquidTime.h"
+#include "Store.h"
+#include "StoreClient.h"
/// dials htcpIncomingConnectionOpened call
class HtcpListeningStartedDialer: public CallDialer,
copy_sz += 2;
if (buflen < copy_sz)
return -1;
- xmemcpy(buf, &auth, copy_sz);
+ memcpy(buf, &auth, copy_sz);
return copy_sz;
}
length = htons((uint16_t) len);
- xmemcpy(buf + off, &length, 2);
+ memcpy(buf + off, &length, 2);
off += 2;
return -1;
if (len)
- xmemcpy(buf + off, s, len);
+ memcpy(buf + off, s, len);
off += len;
case RR_REQUEST:
debugs(31, 3, "htcpBuildClrOpData: RR_REQUEST");
reason = htons((u_short)stuff->reason);
- xmemcpy(buf, &reason, 2);
+ memcpy(buf, &reason, 2);
return htcpBuildSpecifier(buf + 2, buflen - 2, stuff) + 2;
case RR_RESPONSE:
break;
hdr.msg_id = htonl(hdr.msg_id);
if (!old_squid_format) {
- xmemcpy(buf, &hdr, hdr_sz);
+ memcpy(buf, &hdr, hdr_sz);
} else {
htcpDataHeaderSquid hdrSquid;
memset(&hdrSquid, 0, sizeof(hdrSquid));
hdrSquid.response = hdr.response;
hdrSquid.F1 = hdr.F1;
hdrSquid.RR = hdr.RR;
- xmemcpy(buf, &hdrSquid, hdr_sz);
+ memcpy(buf, &hdrSquid, hdr_sz);
}
debugs(31, 3, "htcpBuildData: size " << off);
else
hdr.minor = 1;
- xmemcpy(buf, &hdr, hdr_sz);
+ memcpy(buf, &hdr, hdr_sz);
debugs(31, 3, "htcpBuildPacket: size " << off);
}
htcpHexdump("htcpHandle", buf, sz);
- xmemcpy(&htcpHdr, buf, sizeof(htcpHeader));
+ memcpy(&htcpHdr, buf, sizeof(htcpHeader));
htcpHdr.length = ntohs(htcpHdr.length);
if (htcpHdr.minor == 0)
}
if (!old_squid_format) {
- xmemcpy(&hdr, hbuf, sizeof(hdr));
+ memcpy(&hdr, hbuf, sizeof(hdr));
} else {
htcpDataHeaderSquid hdrSquid;
- xmemcpy(&hdrSquid, hbuf, sizeof(hdrSquid));
+ memcpy(&hdrSquid, hbuf, sizeof(hdrSquid));
hdr.length = hdrSquid.length;
hdr.opcode = hdrSquid.opcode;
hdr.response = hdrSquid.response;
htcpHandleMsg(buf, len, from);
- commSetSelect(fd, COMM_SELECT_READ, htcpRecv, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_READ, htcpRecv, NULL, 0);
}
/*
if (htcpOutSocket < 0)
fatal("Cannot open Outgoing HTCP Socket");
- commSetSelect(htcpOutSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
+ Comm::SetSelect(htcpOutSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
debugs(31, 1, "Outgoing HTCP messages on port " << Config.Port.htcp << ", FD " << htcpOutSocket << ".");
if (htcpInSocket < 0)
fatal("Cannot open HTCP Socket");
- commSetSelect(htcpInSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
+ Comm::SetSelect(htcpInSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
debugs(31, 1, "Accepting HTCP messages on port " << Config.Port.htcp << ", FD " << htcpInSocket << ".");
*/
assert(htcpOutSocket > -1);
- commSetSelect(htcpOutSocket, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(htcpOutSocket, COMM_SELECT_READ, NULL, NULL, 0);
}
void
entry->mem_obj->vary_headers = xstrdup(vary);
}
-#if WIP_FWD_LOG
- fwdStatus(fwd, s);
-
-#endif
/*
* If its not a reply that we will re-forward, then
* allow the client to get it.
HttpStateData::persistentConnStatus() const
{
debugs(11, 3, "persistentConnStatus: FD " << fd << " eof=" << eof);
- const HttpReply *vrep = virginReply();
- debugs(11, 5, "persistentConnStatus: content_length=" << vrep->content_length);
-
- /* If we haven't seen the end of reply headers, we are not done */
- debugs(11, 5, "persistentConnStatus: flags.headers_parsed=" << flags.headers_parsed);
-
- if (!flags.headers_parsed)
- return INCOMPLETE_MSG;
-
if (eof) // already reached EOF
return COMPLETE_NONPERSISTENT_MSG;
+ /* If server fd is closing (but we have not been notified yet), stop Comm
+ I/O to avoid assertions. TODO: Change Comm API to handle callers that
+ want more I/O after async closing (usually initiated by others). */
+ // XXX: add canReceive or s/canSend/canTalkToServer/
+ if (!canSend(fd))
+ return COMPLETE_NONPERSISTENT_MSG;
+
/** \par
* In chunked response we do not know the content length but we are absolutely
* sure about the end of response, so we are calling the statusIfComplete to
if (lastChunk && flags.chunked)
return statusIfComplete();
+ const HttpReply *vrep = virginReply();
+ debugs(11, 5, "persistentConnStatus: content_length=" << vrep->content_length);
+
const int64_t clen = vrep->bodySize(request->method);
debugs(11, 5, "persistentConnStatus: clen=" << clen);
/* Skip whitespace between replies */
while (len > 0 && xisspace(*buf))
- xmemmove(buf, buf + 1, len--);
+ memmove(buf, buf + 1, len--);
if (len == 0) {
/* Continue to read... */
if (len > MAX_PAYLOAD)
len = MAX_PAYLOAD;
- xmemcpy(echo->payload, payload, len);
+ memcpy(echo->payload, payload, len);
icmp_pktsize += len;
}
#include <netinet/ip_icmp.h>
#endif
-#ifndef _SQUID_LINUX_
-#ifndef _SQUID_CYGWIN_
-#ifndef _SQUID_MSWIN_
+#if !_SQUID_LINUX_ && !_SQUID_WINDOWS_
#define icmphdr icmp
#define iphdr ip
#endif
-#endif
-#endif
/* Linux uses its own field names. */
#if defined (_SQUID_LINUX_)
to use the native Windows port definitions.
*/
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
#include "fde.h"
#ifdef _SQUID_MSWIN_
if (len > MAX_PAYLOAD)
len = MAX_PAYLOAD;
- xmemcpy(echo->payload, payload, len);
+ memcpy(echo->payload, payload, len);
icmp6_pktsize += len;
}
return -1;
}
- xmemcpy(&wpi, buf, sizeof(wpi));
+ memcpy(&wpi, buf, sizeof(wpi));
write(1, "OK\n", 3);
x = read(0, buf, sizeof(PS));
return -1;
}
- xmemcpy(&PS, buf, sizeof(PS));
+ memcpy(&PS, buf, sizeof(PS));
icmp_sock = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &wpi, 0, 0);
*/
#include "squid.h"
+#include "comm.h"
+#include "comm/Loops.h"
#include "icmp/IcmpSquid.h"
#include "icmp/net_db.h"
#include "ip/tools.h"
-#include "comm.h"
#include "SquidTime.h"
// Instance global to be available in main() and elsewhere.
pecho.psize = len;
if (len > 0)
- xmemcpy(pecho.payload, payload, len);
+ memcpy(pecho.payload, payload, len);
slen = sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ + pecho.psize;
pingerReplyData preply;
static Ip::Address F;
- commSetSelect(icmp_sock, COMM_SELECT_READ, icmpSquidRecv, NULL, 0);
+ Comm::SetSelect(icmp_sock, COMM_SELECT_READ, icmpSquidRecv, NULL, 0);
memset(&preply, '\0', sizeof(pingerReplyData));
n = comm_udp_recv(icmp_sock,
(char *) &preply,
fd_note(icmp_sock, "pinger");
- commSetSelect(icmp_sock, COMM_SELECT_READ, icmpSquidRecv, NULL, 0);
+ Comm::SetSelect(icmp_sock, COMM_SELECT_READ, icmpSquidRecv, NULL, 0);
commSetTimeout(icmp_sock, -1, NULL, NULL);
n = (netdbEntry *)memAllocate(MEM_NETDBENTRY);
- xmemcpy(n, &N, sizeof(netdbEntry));
+ memcpy(n, &N, sizeof(netdbEntry));
netdbHashInsert(n, addr);
case NETDB_EX_NETWORK:
o++;
/* FIXME INET6 : NetDB can still ony send IPv4 */
- xmemcpy(&line_addr, p + o, sizeof(struct in_addr));
+ memcpy(&line_addr, p + o, sizeof(struct in_addr));
addr = line_addr;
o += sizeof(struct in_addr);
break;
case NETDB_EX_RTT:
o++;
- xmemcpy(&j, p + o, sizeof(int));
+ memcpy(&j, p + o, sizeof(int));
o += sizeof(int);
rtt = (double) ntohl(j) / 1000.0;
break;
case NETDB_EX_HOPS:
o++;
- xmemcpy(&j, p + o, sizeof(int));
+ memcpy(&j, p + o, sizeof(int));
o += sizeof(int);
hops = (double) ntohl(j) / 1000.0;
break;
buf[i++] = (char) NETDB_EX_NETWORK;
addr.GetInAddr(line_addr);
- xmemcpy(&buf[i], &line_addr, sizeof(struct in_addr));
+ memcpy(&buf[i], &line_addr, sizeof(struct in_addr));
i += sizeof(struct in_addr);
j = htonl((int) (n->rtt * 1000));
- xmemcpy(&buf[i], &j, sizeof(int));
+ memcpy(&buf[i], &j, sizeof(int));
i += sizeof(int);
j = htonl((int) (n->hops * 1000));
- xmemcpy(&buf[i], &j, sizeof(int));
+ memcpy(&buf[i], &j, sizeof(int));
i += sizeof(int);
#include "squid.h"
#include "Store.h"
#include "comm.h"
+#include "comm/Loops.h"
#include "ICP.h"
#include "HttpRequest.h"
#include "acl/FilledChecklist.h"
return;
}
- xmemcpy(this, buf, sizeof(icp_common_t));
+ memcpy(this, buf, sizeof(icp_common_t));
/*
* Convert network order sensitive fields
*/
if (opcode == ICP_QUERY)
urloffset += sizeof(uint32_t);
- xmemcpy(urloffset, url, strlen(url));
+ memcpy(urloffset, url, strlen(url));
return (icp_common_t *)buf;
}
IcpQueueTail = queue;
}
- commSetSelect(fd, COMM_SELECT_WRITE, icpUdpSendQueue, NULL, 0);
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, icpUdpSendQueue, NULL, 0);
statCounter.icp.replies_queued++;
} else {
/* don't queue it */
int len;
int icp_version;
int max = INCOMING_ICP_MAX;
- commSetSelect(sock, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
+ Comm::SetSelect(sock, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
while (max--) {
len = comm_udp_recvfrom(sock,
if (theOutIcpConnection < 0)
fatal("Cannot open Outgoing ICP Port");
- commSetSelect(theOutIcpConnection,
- COMM_SELECT_READ,
- icpHandleUdp,
- NULL,
- 0);
+ Comm::SetSelect(theOutIcpConnection, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
debugs(12, 1, "Outgoing ICP messages on port " << addr.GetPort() << ", FD " << theOutIcpConnection << ".");
if (theInIcpConnection < 0)
fatal("Cannot open ICP Port");
- commSetSelect(theInIcpConnection,
- COMM_SELECT_READ,
- icpHandleUdp,
- NULL,
- 0);
+ Comm::SetSelect(theInIcpConnection, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
for (const wordlist *s = Config.mcast_group_list; s; s = s->next)
ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL);
*/
assert(theOutIcpConnection > -1);
- commSetSelect(theOutIcpConnection, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(theOutIcpConnection, COMM_SELECT_READ, NULL, NULL, 0);
}
void
return len;
}
-const int
+int
Ip::Address::ApplyMask(Ip::Address const &mask_addr)
{
uint32_t *p1 = (uint32_t*)(&m_SocketAddr.sin6_addr);
/** Apply a mask to the stored address.
\param mask Netmask format to be bit-mask-AND'd over the stored address.
*/
- const int ApplyMask(const Address &mask);
+ int ApplyMask(const Address &mask);
/** Apply a mask to the stored address.
* CIDR will be converted appropriate to map the stored content.
#include "CacheManager.h"
#include "comm.h"
#include "ipc/Coordinator.h"
-#include "ipc/FdNotes.h"
#include "ipc/SharedListen.h"
#include "mgr/Inquirer.h"
#include "mgr/Request.h"
#include "mgr/Response.h"
-#include "mgr/StoreToCommWriter.h"
-
+#if SQUID_SNMP
+#include "snmp/Inquirer.h"
+#include "snmp/Request.h"
+#include "snmp/Response.h"
+#endif
CBDATA_NAMESPACED_CLASS_INIT(Ipc, Coordinator);
Ipc::Coordinator* Ipc::Coordinator::TheInstance = NULL;
handleSharedListenRequest(SharedListenRequest(message));
break;
- case mtCacheMgrRequest:
+ case mtCacheMgrRequest: {
debugs(54, 6, HERE << "Cache manager request");
- handleCacheMgrRequest(Mgr::Request(message));
- break;
+ const Mgr::Request req(message);
+ handleCacheMgrRequest(req);
+ }
+ break;
- case mtCacheMgrResponse:
+ case mtCacheMgrResponse: {
debugs(54, 6, HERE << "Cache manager response");
- handleCacheMgrResponse(Mgr::Response(message));
- break;
+ const Mgr::Response resp(message);
+ handleCacheMgrResponse(resp);
+ }
+ break;
+
+#if SQUID_SNMP
+ case mtSnmpRequest: {
+ debugs(54, 6, HERE << "SNMP request");
+ const Snmp::Request req(message);
+ handleSnmpRequest(req);
+ }
+ break;
+
+ case mtSnmpResponse: {
+ debugs(54, 6, HERE << "SNMP response");
+ const Snmp::Response resp(message);
+ handleSnmpResponse(resp);
+ }
+ break;
+#endif
default:
debugs(54, 1, HERE << "Unhandled message type: " << message.type());
Mgr::Action::Pointer action =
CacheManager::GetInstance()->createRequestedAction(request.params);
- AsyncJob::Start(new Mgr::Inquirer(action,
- Mgr::ImportHttpFdIntoComm(request.fd), request, strands_));
+ AsyncJob::Start(new Mgr::Inquirer(action, request, strands_));
}
void
Mgr::Inquirer::HandleRemoteAck(response);
}
+#if SQUID_SNMP
+void
+Ipc::Coordinator::handleSnmpRequest(const Snmp::Request& request)
+{
+ debugs(54, 4, HERE);
+
+ Snmp::Response response(request.requestId);
+ TypedMsgHdr message;
+ response.pack(message);
+ SendMessage(MakeAddr(strandAddrPfx, request.requestorId), message);
+
+ AsyncJob::Start(new Snmp::Inquirer(request, strands_));
+}
+
+void
+Ipc::Coordinator::handleSnmpResponse(const Snmp::Response& response)
+{
+ debugs(54, 4, HERE);
+ Snmp::Inquirer::HandleRemoteAck(response);
+}
+#endif
+
int
Ipc::Coordinator::openListenSocket(const SharedListenRequest& request,
int &errNo)
#include "ipc/SharedListen.h"
#include "ipc/StrandCoords.h"
#include "mgr/forward.h"
-
+#if SQUID_SNMP
+#include "snmp/forward.h"
+#endif
#include <map>
namespace Ipc
void handleSharedListenRequest(const SharedListenRequest& request);
void handleCacheMgrRequest(const Mgr::Request& request);
void handleCacheMgrResponse(const Mgr::Response& response);
-
+#if SQUID_SNMP
+ void handleSnmpRequest(const Snmp::Request& request);
+ void handleSnmpResponse(const Snmp::Response& response);
+#endif
/// calls comm_open_listener()
int openListenSocket(const SharedListenRequest& request, int &errNo);
"None", // fdnNone
"HTTP Socket", // fdnHttpSocket
"HTTPS Socket", // fdnHttpsSocket
+#if SQUID_SNMP
"Incoming SNMP Socket", // fdnInSnmpSocket
"Outgoing SNMP Socket", // fdnOutSnmpSocket
+#endif
"Incoming ICP Socket", // fdnInIcpSocket
"Incoming HTCP Socket" // fdnInHtcpSocket
};
/// fd_note() label ID
typedef enum { fdnNone, fdnHttpSocket, fdnHttpsSocket,
+#if SQUID_SNMP
fdnInSnmpSocket, fdnOutSnmpSocket,
+#endif
fdnInIcpSocket, fdnInHtcpSocket, fdnEnd
} FdNoteId;
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+#include "config.h"
+#include "base/AsyncJobCalls.h"
+#include "base/TextException.h"
+#include "ipc/Forwarder.h"
+#include "ipc/Port.h"
+#include "ipc/TypedMsgHdr.h"
+
+
+CBDATA_NAMESPACED_CLASS_INIT(Ipc, Forwarder);
+
+Ipc::Forwarder::RequestsMap Ipc::Forwarder::TheRequestsMap;
+unsigned int Ipc::Forwarder::LastRequestId = 0;
+
+Ipc::Forwarder::Forwarder(Request::Pointer aRequest, double aTimeout):
+ AsyncJob("Ipc::Forwarder"),
+ request(aRequest), timeout(aTimeout)
+{
+ debugs(54, 5, HERE);
+}
+
+Ipc::Forwarder::~Forwarder()
+{
+ debugs(54, 5, HERE);
+ Must(request->requestId == 0);
+ cleanup();
+}
+
+/// perform cleanup actions
+void
+Ipc::Forwarder::cleanup()
+{
+}
+
+void
+Ipc::Forwarder::start()
+{
+ debugs(54, 3, HERE);
+
+ typedef NullaryMemFunT<Forwarder> Dialer;
+ AsyncCall::Pointer callback = JobCallback(54, 5, Dialer, this, Forwarder::handleRemoteAck);
+ if (++LastRequestId == 0) // don't use zero value as request->requestId
+ ++LastRequestId;
+ request->requestId = LastRequestId;
+ TheRequestsMap[request->requestId] = callback;
+ TypedMsgHdr message;
+
+ try {
+ request->pack(message);
+ } catch (...) {
+ // assume the pack() call failed because the message did not fit
+ // TODO: add a more specific exception?
+ handleError();
+ }
+
+ SendMessage(coordinatorAddr, message);
+ eventAdd("Ipc::Forwarder::requestTimedOut", &Forwarder::RequestTimedOut,
+ this, timeout, 0, false);
+}
+
+void
+Ipc::Forwarder::swanSong()
+{
+ debugs(54, 5, HERE);
+ removeTimeoutEvent();
+ if (request->requestId > 0) {
+ DequeueRequest(request->requestId);
+ request->requestId = 0;
+ }
+ cleanup();
+}
+
+bool
+Ipc::Forwarder::doneAll() const
+{
+ debugs(54, 5, HERE);
+ return request->requestId == 0;
+}
+
+/// called when Coordinator starts processing the request
+void
+Ipc::Forwarder::handleRemoteAck()
+{
+ debugs(54, 3, HERE);
+ request->requestId = 0;
+}
+
+/// Ipc::Forwarder::requestTimedOut wrapper
+void
+Ipc::Forwarder::RequestTimedOut(void* param)
+{
+ debugs(54, 3, HERE);
+ Must(param != NULL);
+ Forwarder* fwdr = static_cast<Forwarder*>(param);
+ // use async call to enable job call protection that time events lack
+ CallJobHere(54, 5, fwdr, Forwarder, requestTimedOut);
+}
+
+/// called when Coordinator fails to start processing the request [in time]
+void
+Ipc::Forwarder::requestTimedOut()
+{
+ debugs(54, 3, HERE);
+ handleTimeout();
+}
+
+void
+Ipc::Forwarder::handleError()
+{
+ mustStop("error");
+}
+
+void
+Ipc::Forwarder::handleTimeout()
+{
+ mustStop("timeout");
+}
+
+/// terminate with an error
+void
+Ipc::Forwarder::handleException(const std::exception& e)
+{
+ debugs(54, 3, HERE << e.what());
+ mustStop("exception");
+}
+
+void
+Ipc::Forwarder::callException(const std::exception& e)
+{
+ try {
+ handleException(e);
+ } catch (const std::exception& ex) {
+ debugs(54, DBG_CRITICAL, HERE << ex.what());
+ }
+ AsyncJob::callException(e);
+}
+
+/// returns and forgets the right Forwarder callback for the request
+AsyncCall::Pointer
+Ipc::Forwarder::DequeueRequest(unsigned int requestId)
+{
+ debugs(54, 3, HERE);
+ Must(requestId != 0);
+ AsyncCall::Pointer call;
+ RequestsMap::iterator request = TheRequestsMap.find(requestId);
+ if (request != TheRequestsMap.end()) {
+ call = request->second;
+ Must(call != NULL);
+ TheRequestsMap.erase(request);
+ }
+ return call;
+}
+
+/// called when we are no longer waiting for Coordinator to respond
+void
+Ipc::Forwarder::removeTimeoutEvent()
+{
+ if (eventFind(&Forwarder::RequestTimedOut, this))
+ eventDelete(&Forwarder::RequestTimedOut, this);
+}
+
+void
+Ipc::Forwarder::HandleRemoteAck(unsigned int requestId)
+{
+ debugs(54, 3, HERE);
+ Must(requestId != 0);
+
+ AsyncCall::Pointer call = DequeueRequest(requestId);
+ if (call != NULL)
+ ScheduleCallHere(call);
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+#ifndef SQUID_IPC_FORWARDER_H
+#define SQUID_IPC_FORWARDER_H
+
+#include "base/AsyncJob.h"
+#include "ipc/Request.h"
+#include <map>
+
+
+namespace Ipc
+{
+
+/** Forwards a worker request to coordinator.
+ * Waits for an ACK from Coordinator
+ * Send the data unit with an error response if forwarding fails.
+ */
+class Forwarder: public AsyncJob
+{
+public:
+ Forwarder(Request::Pointer aRequest, double aTimeout);
+ virtual ~Forwarder();
+
+ /// finds and calls the right Forwarder upon Coordinator's response
+ static void HandleRemoteAck(unsigned int requestId);
+
+ /* has-to-be-public AsyncJob API */
+ virtual void callException(const std::exception& e);
+
+protected:
+ /* AsyncJob API */
+ virtual void start();
+ virtual void swanSong();
+ virtual bool doneAll() const;
+
+ virtual void cleanup(); ///< perform cleanup actions
+ virtual void handleError();
+ virtual void handleTimeout();
+ virtual void handleException(const std::exception& e);
+ virtual void handleRemoteAck();
+
+private:
+ static void RequestTimedOut(void* param);
+ void requestTimedOut();
+ void removeTimeoutEvent();
+ static AsyncCall::Pointer DequeueRequest(unsigned int requestId);
+
+protected:
+ Request::Pointer request;
+ const double timeout; ///< response wait timeout in seconds
+
+ /// maps request->id to Forwarder::handleRemoteAck callback
+ typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
+ static RequestsMap TheRequestsMap; ///< pending Coordinator requests
+
+ static unsigned int LastRequestId; ///< last requestId used
+
+ CBDATA_CLASS2(Forwarder);
+};
+
+} // namespace Ipc
+
+#endif /* SQUID_IPC_FORWARDER_H */
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+#include "config.h"
+#include "base/TextException.h"
+#include "comm/Write.h"
+#include "ipc/Inquirer.h"
+#include "ipc/Port.h"
+#include "ipc/TypedMsgHdr.h"
+#include "MemBuf.h"
+#include <algorithm>
+
+
+CBDATA_NAMESPACED_CLASS_INIT(Ipc, Inquirer);
+
+Ipc::Inquirer::RequestsMap Ipc::Inquirer::TheRequestsMap;
+unsigned int Ipc::Inquirer::LastRequestId = 0;
+
+/// compare Ipc::StrandCoord using kidId, for std::sort() below
+static bool
+LesserStrandByKidId(const Ipc::StrandCoord &c1, const Ipc::StrandCoord &c2)
+{
+ return c1.kidId < c2.kidId;
+}
+
+Ipc::Inquirer::Inquirer(Request::Pointer aRequest, const StrandCoords& coords,
+ double aTimeout):
+ AsyncJob("Ipc::Inquirer"),
+ request(aRequest), strands(coords), pos(strands.begin()), timeout(aTimeout)
+{
+ debugs(54, 5, HERE);
+
+ // order by ascending kid IDs; useful for non-aggregatable stats
+ std::sort(strands.begin(), strands.end(), LesserStrandByKidId);
+}
+
+Ipc::Inquirer::~Inquirer()
+{
+ debugs(54, 5, HERE);
+ cleanup();
+}
+
+void
+Ipc::Inquirer::cleanup()
+{
+}
+
+void
+Ipc::Inquirer::start()
+{
+ request->requestId = 0;
+}
+
+void
+Ipc::Inquirer::inquire()
+{
+ if (pos == strands.end()) {
+ Must(done());
+ return;
+ }
+
+ Must(request->requestId == 0);
+ AsyncCall::Pointer callback = asyncCall(54, 5, "Mgr::Inquirer::handleRemoteAck",
+ HandleAckDialer(this, &Inquirer::handleRemoteAck, NULL));
+ if (++LastRequestId == 0) // don't use zero value as request->requestId
+ ++LastRequestId;
+ request->requestId = LastRequestId;
+ const int kidId = pos->kidId;
+ debugs(54, 4, HERE << "inquire kid: " << kidId << status());
+ TheRequestsMap[request->requestId] = callback;
+ TypedMsgHdr message;
+ request->pack(message);
+ SendMessage(Port::MakeAddr(strandAddrPfx, kidId), message);
+ eventAdd("Ipc::Inquirer::requestTimedOut", &Inquirer::RequestTimedOut,
+ this, timeout, 0, false);
+}
+
+/// called when a strand is done writing its output
+void
+Ipc::Inquirer::handleRemoteAck(Response::Pointer response)
+{
+ debugs(54, 4, HERE << status());
+ request->requestId = 0;
+ removeTimeoutEvent();
+ if (aggregate(response)) {
+ Must(!done()); // or we should not be called
+ ++pos; // advance after a successful inquiry
+ inquire();
+ } else {
+ mustStop("error");
+ }
+}
+
+void
+Ipc::Inquirer::swanSong()
+{
+ debugs(54, 5, HERE);
+ removeTimeoutEvent();
+ if (request->requestId > 0) {
+ DequeueRequest(request->requestId);
+ request->requestId = 0;
+ }
+ sendResponse();
+ cleanup();
+}
+
+bool
+Ipc::Inquirer::doneAll() const
+{
+ return pos == strands.end();
+}
+
+void
+Ipc::Inquirer::handleException(const std::exception& e)
+{
+ debugs(54, 3, HERE << e.what());
+ mustStop("exception");
+}
+
+void
+Ipc::Inquirer::callException(const std::exception& e)
+{
+ debugs(54, 3, HERE);
+ try {
+ handleException(e);
+ } catch (const std::exception& ex) {
+ debugs(54, DBG_CRITICAL, HERE << ex.what());
+ }
+ AsyncJob::callException(e);
+}
+
+/// returns and forgets the right Inquirer callback for strand request
+AsyncCall::Pointer
+Ipc::Inquirer::DequeueRequest(unsigned int requestId)
+{
+ debugs(54, 3, HERE << " requestId " << requestId);
+ Must(requestId != 0);
+ AsyncCall::Pointer call;
+ RequestsMap::iterator request = TheRequestsMap.find(requestId);
+ if (request != TheRequestsMap.end()) {
+ call = request->second;
+ Must(call != NULL);
+ TheRequestsMap.erase(request);
+ }
+ return call;
+}
+
+void
+Ipc::Inquirer::HandleRemoteAck(const Response& response)
+{
+ Must(response.requestId != 0);
+ AsyncCall::Pointer call = DequeueRequest(response.requestId);
+ if (call != NULL) {
+ HandleAckDialer* dialer = dynamic_cast<HandleAckDialer*>(call->getDialer());
+ Must(dialer);
+ dialer->arg1 = response.clone();
+ ScheduleCallHere(call);
+ }
+}
+
+/// called when we are no longer waiting for the strand to respond
+void
+Ipc::Inquirer::removeTimeoutEvent()
+{
+ if (eventFind(&Inquirer::RequestTimedOut, this))
+ eventDelete(&Inquirer::RequestTimedOut, this);
+}
+
+/// Ipc::Inquirer::requestTimedOut wrapper
+void
+Ipc::Inquirer::RequestTimedOut(void* param)
+{
+ debugs(54, 3, HERE);
+ Must(param != NULL);
+ Inquirer* cmi = static_cast<Inquirer*>(param);
+ // use async call to enable job call protection that time events lack
+ CallJobHere(54, 5, cmi, Inquirer, requestTimedOut);
+}
+
+/// called when the strand failed to respond (or finish responding) in time
+void
+Ipc::Inquirer::requestTimedOut()
+{
+ debugs(54, 3, HERE);
+ if (request->requestId != 0) {
+ DequeueRequest(request->requestId);
+ request->requestId = 0;
+ Must(!done()); // or we should not be called
+ ++pos; // advance after a failed inquiry
+ inquire();
+ }
+}
+
+const char*
+Ipc::Inquirer::status() const
+{
+ static MemBuf buf;
+ buf.reset();
+ buf.Printf(" [request->requestId %u]", request->requestId);
+ buf.terminate();
+ return buf.content();
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+#ifndef SQUID_IPC_INQUIRER_H
+#define SQUID_IPC_INQUIRER_H
+
+#include "base/AsyncJobCalls.h"
+#include "base/AsyncJob.h"
+#include "ipc/forward.h"
+#include "ipc/Request.h"
+#include "ipc/Response.h"
+#include "ipc/StrandCoords.h"
+#include <map>
+
+
+namespace Ipc
+{
+
+/// Coordinator's job that sends a cache manage request to each strand,
+/// aggregating individual strand responses and dumping the result if needed
+class Inquirer: public AsyncJob
+{
+public:
+ Inquirer(Request::Pointer aRequest, const Ipc::StrandCoords& coords, double aTimeout);
+ virtual ~Inquirer();
+
+ /// finds and calls the right Inquirer upon strand's response
+ static void HandleRemoteAck(const Response& response);
+
+ /* has-to-be-public AsyncJob API */
+ virtual void callException(const std::exception& e);
+
+protected:
+ /* AsyncJob API */
+ virtual void start();
+ virtual void swanSong();
+ virtual bool doneAll() const;
+ virtual const char *status() const;
+
+ /// inquire the next strand
+ virtual void inquire();
+ /// perform cleanup actions on completion of job
+ virtual void cleanup();
+ /// do specific exception handling
+ virtual void handleException(const std::exception& e);
+ /// send response to client
+ virtual void sendResponse() = 0;
+ /// perform aggregating of responses and returns true if need to continue
+ virtual bool aggregate(Response::Pointer aResponse) = 0;
+
+private:
+ typedef UnaryMemFunT<Inquirer, Response::Pointer, Response::Pointer> HandleAckDialer;
+
+ void handleRemoteAck(Response::Pointer response);
+
+ static AsyncCall::Pointer DequeueRequest(unsigned int requestId);
+
+ static void RequestTimedOut(void* param);
+ void requestTimedOut();
+ void removeTimeoutEvent();
+
+protected:
+ Request::Pointer request; ///< cache manager request received from client
+
+ Ipc::StrandCoords strands; ///< all strands we want to query, in order
+ Ipc::StrandCoords::const_iterator pos; ///< strand we should query now
+
+ const double timeout; ///< number of seconds to wait for strand response
+
+ /// maps request->id to Inquirer::handleRemoteAck callback
+ typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
+ static RequestsMap TheRequestsMap; ///< pending strand requests
+
+ static unsigned int LastRequestId; ///< last requestId used
+
+ CBDATA_CLASS2(Inquirer);
+};
+
+} // namespace Ipc
+
+#endif /* SQUID_IPC_INQUIRER_H */
Port.h \
Strand.cc \
Strand.h \
- \
- forward.h
+ forward.h \
+ Forwarder.cc \
+ Forwarder.h \
+ Inquirer.cc \
+ Inquirer.h \
+ Request.h \
+ Response.h
DEFS += -DDEFAULT_PREFIX=\"$(prefix)\"
#ifndef SQUID_IPC_MESSAGES_H
#define SQUID_IPC_MESSAGES_H
-#include "ipc/forward.h"
-#include <sys/types.h>
-
-/** Declarations used by varios IPC messages */
+/** Declarations used by various IPC messages */
namespace Ipc
{
/// message class identifier
typedef enum { mtNone = 0, mtRegistration,
mtSharedListenRequest, mtSharedListenResponse,
- mtCacheMgrRequest, mtCacheMgrResponse
+ mtCacheMgrRequest, mtCacheMgrResponse,
+#if SQUID_SNMP
+ mtSnmpRequest, mtSnmpResponse
+#endif
} MessageType;
} // namespace Ipc;
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+#ifndef SQUID_IPC_REQUEST_H
+#define SQUID_IPC_REQUEST_H
+
+#include "ipc/forward.h"
+#include "RefCount.h"
+
+
+namespace Ipc
+{
+
+/// IPC request
+class Request: public RefCountable
+{
+public:
+ typedef RefCount<Request> Pointer;
+
+public:
+ Request(int aRequestorId, unsigned int aRequestId):
+ requestorId(aRequestorId), requestId(aRequestId) {}
+
+ virtual void pack(TypedMsgHdr& msg) const = 0; ///< prepare for sendmsg()
+ virtual Pointer clone() const = 0; ///< returns a copy of this
+
+private:
+ Request(const Request&); // not implemented
+ Request& operator= (const Request&); // not implemented
+
+public:
+ int requestorId; ///< kidId of the requestor; used for response destination
+ unsigned int requestId; ///< unique for sender; matches request w/ response
+};
+
+
+} // namespace Ipc
+
+#endif /* SQUID_IPC_REQUEST_H */
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+#ifndef SQUID_IPC_RESPONSE_H
+#define SQUID_IPC_RESPONSE_H
+
+#include "ipc/forward.h"
+#include "RefCount.h"
+
+
+namespace Ipc
+{
+
+/// A response to Ipc::Request.
+class Response: public RefCountable
+{
+public:
+ typedef RefCount<Response> Pointer;
+
+public:
+ explicit Response(unsigned int aRequestId):
+ requestId(aRequestId) {}
+
+ virtual void pack(TypedMsgHdr& msg) const = 0; ///< prepare for sendmsg()
+ virtual Pointer clone() const = 0; ///< returns a copy of this
+
+private:
+ Response(const Response&); // not implemented
+ Response& operator= (const Response&); // not implemented
+
+public:
+ unsigned int requestId; ///< ID of request we are responding to
+};
+
+inline
+std::ostream& operator << (std::ostream &os, const Response& response)
+{
+ os << "[response.requestId %u]" << response.requestId << '}';
+ return os;
+}
+
+
+} // namespace Ipc
+
+#endif /* SQUID_IPC_RESPONSE_H */
*/
#include "config.h"
-#include "comm.h"
#include "base/TextException.h"
+#include "comm.h"
#include "ipc/SharedListen.h"
#include "ipc/StartListening.h"
return os << "(FD " << fd << ", err=" << errNo;
}
-
-void Ipc::StartListening(int sock_type, int proto, Ip::Address &addr,
- int flags, FdNoteId fdNote, AsyncCall::Pointer &callback)
+void
+Ipc::StartListening(int sock_type, int proto, Ip::Address &addr, int flags,
+ FdNoteId fdNote, AsyncCall::Pointer &callback)
{
- OpenListenerParams p;
- p.sock_type = sock_type;
- p.proto = proto;
- p.addr = addr;
- p.flags = flags;
- p.fdNote = fdNote;
-
if (UsingSmp()) { // if SMP is on, share
+ OpenListenerParams p;
+ p.sock_type = sock_type;
+ p.proto = proto;
+ p.addr = addr;
+ p.flags = flags;
+ p.fdNote = fdNote;
Ipc::JoinSharedListen(p, callback);
return; // wait for the call back
}
+ StartListeningCb *cbd = dynamic_cast<StartListeningCb*>(callback->getDialer());
+ Must(cbd);
+
enter_suid();
- const int sock = comm_open_listener(p.sock_type, p.proto, p.addr, p.flags,
- FdNote(p.fdNote));
- const int errNo = (sock >= 0) ? 0 : errno;
+ cbd->fd = comm_open_listener(sock_type, proto, addr, flags, FdNote(fdNote));
+ cbd->errNo = cbd->fd >= 0 ? 0 : errno;
leave_suid();
- debugs(54, 3, HERE << "opened listen FD " << sock << " for " << p.addr);
-
- StartListeningCb *cbd =
- dynamic_cast<StartListeningCb*>(callback->getDialer());
- Must(cbd);
- cbd->fd = sock;
- cbd->errNo = errNo;
+ debugs(54, 3, HERE << "opened listen FD " << cbd->fd << " on " << addr);
ScheduleCallHere(callback);
}
#include "mgr/Response.h"
#include "mgr/Forwarder.h"
#include "CacheManager.h"
-
+#if SQUID_SNMP
+#include "snmp/Forwarder.h"
+#include "snmp/Request.h"
+#include "snmp/Response.h"
+#endif
CBDATA_NAMESPACED_CLASS_INIT(Ipc, Strand);
SharedListenJoined(SharedListenResponse(message));
break;
- case mtCacheMgrRequest:
- handleCacheMgrRequest(Mgr::Request(message));
- break;
+ case mtCacheMgrRequest: {
+ const Mgr::Request req(message);
+ handleCacheMgrRequest(req);
+ }
+ break;
- case mtCacheMgrResponse:
- handleCacheMgrResponse(Mgr::Response(message));
- break;
+ case mtCacheMgrResponse: {
+ const Mgr::Response resp(message);
+ handleCacheMgrResponse(resp);
+ }
+ break;
+
+#if SQUID_SNMP
+ case mtSnmpRequest: {
+ const Snmp::Request req(message);
+ handleSnmpRequest(req);
+ }
+ break;
+
+ case mtSnmpResponse: {
+ const Snmp::Response resp(message);
+ handleSnmpResponse(resp);
+ }
+ break;
+#endif
default:
debugs(54, 1, HERE << "Unhandled message type: " << message.type());
Mgr::Forwarder::HandleRemoteAck(response.requestId);
}
+#if SQUID_SNMP
+void Ipc::Strand::handleSnmpRequest(const Snmp::Request& request)
+{
+ debugs(54, 6, HERE);
+ Snmp::SendResponse(request.requestId, request.pdu);
+}
+
+void Ipc::Strand::handleSnmpResponse(const Snmp::Response& response)
+{
+ debugs(54, 6, HERE);
+ Snmp::Forwarder::HandleRemoteAck(response.requestId);
+}
+#endif
+
void Ipc::Strand::timedout()
{
debugs(54, 6, HERE << isRegistered);
#include "ipc/Port.h"
#include "mgr/forward.h"
-
+#if SQUID_SNMP
+#include "snmp/forward.h"
+#endif
namespace Ipc
{
void handleRegistrationResponse(const StrandCoord &strand);
void handleCacheMgrRequest(const Mgr::Request& request);
void handleCacheMgrResponse(const Mgr::Response& response);
+#if SQUID_SNMP
+ void handleSnmpRequest(const Snmp::Request& request);
+ void handleSnmpResponse(const Snmp::Response& response);
+#endif
private:
bool isRegistered; ///< whether Coordinator ACKed registration (unused)
Ipc::TypedMsgHdr::TypedMsgHdr(const TypedMsgHdr &tmh)
{
- xmemcpy(this, &tmh, sizeof(*this));
+ memcpy(this, &tmh, sizeof(*this));
sync();
}
Ipc::TypedMsgHdr &Ipc::TypedMsgHdr::operator =(const TypedMsgHdr &tmh)
{
if (this != &tmh) { // skip assignment to self
- xmemcpy(this, &tmh, sizeof(*this));
+ memcpy(this, &tmh, sizeof(*this));
sync();
}
return *this;
Must(size >= 0);
if (size > 0) {
Must(size <= data.size - offset);
- xmemcpy(raw, data.raw + offset, size);
+ memcpy(raw, data.raw + offset, size);
offset += size;
}
}
Must(size >= 0);
if (size > 0) {
Must(size <= sizeof(data.raw) - data.size);
- xmemcpy(data.raw + data.size, raw, size);
+ memcpy(data.raw + data.size, raw, size);
data.size += size;
}
}
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
int *fdStore = reinterpret_cast<int*>(CMSG_DATA(cmsg));
- xmemcpy(fdStore, &fd, fdCount * sizeof(int));
+ memcpy(fdStore, &fd, fdCount * sizeof(int));
msg_controllen = cmsg->cmsg_len;
}
const int fdCount = 1;
const int *fdStore = reinterpret_cast<const int*>(CMSG_DATA(cmsg));
int fd = -1;
- xmemcpy(&fd, fdStore, fdCount * sizeof(int));
+ memcpy(&fd, fdStore, fdCount * sizeof(int));
return fd;
}
void Ipc::UdsSender::wrote(const CommIoCbParams& params)
{
- debugs(54, 5, HERE << "FD " << params.fd << " flag " << params.flag << " [" << this << ']');
+ debugs(54, 5, HERE << "FD " << params.fd << " flag " << params.flag << " retries " << retries << " [" << this << ']');
writing = false;
if (params.flag != COMM_OK && retries-- > 0) {
sleep(1); // do not spend all tries at once; XXX: use an async timed event instead of blocking here; store the time when we started writing so that we do not sleep if not needed?
{
AsyncJob::Start(new UdsSender(toAddress, message));
}
+
+int Ipc::ImportFdIntoComm(int fd, int socktype, int protocol, Ipc::FdNoteId noteId)
+{
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+ if (getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
+ Ip::Address ipAddr(addr);
+ struct addrinfo* addr_info = NULL;
+ ipAddr.GetAddrInfo(addr_info);
+ addr_info->ai_socktype = socktype;
+ addr_info->ai_protocol = protocol;
+ comm_import_opened(fd, ipAddr, COMM_NONBLOCKING, Ipc::FdNote(noteId), addr_info);
+ ipAddr.FreeAddrInfo(addr_info);
+ } else {
+ debugs(54, DBG_CRITICAL, HERE << "ERROR: FD " << fd << ' ' << xstrerror());
+ ::close(fd);
+ fd = -1;
+ }
+ return fd;
+}
#include "SquidString.h"
#include "base/AsyncJob.h"
#include "ipc/TypedMsgHdr.h"
+#include "ipc/FdNotes.h"
class CommTimeoutCbParams;
class CommIoCbParams;
void SendMessage(const String& toAddress, const TypedMsgHdr& message);
+/// import socket fd from another strand into our Comm state
+int ImportFdIntoComm(int fd, int socktype, int protocol, FdNoteId noteId);
}
class TypedMsgHdr;
class StrandCoord;
+class Forwarder;
+class Inquirer;
+class Request;
+class Response;
} // namespace Ipc
else
thread_params.rfd = prfd_ipc;
- thread =
- (HANDLE) _beginthreadex(NULL, 0, ipc_thread_2, &thread_params, 0, NULL);
+ thread = (HANDLE)_beginthreadex(NULL, 0, ipc_thread_2, &thread_params, 0, NULL);
if (!thread) {
debugs(54, 0, "ipcCreate: CHILD: _beginthreadex: " << xstrerror());
extern int _dns_ttl_;
#endif
+/// \ingroup IPCacheInternal
+inline int ipcacheCount() { return ip_table ? ip_table->count : 0; }
+
int
ipcache_entry::age() const
{
eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
for (m = lru_list.tail; m; m = prev) {
- if (memInUse(MEM_IPCACHE_ENTRY) < ipcache_low)
+ if (ipcacheCount() < ipcache_low)
break;
prev = m->prev;
continue;
struct in_addr temp;
- xmemcpy(&temp, answers[k].rdata, sizeof(struct in_addr));
+ memcpy(&temp, answers[k].rdata, sizeof(struct in_addr));
i->addrs.in_addrs[j] = temp;
debugs(14, 3, "ipcacheParse: " << name << " #" << j << " " << i->addrs.in_addrs[j]);
continue;
struct in6_addr temp;
- xmemcpy(&temp, answers[k].rdata, sizeof(struct in6_addr));
+ memcpy(&temp, answers[k].rdata, sizeof(struct in6_addr));
i->addrs.in_addrs[j] = temp;
debugs(14, 3, "ipcacheParse: " << name << " #" << j << " " << i->addrs.in_addrs[j] );
dlink_node *m;
assert(ip_table != NULL);
storeAppendPrintf(sentry, "IP Cache Statistics:\n");
- storeAppendPrintf(sentry, "IPcache Entries: %d\n",
+ storeAppendPrintf(sentry, "IPcache Entries In Use: %d\n",
memInUse(MEM_IPCACHE_ENTRY));
+ storeAppendPrintf(sentry, "IPcache Entries Cached: %d\n",
+ ipcacheCount());
storeAppendPrintf(sentry, "IPcache Requests: %d\n",
IpcacheStats.requests);
storeAppendPrintf(sentry, "IPcache Hits: %d\n",
case IP_ENT:
Answer = snmp_var_new_integer(Var->name, Var->name_length,
- memInUse(MEM_IPCACHE_ENTRY),
+ ipcacheCount(),
SMI_GAUGE32);
break;
#include "config.h"
#include "log/Config.h"
+#include "log/Tokens.h"
+#include "protos.h"
Log::LogConfig Log::TheConfig;
+
+void
+Log::LogConfig::parseFormats()
+{
+ char *name, *def;
+
+ if ((name = strtok(NULL, w_space)) == NULL)
+ self_destruct();
+
+ if ((def = strtok(NULL, "\r\n")) == NULL) {
+ self_destruct();
+ return;
+ }
+
+ debugs(3, 2, "Logformat for '" << name << "' is '" << def << "'");
+
+ logformat *nlf = new logformat(name);
+
+ if (!accessLogParseLogFormat(&nlf->format, def)) {
+ self_destruct();
+ return;
+ }
+
+ // add to global config list
+ nlf->next = logformats;
+ logformats = nlf;
+}
#ifndef SQUID_SRC_LOG_CONFIG_H
#define SQUID_SRC_LOG_CONFIG_H
+#include "log/Tokens.h"
+
+class StoreEntry;
+
namespace Log
{
class LogConfig
{
public:
+ void parseFormats();
+ void dumpFormats(StoreEntry *e, const char *name) {
+ accessLogDumpLogFormat(e, name, logformats);
+ }
+
+ /// File path to logging daemon executable
char *logfile_daemon;
+
+ /// Linked list of custom log formats
+ logformat *logformats;
};
extern LogConfig TheConfig;
} // namespace Log
+// Legacy parsing wrappers
+#define parse_logformat(X) (X)->parseFormats()
+#define free_logformat(X) do{ delete (*X).logformats; (*X).logformats=NULL; }while(false)
+#define dump_logformat(E,N,D) (D).dumpFormats((E),(N))
+
#endif
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 46 Access Log - Apache combined format
+ * AUTHOR: Amos Jeffries
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * 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, USA.
+ *
+ */
+
+#include "config.h"
+#include "AccessLogEntry.h"
+#include "HttpRequest.h"
+#include "log/File.h"
+#include "log/Formats.h"
+#include "log/Gadgets.h"
+#include "log/Tokens.h"
+#include "SquidTime.h"
+
+void
+Log::Format::HttpdCombined(AccessLogEntry * al, Logfile * logfile)
+{
+ char clientip[MAX_IPSTRLEN];
+
+ const char *user_ident = FormatName(al->cache.rfc931);
+
+ const char *user_auth = FormatName(al->cache.authuser);
+
+ const char *referer = al->request->header.getStr(HDR_REFERER);
+ if (!referer || *referer == '\0')
+ referer = "-";
+
+ const char *agent = al->request->header.getStr(HDR_USER_AGENT);
+ if (!agent || *agent == '\0')
+ agent = "-";
+
+ logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %"PRId64" \"%s\" \"%s\" %s%s:%s%s",
+ al->cache.caddr.NtoA(clientip,MAX_IPSTRLEN),
+ user_ident ? user_ident : dash_str,
+ user_auth ? user_auth : dash_str,
+ Time::FormatHttpd(squid_curtime),
+ al->_private.method_str,
+ al->url,
+ al->http.version.major, al->http.version.minor,
+ al->http.code,
+ al->cache.replySize,
+ referer,
+ agent,
+ log_tags[al->cache.code],
+ al->http.statusSfx(),
+ hier_code_str[al->hier.code],
+ (Config.onoff.log_mime_hdrs?"":"\n"));
+
+ safe_free(user_ident);
+ safe_free(user_auth);
+
+ if (Config.onoff.log_mime_hdrs) {
+ char *ereq = QuoteMimeBlob(al->headers.request);
+ char *erep = QuoteMimeBlob(al->headers.reply);
+ logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
+ safe_free(ereq);
+ safe_free(erep);
+ }
+}
/*
* $Id$
*
- * DEBUG: section 40 User-Agent Logging
- * AUTHOR: Joe Ramey <ramey@csc.ti.com>
+ * DEBUG: section 46 Access Log - Apache common format
+ * AUTHOR: Duane Wessels
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
*/
-#include "squid.h"
+#include "config.h"
+#include "AccessLogEntry.h"
#include "log/File.h"
+#include "log/Formats.h"
+#include "log/Gadgets.h"
+#include "log/Tokens.h"
#include "SquidTime.h"
-#if USE_USERAGENT_LOG
-static Logfile *useragentlog = NULL;
-#endif
-
-void
-useragentOpenLog(void)
-{
-#if USE_USERAGENT_LOG
- assert(NULL == useragentlog);
-
- if (!Config.Log.useragent || (0 == strcmp(Config.Log.useragent, "none"))) {
- debugs(40, 1, "User-Agent logging is disabled.");
- return;
- }
-
- useragentlog = logfileOpen(Config.Log.useragent, 0, 1);
-#endif
-}
-
-void
-useragentRotateLog(void)
-{
-#if USE_USERAGENT_LOG
-
- if (NULL == useragentlog)
- return;
-
- logfileRotate(useragentlog);
-
-#endif
-}
-
void
-logUserAgent(const char *client, const char *agent)
+Log::Format::HttpdCommon(AccessLogEntry * al, Logfile * logfile)
{
-#if USE_USERAGENT_LOG
- static time_t last_time = 0;
- static char time_str[128];
- const char *s;
-
- if (NULL == useragentlog)
- return;
-
- if (squid_curtime != last_time) {
- s = mkhttpdlogtime(&squid_curtime);
- strcpy(time_str, s);
- last_time = squid_curtime;
+ char clientip[MAX_IPSTRLEN];
+ const char *user_auth = FormatName(al->cache.authuser);
+ const char *user_ident = FormatName(al->cache.rfc931);
+
+ logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %"PRId64" %s%s:%s%s",
+ al->cache.caddr.NtoA(clientip,MAX_IPSTRLEN),
+ user_ident ? user_ident : dash_str,
+ user_auth ? user_auth : dash_str,
+ Time::FormatHttpd(squid_curtime),
+ al->_private.method_str,
+ al->url,
+ al->http.version.major, al->http.version.minor,
+ al->http.code,
+ al->cache.replySize,
+ log_tags[al->cache.code],
+ al->http.statusSfx(),
+ hier_code_str[al->hier.code],
+ (Config.onoff.log_mime_hdrs?"":"\n"));
+
+ safe_free(user_auth);
+ safe_free(user_ident);
+
+ if (Config.onoff.log_mime_hdrs) {
+ char *ereq = QuoteMimeBlob(al->headers.request);
+ char *erep = QuoteMimeBlob(al->headers.reply);
+ logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
+ safe_free(ereq);
+ safe_free(erep);
}
-
- logfilePrintf(useragentlog, "%s [%s] \"%s\"\n",
- client,
- time_str,
- agent);
-#endif
-}
-
-void
-useragentLogClose(void)
-{
-#if USE_USERAGENT_LOG
-
- if (NULL == useragentlog)
- return;
-
- logfileClose(useragentlog);
-
- useragentlog = NULL;
-
-#endif
}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 46 Access Log - Squid Custom format
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * 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, USA.
+ *
+ */
+
+#include "config.h"
+#include "AccessLogEntry.h"
+#include "log/File.h"
+#include "log/Formats.h"
+#include "log/Gadgets.h"
+#include "log/Tokens.h"
+#include "SquidTime.h"
+
+#include "MemBuf.h"
+#include "HttpRequest.h"
+#include "rfc1738.h"
+#include "err_detail_type.h"
+#include "errorpage.h"
+
+static void
+log_quoted_string(const char *str, char *out)
+{
+ char *p = out;
+
+ while (*str) {
+ int l = strcspn(str, "\"\\\r\n\t");
+ memcpy(p, str, l);
+ str += l;
+ p += l;
+
+ switch (*str) {
+
+ case '\0':
+ break;
+
+ case '\r':
+ *p++ = '\\';
+ *p++ = 'r';
+ str++;
+ break;
+
+ case '\n':
+ *p++ = '\\';
+ *p++ = 'n';
+ str++;
+ break;
+
+ case '\t':
+ *p++ = '\\';
+ *p++ = 't';
+ str++;
+ break;
+
+ default:
+ *p++ = '\\';
+ *p++ = *str;
+ str++;
+ break;
+ }
+ }
+
+ *p++ = '\0';
+}
+
+void
+Log::Format::SquidCustom(AccessLogEntry * al, customlog * log)
+{
+ logformat *lf;
+ Logfile *logfile;
+ logformat_token *fmt;
+ static MemBuf mb;
+ char tmp[1024];
+ String sb;
+
+ mb.reset();
+
+ lf = log->logFormat;
+ logfile = log->logfile;
+
+ for (fmt = lf->format; fmt != NULL; fmt = fmt->next) { /* for each token */
+ const char *out = NULL;
+ int quote = 0;
+ long int outint = 0;
+ int doint = 0;
+ int dofree = 0;
+ int64_t outoff = 0;
+ int dooff = 0;
+
+ switch (fmt->type) {
+
+ case LFT_NONE:
+ out = "";
+ break;
+
+ case LFT_STRING:
+ out = fmt->data.string;
+ break;
+
+ case LFT_CLIENT_IP_ADDRESS:
+ if (al->cache.caddr.IsNoAddr()) // e.g., ICAP OPTIONS lack client
+ out = "-";
+ else
+ out = al->cache.caddr.NtoA(tmp,1024);
+ break;
+
+ case LFT_CLIENT_FQDN:
+ if (al->cache.caddr.IsAnyAddr()) // e.g., ICAP OPTIONS lack client
+ out = "-";
+ else
+ out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
+ if (!out) {
+ out = al->cache.caddr.NtoA(tmp,1024);
+ }
+
+ break;
+
+ case LFT_CLIENT_PORT:
+ if (al->request) {
+ outint = al->request->client_addr.GetPort();
+ doint = 1;
+ }
+ break;
+
+#if USE_SQUID_EUI
+ case LFT_CLIENT_EUI:
+ if (al->request) {
+ if (al->cache.caddr.IsIPv4())
+ al->request->client_eui48.encode(tmp, 1024);
+ else
+ al->request->client_eui64.encode(tmp, 1024);
+ out = tmp;
+ }
+ break;
+#endif
+
+ /* case LFT_SERVER_IP_ADDRESS: */
+
+ case LFT_SERVER_IP_OR_PEER_NAME:
+ out = al->hier.host;
+
+ break;
+
+ /* case LFT_SERVER_PORT: */
+
+ case LFT_LOCAL_IP:
+ if (al->request) {
+ out = al->request->my_addr.NtoA(tmp,1024);
+ }
+
+ break;
+
+ case LFT_LOCAL_PORT:
+ if (al->request) {
+ outint = al->request->my_addr.GetPort();
+ doint = 1;
+ }
+
+ break;
+
+ case LFT_PEER_LOCAL_PORT:
+ if (al->hier.peer_local_port) {
+ outint = al->hier.peer_local_port;
+ doint = 1;
+ }
+
+ break;
+
+ case LFT_TIME_SECONDS_SINCE_EPOCH:
+ // some platforms store time in 32-bit, some 64-bit...
+ outoff = static_cast<int64_t>(current_time.tv_sec);
+ dooff = 1;
+ break;
+
+ case LFT_TIME_SUBSECOND:
+ outint = current_time.tv_usec / fmt->divisor;
+ doint = 1;
+ break;
+
+
+ case LFT_TIME_LOCALTIME:
+
+ case LFT_TIME_GMT: {
+ const char *spec;
+
+ struct tm *t;
+ spec = fmt->data.timespec;
+
+ if (fmt->type == LFT_TIME_LOCALTIME) {
+ if (!spec)
+ spec = "%d/%b/%Y:%H:%M:%S %z";
+ t = localtime(&squid_curtime);
+ } else {
+ if (!spec)
+ spec = "%d/%b/%Y:%H:%M:%S";
+
+ t = gmtime(&squid_curtime);
+ }
+
+ strftime(tmp, sizeof(tmp), spec, t);
+
+ out = tmp;
+ }
+
+ break;
+
+ case LFT_TIME_TO_HANDLE_REQUEST:
+ outint = al->cache.msec;
+ doint = 1;
+ break;
+
+ case LFT_PEER_RESPONSE_TIME:
+ if (al->hier.peer_response_time < 0) {
+ out = "-";
+ } else {
+ outoff = al->hier.peer_response_time;
+ dooff = 1;
+ }
+ break;
+
+ case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME:
+ if (al->hier.total_response_time < 0) {
+ out = "-";
+ } else {
+ outoff = al->hier.total_response_time;
+ dooff = 1;
+ }
+ break;
+
+ case LFT_DNS_WAIT_TIME:
+ if (al->request && al->request->dnsWait >= 0) {
+ outint = al->request->dnsWait;
+ doint = 1;
+ }
+ break;
+
+ case LFT_REQUEST_HEADER:
+
+ if (al->request)
+ sb = al->request->header.getByName(fmt->data.header.header);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTED_REQUEST_HEADER:
+
+ if (al->request)
+ sb = al->adapted_request->header.getByName(fmt->data.header.header);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_REPLY_HEADER:
+ if (al->reply)
+ sb = al->reply->header.getByName(fmt->data.header.header);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+#if USE_ADAPTATION
+ case LTF_ADAPTATION_SUM_XACT_TIMES:
+ if (al->request) {
+ Adaptation::History::Pointer ah = al->request->adaptHistory();
+ if (ah != NULL)
+ ah->sumLogString(fmt->data.string, sb);
+ out = sb.termedBuf();
+ }
+ break;
+
+ case LTF_ADAPTATION_ALL_XACT_TIMES:
+ if (al->request) {
+ Adaptation::History::Pointer ah = al->request->adaptHistory();
+ if (ah != NULL)
+ ah->allLogString(fmt->data.string, sb);
+ out = sb.termedBuf();
+ }
+ break;
+#endif
+
+#if ICAP_CLIENT
+ case LFT_ICAP_LAST_MATCHED_HEADER:
+ if (al->request) {
+ Adaptation::Icap::History::Pointer ih = al->request->icapHistory();
+ if (ih != NULL)
+ sb = ih->mergeOfIcapHeaders.getByName(fmt->data.header.header);
+ }
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ICAP_LAST_MATCHED_HEADER_ELEM:
+ if (al->request) {
+ Adaptation::Icap::History::Pointer ih = al->request->icapHistory();
+ if (ih != NULL)
+ sb = ih->mergeOfIcapHeaders.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+ }
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ICAP_LAST_MATCHED_ALL_HEADERS:
+ out = al->headers.icap;
+
+ quote = 1;
+
+ break;
+
+ case LFT_ICAP_ADDR:
+ if (!out)
+ out = al->icap.hostAddr.NtoA(tmp,1024);
+ break;
+
+ case LFT_ICAP_SERV_NAME:
+ out = al->icap.serviceName.termedBuf();
+ break;
+
+ case LFT_ICAP_REQUEST_URI:
+ out = al->icap.reqUri.termedBuf();
+ break;
+
+ case LFT_ICAP_REQUEST_METHOD:
+ out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod);
+ break;
+
+ case LFT_ICAP_BYTES_SENT:
+ outoff = al->icap.bytesSent;
+ dooff = 1;
+ break;
+
+ case LFT_ICAP_BYTES_READ:
+ outoff = al->icap.bytesRead;
+ dooff = 1;
+ break;
+
+ case LFT_ICAP_BODY_BYTES_READ:
+ if (al->icap.bodyBytesRead >= 0) {
+ outoff = al->icap.bodyBytesRead;
+ dooff = 1;
+ }
+ // else if icap.bodyBytesRead < 0, we do not have any http data,
+ // so just print a "-" (204 responses etc)
+ break;
+
+ case LFT_ICAP_REQ_HEADER:
+ if (NULL != al->icap.request) {
+ sb = al->icap.request->header.getByName(fmt->data.header.header);
+ out = sb.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_ICAP_REQ_HEADER_ELEM:
+ if (al->request)
+ sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ICAP_REQ_ALL_HEADERS:
+ if (al->icap.request) {
+ HttpHeaderPos pos = HttpHeaderInitPos;
+ while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) {
+ sb.append(e->name);
+ sb.append(": ");
+ sb.append(e->value);
+ sb.append("\r\n");
+ }
+ out = sb.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_ICAP_REP_HEADER:
+ if (NULL != al->icap.reply) {
+ sb = al->icap.reply->header.getByName(fmt->data.header.header);
+ out = sb.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_ICAP_REP_HEADER_ELEM:
+ if (NULL != al->icap.reply)
+ sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ICAP_REP_ALL_HEADERS:
+ if (al->icap.reply) {
+ HttpHeaderPos pos = HttpHeaderInitPos;
+ while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) {
+ sb.append(e->name);
+ sb.append(": ");
+ sb.append(e->value);
+ sb.append("\r\n");
+ }
+ out = sb.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_ICAP_TR_RESPONSE_TIME:
+ outint = al->icap.trTime;
+ doint = 1;
+ break;
+
+ case LFT_ICAP_IO_TIME:
+ outint = al->icap.ioTime;
+ doint = 1;
+ break;
+
+ case LFT_ICAP_STATUS_CODE:
+ outint = al->icap.resStatus;
+ doint = 1;
+ break;
+
+ case LFT_ICAP_OUTCOME:
+ out = al->icap.outcome;
+ break;
+
+ case LFT_ICAP_TOTAL_TIME:
+ outint = al->icap.processingTime;
+ doint = 1;
+ break;
+#endif
+ case LFT_REQUEST_HEADER_ELEM:
+ if (al->request)
+ sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+ if (al->adapted_request)
+ sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_REPLY_HEADER_ELEM:
+ if (al->reply)
+ sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_REQUEST_ALL_HEADERS:
+ out = al->headers.request;
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+ out = al->headers.adapted_request;
+
+ quote = 1;
+
+ break;
+
+ case LFT_REPLY_ALL_HEADERS:
+ out = al->headers.reply;
+
+ quote = 1;
+
+ break;
+
+ case LFT_USER_NAME:
+ out = Log::FormatName(al->cache.authuser);
+
+ if (!out)
+ out = Log::FormatName(al->cache.extuser);
+
+#if USE_SSL
+
+ if (!out)
+ out = Log::FormatName(al->cache.ssluser);
+
+#endif
+
+ if (!out)
+ out = Log::FormatName(al->cache.rfc931);
+
+ dofree = 1;
+
+ break;
+
+ case LFT_USER_LOGIN:
+ out = Log::FormatName(al->cache.authuser);
+
+ dofree = 1;
+
+ break;
+
+ case LFT_USER_IDENT:
+ out = Log::FormatName(al->cache.rfc931);
+
+ dofree = 1;
+
+ break;
+
+ case LFT_USER_EXTERNAL:
+ out = Log::FormatName(al->cache.extuser);
+
+ dofree = 1;
+
+ break;
+
+ /* case LFT_USER_REALM: */
+ /* case LFT_USER_SCHEME: */
+
+ // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
+ // but compiler complains if ommited
+ case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
+ case LFT_HTTP_SENT_STATUS_CODE:
+ outint = al->http.code;
+
+ doint = 1;
+
+ break;
+
+ case LFT_HTTP_RECEIVED_STATUS_CODE:
+ if (al->hier.peer_reply_status == HTTP_STATUS_NONE) {
+ out = "-";
+ } else {
+ outint = al->hier.peer_reply_status;
+ doint = 1;
+ }
+ break;
+ /* case LFT_HTTP_STATUS:
+ * out = statusline->text;
+ * quote = 1;
+ * break;
+ */
+ case LFT_HTTP_BODY_BYTES_READ:
+ if (al->hier.bodyBytesRead >= 0) {
+ outoff = al->hier.bodyBytesRead;
+ dooff = 1;
+ }
+ // else if hier.bodyBytesRead < 0 we did not have any data exchange with
+ // a peer server so just print a "-" (eg requests served from cache,
+ // or internal error messages).
+ break;
+
+ case LFT_SQUID_STATUS:
+ if (al->http.timedout || al->http.aborted) {
+ snprintf(tmp, sizeof(tmp), "%s%s", log_tags[al->cache.code],
+ al->http.statusSfx());
+ out = tmp;
+ } else {
+ out = log_tags[al->cache.code];
+ }
+
+ break;
+
+ case LFT_SQUID_ERROR:
+ if (al->request && al->request->errType != ERR_NONE)
+ out = errorPageName(al->request->errType);
+ break;
+
+ case LFT_SQUID_ERROR_DETAIL:
+ if (al->request && al->request->errDetail != ERR_DETAIL_NONE) {
+ if (al->request->errDetail > ERR_DETAIL_START &&
+ al->request->errDetail < ERR_DETAIL_MAX)
+ out = errorDetailName(al->request->errDetail);
+ else {
+ if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START)
+ snprintf(tmp, sizeof(tmp), "%s=0x%X",
+ errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail);
+ else
+ snprintf(tmp, sizeof(tmp), "%s=%d",
+ errorDetailName(al->request->errDetail), al->request->errDetail);
+ out = tmp;
+ }
+ }
+ break;
+
+ case LFT_SQUID_HIERARCHY:
+ if (al->hier.ping.timedout)
+ mb.append("TIMEOUT_", 8);
+
+ out = hier_code_str[al->hier.code];
+
+ break;
+
+ case LFT_MIME_TYPE:
+ out = al->http.content_type;
+
+ break;
+
+ case LFT_REQUEST_METHOD:
+ out = al->_private.method_str;
+
+ break;
+
+ case LFT_REQUEST_URI:
+ out = al->url;
+
+ break;
+
+ case LFT_REQUEST_URLPATH:
+ if (al->request) {
+ out = al->request->urlpath.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_REQUEST_VERSION:
+ snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
+ out = tmp;
+ break;
+
+ case LFT_REQUEST_SIZE_TOTAL:
+ outoff = al->cache.requestSize;
+ dooff = 1;
+ break;
+
+ /*case LFT_REQUEST_SIZE_LINE: */
+ case LFT_REQUEST_SIZE_HEADERS:
+ outoff = al->cache.requestHeadersSize;
+ dooff =1;
+ break;
+ /*case LFT_REQUEST_SIZE_BODY: */
+ /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
+
+ case LFT_REPLY_SIZE_TOTAL:
+ outoff = al->cache.replySize;
+ dooff = 1;
+ break;
+
+ case LFT_REPLY_HIGHOFFSET:
+ outoff = al->cache.highOffset;
+
+ dooff = 1;
+
+ break;
+
+ case LFT_REPLY_OBJECTSIZE:
+ outoff = al->cache.objectSize;
+
+ dooff = 1;
+
+ break;
+
+ /*case LFT_REPLY_SIZE_LINE: */
+ case LFT_REPLY_SIZE_HEADERS:
+ outint = al->cache.replyHeadersSize;
+ doint = 1;
+ break;
+ /*case LFT_REPLY_SIZE_BODY: */
+ /*case LFT_REPLY_SIZE_BODY_NO_TE: */
+
+ case LFT_TAG:
+ if (al->request)
+ out = al->request->tag.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_IO_SIZE_TOTAL:
+ outint = al->cache.requestSize + al->cache.replySize;
+ doint = 1;
+ break;
+
+ case LFT_EXT_LOG:
+ if (al->request)
+ out = al->request->extacl_log.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_SEQUENCE_NUMBER:
+ outoff = logfile->sequence_number;
+ dooff = 1;
+ break;
+
+ case LFT_PERCENT:
+ out = "%";
+
+ break;
+ }
+
+ if (dooff) {
+ snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero ? (int) fmt->width : 0, outoff);
+ out = tmp;
+
+ } else if (doint) {
+ snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint);
+ out = tmp;
+ }
+
+ if (out && *out) {
+ if (quote || fmt->quote != LOG_QUOTE_NONE) {
+ char *newout = NULL;
+ int newfree = 0;
+
+ switch (fmt->quote) {
+
+ case LOG_QUOTE_NONE:
+ newout = rfc1738_escape_unescaped(out);
+ break;
+
+ case LOG_QUOTE_QUOTES: {
+ size_t out_len = static_cast<size_t>(strlen(out)) * 2 + 1;
+ if (out_len >= sizeof(tmp)) {
+ newout = (char *)xmalloc(out_len);
+ newfree = 1;
+ } else
+ newout = tmp;
+ log_quoted_string(out, newout);
+ }
+ break;
+
+ case LOG_QUOTE_MIMEBLOB:
+ newout = Log::QuoteMimeBlob(out);
+ newfree = 1;
+ break;
+
+ case LOG_QUOTE_URL:
+ newout = rfc1738_escape(out);
+ break;
+
+ case LOG_QUOTE_RAW:
+ break;
+ }
+
+ if (newout) {
+ if (dofree)
+ safe_free(out);
+
+ out = newout;
+
+ dofree = newfree;
+ }
+ }
+
+ if (fmt->width) {
+ if (fmt->left)
+ mb.Printf("%-*s", (int) fmt->width, out);
+ else
+ mb.Printf("%*s", (int) fmt->width, out);
+ } else
+ mb.append(out, strlen(out));
+ } else {
+ mb.append("-", 1);
+ }
+
+ if (fmt->space)
+ mb.append(" ", 1);
+
+ sb.clean();
+
+ if (dofree)
+ safe_free(out);
+ }
+
+ logfilePrintf(logfile, "%s\n", mb.buf);
+}
/*
* $Id$
*
- * DEBUG: section 40 Referer Logging
- * AUTHOR: Joe Ramey <ramey@csc.ti.com> (useragent)
- * Jens-S. Vöckler <voeckler@rvs.uni-hannover.de> (mod 4 referer)
+ * DEBUG: section 46 Access Log - Squid ICAP Logging
+ * AUTHOR: Alex Rousskov
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
*/
-#include "squid.h"
+#include "config.h"
+
+#if ICAP_CLIENT
+
+#include "AccessLogEntry.h"
+#include "HttpRequest.h"
#include "log/File.h"
+#include "log/Formats.h"
+#include "log/Gadgets.h"
#include "SquidTime.h"
-#if USE_REFERER_LOG
-static Logfile *refererlog = NULL;
-#endif
-
void
-refererOpenLog(void)
+Log::Format::SquidIcap(AccessLogEntry * al, Logfile * logfile)
{
-#if USE_REFERER_LOG
- assert(NULL == refererlog);
-
- if (!Config.Log.referer || (0 == strcmp(Config.Log.referer, "none"))) {
- debugs(40, 1, "Referer logging is disabled.");
- return;
+ const char *client = NULL;
+ const char *user = NULL;
+ char tmp[MAX_IPSTRLEN], clientbuf[MAX_IPSTRLEN];
+
+ if (al->cache.caddr.IsAnyAddr()) { // ICAP OPTIONS xactions lack client
+ client = "-";
+ } else {
+ if (Config.onoff.log_fqdn)
+ client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
+ if (!client)
+ client = al->cache.caddr.NtoA(clientbuf, MAX_IPSTRLEN);
}
- refererlog = logfileOpen(Config.Log.referer, 0, 1);
-#endif
-}
-
-void
-refererRotateLog(void)
-{
-#if USE_REFERER_LOG
-
- if (NULL == refererlog)
- return;
+ user = Log::FormatName(al->cache.authuser);
- logfileRotate(refererlog);
+ if (!user)
+ user = Log::FormatName(al->cache.extuser);
+#if USE_SSL
+ if (!user)
+ user = Log::FormatName(al->cache.ssluser);
#endif
-}
-void
-logReferer(const char *client, const char *referer, const char *uri)
-{
-#if USE_REFERER_LOG
+ if (!user)
+ user = Log::FormatName(al->cache.rfc931);
- if (NULL == refererlog)
- return;
+ if (user && !*user)
+ safe_free(user);
- logfilePrintf(refererlog, "%9d.%03d %s %s %s\n",
- (int) current_time.tv_sec,
+ logfilePrintf(logfile, "%9ld.%03d %6d %s -/%03d %"PRId64" %s %s %s -/%s -\n",
+ (long int) current_time.tv_sec,
(int) current_time.tv_usec / 1000,
+ al->icap.trTime,
client,
- referer,
- uri ? uri : "-");
-
-#endif
+ al->icap.resStatus,
+ al->icap.bytesRead,
+ Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod),
+ al->icap.reqUri.termedBuf(),
+ user ? user : "-",
+ al->icap.hostAddr.NtoA(tmp, MAX_IPSTRLEN));
+ safe_free(user);
}
-
-void
-refererCloseLog(void)
-{
-#if USE_REFERER_LOG
-
- if (NULL == refererlog)
- return;
-
- logfileClose(refererlog);
-
- refererlog = NULL;
-
#endif
-}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 46 Access Log - Squid format
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * 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, USA.
+ *
+ */
+
+#include "config.h"
+#include "AccessLogEntry.h"
+#include "log/File.h"
+#include "log/Formats.h"
+#include "log/Gadgets.h"
+#include "log/Tokens.h"
+#include "SquidTime.h"
+
+void
+Log::Format::SquidNative(AccessLogEntry * al, Logfile * logfile)
+{
+ const char *user = NULL;
+ char clientip[MAX_IPSTRLEN];
+
+ user = FormatName(al->cache.authuser);
+
+ if (!user)
+ user = FormatName(al->cache.extuser);
+
+#if USE_SSL
+ if (!user)
+ user = FormatName(al->cache.ssluser);
+#endif
+
+ if (!user)
+ user = FormatName(al->cache.rfc931);
+
+ if (user && !*user)
+ safe_free(user);
+
+ logfilePrintf(logfile, "%9ld.%03d %6d %s %s%s/%03d %"PRId64" %s %s %s %s%s/%s %s%s",
+ (long int) current_time.tv_sec,
+ (int) current_time.tv_usec / 1000,
+ al->cache.msec,
+ al->cache.caddr.NtoA(clientip, MAX_IPSTRLEN),
+ log_tags[al->cache.code],
+ al->http.statusSfx(),
+ al->http.code,
+ al->cache.replySize,
+ al->_private.method_str,
+ al->url,
+ user ? user : dash_str,
+ al->hier.ping.timedout ? "TIMEOUT_" : "",
+ hier_code_str[al->hier.code],
+ al->hier.host,
+ al->http.content_type,
+ (Config.onoff.log_mime_hdrs?"":"\n"));
+
+ safe_free(user);
+
+ if (Config.onoff.log_mime_hdrs) {
+ char *ereq = QuoteMimeBlob(al->headers.request);
+ char *erep = QuoteMimeBlob(al->headers.reply);
+ logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
+ safe_free(ereq);
+ safe_free(erep);
+ }
+}
-
/*
* $Id$
*
+ * DEBUG: section 46 Access Log - Squid referer format
+ * AUTHOR: Joe Ramey <ramey@csc.ti.com> (useragent)
+ * Jens-S. V?ckler <voeckler@rvs.uni-hannover.de> (mod 4 referer)
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
*/
-#ifndef SQUID_COMM_EPOLL_H
-#define SQUID_COMM_EPOLL_H
+#include "config.h"
+#include "AccessLogEntry.h"
+#include "HttpRequest.h"
+#include "log/File.h"
+#include "log/Formats.h"
+#include "SquidTime.h"
+
+void
+Log::Format::SquidReferer(AccessLogEntry *al, Logfile *logfile)
+{
+ const char *referer = al->request->header.getStr(HDR_REFERER);
+
+ // do not log unless there is something to be displayed
+ if (!referer || *referer == '\0')
+ return;
+
+ char clientip[MAX_IPSTRLEN];
-#endif /* SQUID_COMM_EPOLL_H */
+ logfilePrintf(logfile, "%9ld.%03d %s %s %s\n",
+ (long int) current_time.tv_sec,
+ (int) current_time.tv_usec / 1000,
+ al->cache.caddr.NtoA(clientip, MAX_IPSTRLEN),
+ referer,
+ al->url ? al->url : "-");
+}
-
/*
* $Id$
*
+ * DEBUG: section 46 Access Log - Squid useragent format
+ * AUTHOR: Joe Ramey <ramey@csc.ti.com>
+ * AUTHOR: Amos Jeffries <amosjeffries@squid-cache.org>
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
*/
-#ifndef SQUID_COMM_SELECT_H
-#define SQUID_COMM_SELECT_H
+#include "config.h"
+#include "AccessLogEntry.h"
+#include "HttpRequest.h"
+#include "log/File.h"
+#include "log/Formats.h"
+#include "SquidTime.h"
+
+void
+Log::Format::SquidUserAgent(AccessLogEntry * al, Logfile * logfile)
+{
+ char clientip[MAX_IPSTRLEN];
+
+ const char *agent = al->request->header.getStr(HDR_USER_AGENT);
+ // do not log unless there is something to be displayed.
+ if (!agent || *agent == '\0')
+ return;
-#endif /* SQUID_COMM_SELECT_H */
+ logfilePrintf(logfile, "%s [%s] \"%s\"\n",
+ al->cache.caddr.NtoA(clientip,MAX_IPSTRLEN),
+ Time::FormatHttpd(squid_curtime),
+ agent);
+}
--- /dev/null
+#ifndef _SQUID_LOG_FORMATS_H
+#define _SQUID_LOG_FORMATS_H
+
+class AccessLogEntry;
+class Logfile;
+
+namespace Log
+{
+
+namespace Format
+{
+
+typedef enum {
+ CLF_UNKNOWN,
+ CLF_COMBINED,
+ CLF_COMMON,
+ CLF_CUSTOM,
+#if ICAP_CLIENT
+ CLF_ICAP_SQUID,
+#endif
+ CLF_REFERER,
+ CLF_SQUID,
+ CLF_USERAGENT,
+ CLF_NONE
+} log_type;
+
+/// Native Squid Format Display
+void SquidNative(AccessLogEntry * al, Logfile * logfile);
+
+/// Display log details in Squid ICAP format.
+void SquidIcap(AccessLogEntry * al, Logfile * logfile);
+
+/// Display log details in useragent format.
+void SquidUserAgent(AccessLogEntry * al, Logfile * logfile);
+
+/// Display log details in Squid old refererlog format.
+void SquidReferer(AccessLogEntry * al, Logfile * logfile);
+
+/// Log with a local custom format
+void SquidCustom(AccessLogEntry * al, customlog * log);
+
+/// Log with Apache httpd common format
+void HttpdCommon(AccessLogEntry * al, Logfile * logfile);
+
+/// Log with Apache httpd combined format
+void HttpdCombined(AccessLogEntry * al, Logfile * logfile);
+
+}; // namespace Format
+}; // namespace Log
+
+#endif /* _SQUID_LOG_FORMATS_H */
--- /dev/null
+#include "config.h"
+#include "log/Gadgets.h"
+
+static const char c2x[] =
+ "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
+
+#if DEAD_USING_QUOTEMIMEBLOB
+/** copy of Log::QuoteMimeBlob. Bugs there will be found here.
+ * This omits [] characters but is otherwise identical to Log::QuoteMimeBlob when OLD_LOG_MIME = 1
+ */
+static char *
+username_quote(const char *header)
+{
+ int c;
+ int i;
+ char *buf;
+ char *buf_cursor;
+
+ if (header == NULL) {
+ buf = static_cast<char *>(xcalloc(1, 1));
+ *buf = '\0';
+ return buf;
+ }
+
+ buf = static_cast<char *>(xcalloc(1, (strlen(header) * 3) + 1));
+ buf_cursor = buf;
+ /*
+ * We escape: space \x00-\x1F and space (0x40) and \x7F-\xFF
+ * to prevent garbage in the logs. CR and LF are also there just in case.
+ */
+
+ while ((c = *(const unsigned char *) header++) != '\0') {
+ if (c == '\r') {
+ *buf_cursor++ = '\\';
+ *buf_cursor++ = 'r';
+ } else if (c == '\n') {
+ *buf_cursor++ = '\\';
+ *buf_cursor++ = 'n';
+ } else if (c <= 0x1F
+ || c >= 0x7F
+ || c == '%'
+ || c == ' ') {
+ *buf_cursor++ = '%';
+ i = c * 2;
+ *buf_cursor++ = c2x[i];
+ *buf_cursor++ = c2x[i + 1];
+ } else {
+ *buf_cursor++ = (char) c;
+ }
+ }
+
+ *buf_cursor = '\0';
+ return buf;
+}
+#endif // DEAD
+
+char *
+Log::FormatName(const char *name)
+{
+ if (NULL == name)
+ return NULL;
+
+ if (name[0] == '\0')
+ return NULL;
+
+ return QuoteMimeBlob(name);
+// return username_quote(name);
+}
+
+char *
+Log::QuoteMimeBlob(const char *header)
+{
+ int c;
+ int i;
+ char *buf;
+ char *buf_cursor;
+
+ if (header == NULL) {
+ buf = static_cast<char *>(xcalloc(1, 1));
+ *buf = '\0';
+ return buf;
+ }
+
+ buf = static_cast<char *>(xcalloc(1, (strlen(header) * 3) + 1));
+ buf_cursor = buf;
+ /**
+ * Whe OLD_LOG_MIME is defined we escape: \x00-\x1F"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF
+ * which is the default escape list for the CPAN Perl5 URI module
+ * modulo the inclusion of space (x40) to make the raw logs a bit
+ * more readable.
+ */
+
+ while ((c = *(const unsigned char *) header++) != '\0') {
+#if !OLD_LOG_MIME
+ if (c == '\r') {
+ *buf_cursor++ = '\\';
+ *buf_cursor++ = 'r';
+ } else if (c == '\n') {
+ *buf_cursor++ = '\\';
+ *buf_cursor++ = 'n';
+ } else
+#endif
+ if (c <= 0x1F
+ || c >= 0x7F
+ || c == '%'
+#if OLD_LOG_MIME
+ || c == '"'
+ || c == '#'
+ || c == ';'
+ || c == '<'
+ || c == '>'
+ || c == '?'
+ || c == '{'
+ || c == '}'
+ || c == '|'
+ || c == '\\'
+ || c == '^'
+ || c == '~'
+ || c == '`'
+#endif
+ || c == '['
+ || c == ']') {
+ *buf_cursor++ = '%';
+ i = c * 2;
+ *buf_cursor++ = c2x[i];
+ *buf_cursor++ = c2x[i + 1];
+#if !OLD_LOG_MIME
+
+ } else if (c == '\\') {
+ *buf_cursor++ = '\\';
+ *buf_cursor++ = '\\';
+#endif
+
+ } else {
+ *buf_cursor++ = (char) c;
+ }
+ }
+
+ *buf_cursor = '\0';
+ return buf;
+}
--- /dev/null
+#ifndef _SQUID_LOG_GADGETS_H
+#define _SQUID_LOG_GADGETS_H
+
+namespace Log
+{
+
+/// Safely URL-encode a username.
+/// Accepts NULL or empty strings.
+char * FormatName(const char *name);
+
+/** URL-style encoding on a MIME headers blob.
+ * May accept NULL or empty strings.
+ * \return A dynamically allocated string. recipient is responsible for free()'ing
+ */
+char *QuoteMimeBlob(const char *header);
+
+}; // namespace Log
+
+#endif /* _SQUID_LOG_GADGETS_H */
Config.h \
File.cc \
File.h \
+ FormatHttpdCombined.cc \
+ FormatHttpdCommon.cc \
+ Formats.h \
+ FormatSquidCustom.cc \
+ FormatSquidIcap.cc \
+ FormatSquidNative.cc \
+ FormatSquidReferer.cc \
+ FormatSquidUseragent.cc \
+ Gadgets.cc \
+ Gadgets.h \
ModDaemon.cc \
ModDaemon.h \
ModStdio.cc \
ModTcp.cc \
ModTcp.h \
ModUdp.cc \
- ModUdp.h
+ ModUdp.h \
+ Tokens.cc \
+ Tokens.h
+
#include "squid.h"
#include "cbdata.h"
+#include "comm/Loops.h"
#include "fde.h"
#include "log/Config.h"
#include "log/File.h"
/* there is, so schedule more */
reschedule:
- commSetSelect(ll->wfd, COMM_SELECT_WRITE, logfileHandleWrite, lf, 0);
+ Comm::SetSelect(ll->wfd, COMM_SELECT_WRITE, logfileHandleWrite, lf, 0);
ll->flush_pending = 1;
finish:
return;
logfile_mod_daemon_append(lf, "F\n", 2);
}
/* Ok, schedule a write-event */
- commSetSelect(ll->wfd, COMM_SELECT_WRITE, logfileHandleWrite, lf, 0);
+ Comm::SetSelect(ll->wfd, COMM_SELECT_WRITE, logfileHandleWrite, lf, 0);
}
static void
b = static_cast<logfile_buffer_t*>(ll->bufs.tail->data);
debugs(50, 3, "logfile_mod_daemon_append: current buffer has " << b->len << " of " << b->size << " bytes before append");
s = min(len, (b->size - b->len));
- xmemcpy(b->buf + b->len, buf, s);
+ memcpy(b->buf + b->len, buf, s);
len = len - s;
buf = buf + s;
b->len = b->len + s;
return;
}
/* buffer it */
- xmemcpy(ll->buf + ll->offset, buf, len);
+ memcpy(ll->buf + ll->offset, buf, len);
ll->offset += len;
return;
}
/* buffer it */
- xmemcpy(ll->buf + ll->offset, buf, len);
+ memcpy(ll->buf + ll->offset, buf, len);
ll->offset += len;
return;
}
/* buffer it */
- xmemcpy(ll->buf + ll->offset, buf, len);
+ memcpy(ll->buf + ll->offset, buf, len);
ll->offset += len;
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 46 Access Log Format Tokens
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * 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, USA.
+ *
+ */
+
+#include "config.h"
+#include "log/Tokens.h"
+#include "Store.h"
+
+const char *log_tags[] = {
+ "NONE",
+ "TCP_HIT",
+ "TCP_MISS",
+ "TCP_REFRESH_UNMODIFIED",
+ "TCP_REFRESH_FAIL", // same tag logged for LOG_TCP_REFRESH_FAIL_OLD and
+ "TCP_REFRESH_FAIL", // LOG_TCP_REFRESH_FAIL_ERR for backward-compatibility
+ "TCP_REFRESH_MODIFIED",
+ "TCP_CLIENT_REFRESH_MISS",
+ "TCP_IMS_HIT",
+ "TCP_SWAPFAIL_MISS",
+ "TCP_NEGATIVE_HIT",
+ "TCP_MEM_HIT",
+ "TCP_DENIED",
+ "TCP_DENIED_REPLY",
+ "TCP_OFFLINE_HIT",
+#if LOG_TCP_REDIRECTS
+ "TCP_REDIRECT",
+#endif
+ "UDP_HIT",
+ "UDP_MISS",
+ "UDP_DENIED",
+ "UDP_INVALID",
+ "UDP_MISS_NOFETCH",
+ "ICP_QUERY",
+ "LOG_TYPE_MAX"
+};
+
+#if USE_ADAPTATION
+bool alLogformatHasAdaptToken = false;
+#endif
+
+#if ICAP_CLIENT
+bool alLogformatHasIcapToken = false;
+#endif
+
+struct logformat_token_table_entry logformat_token_table[] = {
+
+ {">a", LFT_CLIENT_IP_ADDRESS},
+ {">p", LFT_CLIENT_PORT},
+ {">A", LFT_CLIENT_FQDN},
+#if USE_SQUID_EUI
+ {">eui", LFT_CLIENT_EUI},
+#endif
+
+ /*{ "<a", LFT_SERVER_IP_ADDRESS }, */
+ /*{ "<p", LFT_SERVER_PORT }, */
+ {"<A", LFT_SERVER_IP_OR_PEER_NAME},
+
+ /* {"oa", LFT_OUTGOING_IP}, */
+ /* {"ot", LFT_OUTGOING_TOS}, */
+
+ {"la", LFT_LOCAL_IP},
+ {"lp", LFT_LOCAL_PORT},
+ /*{ "lA", LFT_LOCAL_NAME }, */
+ {"<lp", LFT_PEER_LOCAL_PORT},
+
+ {"ts", LFT_TIME_SECONDS_SINCE_EPOCH},
+ {"tu", LFT_TIME_SUBSECOND},
+ {"tl", LFT_TIME_LOCALTIME},
+ {"tg", LFT_TIME_GMT},
+ {"tr", LFT_TIME_TO_HANDLE_REQUEST},
+
+ {"<pt", LFT_PEER_RESPONSE_TIME},
+ {"<tt", LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME},
+ {"dt", LFT_DNS_WAIT_TIME},
+
+ {">ha", LFT_ADAPTED_REQUEST_HEADER},
+ {">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS},
+ {">h", LFT_REQUEST_HEADER},
+ {">h", LFT_REQUEST_ALL_HEADERS},
+ {"<h", LFT_REPLY_HEADER},
+ {"<h", LFT_REPLY_ALL_HEADERS},
+
+ {"un", LFT_USER_NAME},
+ {"ul", LFT_USER_LOGIN},
+ /*{ "ur", LFT_USER_REALM }, */
+ /*{ "us", LFT_USER_SCHEME }, */
+ {"ui", LFT_USER_IDENT},
+ {"ue", LFT_USER_EXTERNAL},
+
+ {"Hs", LFT_HTTP_SENT_STATUS_CODE_OLD_30},
+ {">Hs", LFT_HTTP_SENT_STATUS_CODE},
+ {"<Hs", LFT_HTTP_RECEIVED_STATUS_CODE},
+ /*{ "Ht", LFT_HTTP_STATUS }, */
+ {"<bs", LFT_HTTP_BODY_BYTES_READ},
+
+ {"Ss", LFT_SQUID_STATUS},
+ { "err_code", LFT_SQUID_ERROR },
+ { "err_detail", LFT_SQUID_ERROR_DETAIL },
+ {"Sh", LFT_SQUID_HIERARCHY},
+
+ {"mt", LFT_MIME_TYPE},
+
+ {"rm", LFT_REQUEST_METHOD},
+ {"ru", LFT_REQUEST_URI}, /* doesn't include the query-string */
+ {"rp", LFT_REQUEST_URLPATH}, /* doesn't include the host */
+ /* { "rq", LFT_REQUEST_QUERY }, * / / * the query-string, INCLUDING the leading ? */
+ {">v", LFT_REQUEST_VERSION},
+ {"rv", LFT_REQUEST_VERSION},
+
+ { ">st", LFT_REQUEST_SIZE_TOTAL },
+ /*{ ">sl", LFT_REQUEST_SIZE_LINE }, * / / * the request line "GET ... " */
+ { ">sh", LFT_REQUEST_SIZE_HEADERS },
+ /*{ ">sb", LFT_REQUEST_SIZE_BODY }, */
+ /*{ ">sB", LFT_REQUEST_SIZE_BODY_NO_TE }, */
+
+ {"<st", LFT_REPLY_SIZE_TOTAL},
+ {"<sH", LFT_REPLY_HIGHOFFSET},
+ {"<sS", LFT_REPLY_OBJECTSIZE},
+ /*{ "<sl", LFT_REPLY_SIZE_LINE }, * / / * the reply line (protocol, code, text) */
+ { "<sh", LFT_REPLY_SIZE_HEADERS },
+ /*{ "<sb", LFT_REPLY_SIZE_BODY }, */
+ /*{ "<sB", LFT_REPLY_SIZE_BODY_NO_TE }, */
+
+ {"et", LFT_TAG},
+ {"st", LFT_IO_SIZE_TOTAL},
+ {"ea", LFT_EXT_LOG},
+ {"sn", LFT_SEQUENCE_NUMBER},
+
+ {"%", LFT_PERCENT},
+
+#if USE_ADAPTATION
+ {"adapt::all_trs", LTF_ADAPTATION_ALL_XACT_TIMES},
+ {"adapt::sum_trs", LTF_ADAPTATION_SUM_XACT_TIMES},
+#endif
+
+#if ICAP_CLIENT
+ {"icap::tt", LFT_ICAP_TOTAL_TIME},
+ {"icap::<last_h", LFT_ICAP_LAST_MATCHED_HEADER},
+
+ {"icap::<A", LFT_ICAP_ADDR},
+ {"icap::<service_name", LFT_ICAP_SERV_NAME},
+ {"icap::ru", LFT_ICAP_REQUEST_URI},
+ {"icap::rm", LFT_ICAP_REQUEST_METHOD},
+ {"icap::>st", LFT_ICAP_BYTES_SENT},
+ {"icap::<st", LFT_ICAP_BYTES_READ},
+ {"icap::<bs", LFT_ICAP_BODY_BYTES_READ},
+
+ {"icap::>h", LFT_ICAP_REQ_HEADER},
+ {"icap::<h", LFT_ICAP_REP_HEADER},
+
+ {"icap::tr", LFT_ICAP_TR_RESPONSE_TIME},
+ {"icap::tio", LFT_ICAP_IO_TIME},
+ {"icap::to", LFT_ICAP_OUTCOME},
+ {"icap::Hs", LFT_ICAP_STATUS_CODE},
+#endif
+
+ {NULL, LFT_NONE} /* this must be last */
+};
+
+/* parses a single token. Returns the token length in characters,
+ * and fills in the lt item with the token information.
+ * def is for sure null-terminated
+ */
+int
+accessLogGetNewLogFormatToken(logformat_token * lt, char *def, enum log_quote *quote)
+{
+ char *cur = def;
+
+ struct logformat_token_table_entry *lte;
+ int l;
+
+ memset(lt, 0, sizeof(*lt));
+ l = strcspn(cur, "%");
+
+ if (l > 0) {
+ char *cp;
+ /* it's a string for sure, until \0 or the next % */
+ cp = (char *)xmalloc(l + 1);
+ xstrncpy(cp, cur, l + 1);
+ lt->type = LFT_STRING;
+ lt->data.string = cp;
+
+ while (l > 0) {
+ switch (*cur) {
+
+ case '"':
+
+ if (*quote == LOG_QUOTE_NONE)
+ *quote = LOG_QUOTE_QUOTES;
+ else if (*quote == LOG_QUOTE_QUOTES)
+ *quote = LOG_QUOTE_NONE;
+
+ break;
+
+ case '[':
+ if (*quote == LOG_QUOTE_NONE)
+ *quote = LOG_QUOTE_MIMEBLOB;
+
+ break;
+
+ case ']':
+ if (*quote == LOG_QUOTE_MIMEBLOB)
+ *quote = LOG_QUOTE_NONE;
+
+ break;
+ }
+
+ cur++;
+ l--;
+ }
+
+ goto done;
+ }
+
+ if (!*cur)
+ goto done;
+
+ cur++;
+
+ switch (*cur) {
+
+ case '"':
+ lt->quote = LOG_QUOTE_QUOTES;
+ cur++;
+ break;
+
+ case '\'':
+ lt->quote = LOG_QUOTE_RAW;
+ cur++;
+ break;
+
+ case '[':
+ lt->quote = LOG_QUOTE_MIMEBLOB;
+ cur++;
+ break;
+
+ case '#':
+ lt->quote = LOG_QUOTE_URL;
+ cur++;
+ break;
+
+ default:
+ lt->quote = *quote;
+ break;
+ }
+
+ if (*cur == '-') {
+ lt->left = 1;
+ cur++;
+ }
+
+ if (*cur == '0') {
+ lt->zero = 1;
+ cur++;
+ }
+
+ if (xisdigit(*cur))
+ lt->width = strtol(cur, &cur, 10);
+
+ if (*cur == '.')
+ lt->precision = strtol(cur + 1, &cur, 10);
+
+ if (*cur == '{') {
+ char *cp;
+ cur++;
+ l = strcspn(cur, "}");
+ cp = (char *)xmalloc(l + 1);
+ xstrncpy(cp, cur, l + 1);
+ lt->data.string = cp;
+ cur += l;
+
+ if (*cur == '}')
+ cur++;
+ }
+
+ // For upward compatibility, assume "http::" prefix as default prefix
+ // for all log access formating codes, except those starting
+ // from "icap::", "adapt::" and "%"
+ if (strncmp(cur,"http::", 6) == 0 &&
+ strncmp(cur+6, "icap::", 6) != 0 &&
+ strncmp(cur+6, "adapt::", 12) != 0 && *(cur+6) != '%' ) {
+ cur += 6;
+ }
+
+ lt->type = LFT_NONE;
+
+ for (lte = logformat_token_table; lte->config != NULL; lte++) {
+ if (strncmp(lte->config, cur, strlen(lte->config)) == 0) {
+ lt->type = lte->token_type;
+ cur += strlen(lte->config);
+ break;
+ }
+ }
+
+ if (lt->type == LFT_NONE) {
+ fatalf("Can't parse configuration token: '%s'\n",
+ def);
+ }
+
+ if (*cur == ' ') {
+ lt->space = 1;
+ cur++;
+ }
+
+done:
+
+ switch (lt->type) {
+
+#if ICAP_CLIENT
+ case LFT_ICAP_LAST_MATCHED_HEADER:
+
+ case LFT_ICAP_REQ_HEADER:
+
+ case LFT_ICAP_REP_HEADER:
+#endif
+
+ case LFT_ADAPTED_REQUEST_HEADER:
+
+ case LFT_REQUEST_HEADER:
+
+ case LFT_REPLY_HEADER:
+
+ if (lt->data.string) {
+ char *header = lt->data.string;
+ char *cp = strchr(header, ':');
+
+ if (cp) {
+ *cp++ = '\0';
+
+ if (*cp == ',' || *cp == ';' || *cp == ':')
+ lt->data.header.separator = *cp++;
+ else
+ lt->data.header.separator = ',';
+
+ lt->data.header.element = cp;
+
+ switch (lt->type) {
+ case LFT_REQUEST_HEADER:
+ lt->type = LFT_REQUEST_HEADER_ELEM;
+ break;
+
+ case LFT_ADAPTED_REQUEST_HEADER:
+ lt->type = LFT_ADAPTED_REQUEST_HEADER_ELEM;
+ break;
+
+ case LFT_REPLY_HEADER:
+ lt->type = LFT_REPLY_HEADER_ELEM;
+ break;
+#if ICAP_CLIENT
+ case LFT_ICAP_LAST_MATCHED_HEADER:
+ lt->type = LFT_ICAP_LAST_MATCHED_HEADER_ELEM;
+ break;
+ case LFT_ICAP_REQ_HEADER:
+ lt->type = LFT_ICAP_REQ_HEADER_ELEM;
+ break;
+ case LFT_ICAP_REP_HEADER:
+ lt->type = LFT_ICAP_REP_HEADER_ELEM;
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+
+ lt->data.header.header = header;
+ } else {
+ switch (lt->type) {
+ case LFT_REQUEST_HEADER:
+ lt->type = LFT_REQUEST_ALL_HEADERS;
+ break;
+
+ case LFT_ADAPTED_REQUEST_HEADER:
+ lt->type = LFT_ADAPTED_REQUEST_ALL_HEADERS;
+ break;
+
+ case LFT_REPLY_HEADER:
+ lt->type = LFT_REPLY_ALL_HEADERS;
+ break;
+#if ICAP_CLIENT
+ case LFT_ICAP_LAST_MATCHED_HEADER:
+ lt->type = LFT_ICAP_LAST_MATCHED_ALL_HEADERS;
+ break;
+ case LFT_ICAP_REQ_HEADER:
+ lt->type = LFT_ICAP_REQ_ALL_HEADERS;
+ break;
+ case LFT_ICAP_REP_HEADER:
+ lt->type = LFT_ICAP_REP_ALL_HEADERS;
+ break;
+#endif
+ default:
+ break;
+ }
+ Config.onoff.log_mime_hdrs = 1;
+ }
+
+ break;
+
+ case LFT_CLIENT_FQDN:
+ Config.onoff.log_fqdn = 1;
+ break;
+
+ case LFT_TIME_SUBSECOND:
+ lt->divisor = 1000;
+
+ if (lt->precision) {
+ int i;
+ lt->divisor = 1000000;
+
+ for (i = lt->precision; i > 1; i--)
+ lt->divisor /= 10;
+
+ if (!lt->divisor)
+ lt->divisor = 0;
+ }
+
+ break;
+
+ case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
+ debugs(46, 0, "WARNING: the \"Hs\" formating code is deprecated use the \">Hs\" instead");
+ lt->type = LFT_HTTP_SENT_STATUS_CODE;
+ break;
+ default:
+ break;
+ }
+
+ return (cur - def);
+}
+
+int
+accessLogParseLogFormat(logformat_token ** fmt, char *def)
+{
+ char *cur, *eos;
+ logformat_token *new_lt, *last_lt;
+ enum log_quote quote = LOG_QUOTE_NONE;
+
+ debugs(46, 2, "accessLogParseLogFormat: got definition '" << def << "'");
+
+ /* very inefficent parser, but who cares, this needs to be simple */
+ /* First off, let's tokenize, we'll optimize in a second pass.
+ * A token can either be a %-prefixed sequence (usually a dynamic
+ * token but it can be an escaped sequence), or a string. */
+ cur = def;
+ eos = def + strlen(def);
+ *fmt = new_lt = last_lt = (logformat_token *)xmalloc(sizeof(logformat_token));
+ cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
+
+ while (cur < eos) {
+ new_lt = (logformat_token *)xmalloc(sizeof(logformat_token));
+ last_lt->next = new_lt;
+ last_lt = new_lt;
+ cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
+ }
+
+ return 1;
+}
+
+void
+accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions)
+{
+ logformat_token *t;
+ logformat *format;
+
+ struct logformat_token_table_entry *te;
+ debugs(46, 4, "accessLogDumpLogFormat called");
+
+ for (format = definitions; format; format = format->next) {
+ debugs(46, 3, "Dumping logformat definition for " << format->name);
+ storeAppendPrintf(entry, "logformat %s ", format->name);
+
+ for (t = format->format; t; t = t->next) {
+ if (t->type == LFT_STRING)
+ storeAppendPrintf(entry, "%s", t->data.string);
+ else {
+ char argbuf[256];
+ char *arg = NULL;
+ logformat_bcode_t type = t->type;
+
+ switch (type) {
+ /* special cases */
+
+ case LFT_STRING:
+ break;
+#if ICAP_CLIENT
+ case LFT_ICAP_LAST_MATCHED_HEADER_ELEM:
+ case LFT_ICAP_REQ_HEADER_ELEM:
+ case LFT_ICAP_REP_HEADER_ELEM:
+#endif
+ case LFT_REQUEST_HEADER_ELEM:
+ case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+ case LFT_REPLY_HEADER_ELEM:
+
+ if (t->data.header.separator != ',')
+ snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element);
+ else
+ snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element);
+
+ arg = argbuf;
+
+ switch (type) {
+ case LFT_REQUEST_HEADER_ELEM:
+ type = LFT_REQUEST_HEADER_ELEM;
+ break;
+ case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+ type = LFT_ADAPTED_REQUEST_HEADER_ELEM;
+ break;
+ case LFT_REPLY_HEADER_ELEM:
+ type = LFT_REPLY_HEADER_ELEM;
+ break;
+#if ICAP_CLIENT
+ case LFT_ICAP_LAST_MATCHED_HEADER_ELEM:
+ type = LFT_ICAP_LAST_MATCHED_HEADER;
+ break;
+ case LFT_ICAP_REQ_HEADER_ELEM:
+ type = LFT_ICAP_REQ_HEADER;
+ break;
+ case LFT_ICAP_REP_HEADER_ELEM:
+ type = LFT_ICAP_REP_HEADER;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ break;
+
+ case LFT_REQUEST_ALL_HEADERS:
+ case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+ case LFT_REPLY_ALL_HEADERS:
+
+#if ICAP_CLIENT
+ case LFT_ICAP_LAST_MATCHED_ALL_HEADERS:
+ case LFT_ICAP_REQ_ALL_HEADERS:
+ case LFT_ICAP_REP_ALL_HEADERS:
+#endif
+
+ switch (type) {
+ case LFT_REQUEST_ALL_HEADERS:
+ type = LFT_REQUEST_HEADER;
+ break;
+ case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+ type = LFT_ADAPTED_REQUEST_HEADER;
+ break;
+ case LFT_REPLY_ALL_HEADERS:
+ type = LFT_REPLY_HEADER;
+ break;
+#if ICAP_CLIENT
+ case LFT_ICAP_LAST_MATCHED_ALL_HEADERS:
+ type = LFT_ICAP_LAST_MATCHED_HEADER;
+ break;
+ case LFT_ICAP_REQ_ALL_HEADERS:
+ type = LFT_ICAP_REQ_HEADER;
+ break;
+ case LFT_ICAP_REP_ALL_HEADERS:
+ type = LFT_ICAP_REP_HEADER;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ break;
+
+ default:
+ if (t->data.string)
+ arg = t->data.string;
+
+ break;
+ }
+
+ entry->append("%", 1);
+
+ switch (t->quote) {
+
+ case LOG_QUOTE_QUOTES:
+ entry->append("\"", 1);
+ break;
+
+ case LOG_QUOTE_MIMEBLOB:
+ entry->append("[", 1);
+ break;
+
+ case LOG_QUOTE_URL:
+ entry->append("#", 1);
+ break;
+
+ case LOG_QUOTE_RAW:
+ entry->append("'", 1);
+ break;
+
+ case LOG_QUOTE_NONE:
+ break;
+ }
+
+ if (t->left)
+ entry->append("-", 1);
+
+ if (t->zero)
+ entry->append("0", 1);
+
+ if (t->width)
+ storeAppendPrintf(entry, "%d", (int) t->width);
+
+ if (t->precision)
+ storeAppendPrintf(entry, ".%d", (int) t->precision);
+
+ if (arg)
+ storeAppendPrintf(entry, "{%s}", arg);
+
+ for (te = logformat_token_table; te->config != NULL; te++) {
+ if (te->token_type == type) {
+ storeAppendPrintf(entry, "%s", te->config);
+ break;
+ }
+ }
+
+ if (t->space)
+ entry->append(" ", 1);
+
+ assert(te->config != NULL);
+ }
+ }
+
+ entry->append("\n", 1);
+ }
+
+}
+
+void
+accessLogFreeLogFormat(logformat_token ** tokens)
+{
+ while (*tokens) {
+ logformat_token *token = *tokens;
+ *tokens = token->next;
+ safe_free(token->data.string);
+ xfree(token);
+ }
+}
+
+logformat::logformat(const char *n) :
+ format(NULL),
+ next(NULL)
+{
+ name = xstrdup(n);
+}
+
+logformat::~logformat()
+{
+ // erase the list without consuming stack space
+ while (next) {
+ // unlink the next entry for deletion
+ logformat *temp = next;
+ next = temp->next;
+ temp->next = NULL;
+ delete temp;
+ }
+
+ // remove locals
+ xfree(name);
+ accessLogFreeLogFormat(&format);
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 46 Access Log
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * 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, USA.
+ *
+ */
+#ifndef _SQUID_LOG_TOKENS_H
+#define _SQUID_LOG_TOKENS_H
+
+class StoreEntry;
+
+#define LOG_BUF_SZ (MAX_URL<<2)
+
+/*
+ * Bytecodes for the configureable logformat stuff
+ */
+typedef enum {
+ LFT_NONE, /* dummy */
+ LFT_STRING,
+
+ LFT_CLIENT_IP_ADDRESS,
+ LFT_CLIENT_FQDN,
+ LFT_CLIENT_PORT,
+#if USE_SQUID_EUI
+ LFT_CLIENT_EUI,
+#endif
+
+ /*LFT_SERVER_IP_ADDRESS, */
+ LFT_SERVER_IP_OR_PEER_NAME,
+ /*LFT_SERVER_PORT, */
+
+ LFT_LOCAL_IP,
+ LFT_LOCAL_PORT,
+ /*LFT_LOCAL_NAME, */
+ LFT_PEER_LOCAL_PORT,
+
+ LFT_TIME_SECONDS_SINCE_EPOCH,
+ LFT_TIME_SUBSECOND,
+ LFT_TIME_LOCALTIME,
+ LFT_TIME_GMT,
+ LFT_TIME_TO_HANDLE_REQUEST,
+
+ LFT_PEER_RESPONSE_TIME,
+ LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME,
+ LFT_DNS_WAIT_TIME,
+
+ LFT_REQUEST_HEADER,
+ LFT_REQUEST_HEADER_ELEM,
+ LFT_REQUEST_ALL_HEADERS,
+
+ LFT_ADAPTED_REQUEST_HEADER,
+ LFT_ADAPTED_REQUEST_HEADER_ELEM,
+ LFT_ADAPTED_REQUEST_ALL_HEADERS,
+
+ LFT_REPLY_HEADER,
+ LFT_REPLY_HEADER_ELEM,
+ LFT_REPLY_ALL_HEADERS,
+
+ LFT_USER_NAME,
+ LFT_USER_LOGIN,
+ LFT_USER_IDENT,
+ /*LFT_USER_REALM, */
+ /*LFT_USER_SCHEME, */
+ LFT_USER_EXTERNAL,
+
+ LFT_HTTP_SENT_STATUS_CODE_OLD_30,
+ LFT_HTTP_SENT_STATUS_CODE,
+ LFT_HTTP_RECEIVED_STATUS_CODE,
+ /*LFT_HTTP_STATUS, */
+ LFT_HTTP_BODY_BYTES_READ,
+
+ LFT_SQUID_STATUS,
+ LFT_SQUID_ERROR,
+ LFT_SQUID_ERROR_DETAIL,
+ LFT_SQUID_HIERARCHY,
+
+ LFT_MIME_TYPE,
+
+ LFT_REQUEST_METHOD,
+ LFT_REQUEST_URI,
+ LFT_REQUEST_URLPATH,
+ /*LFT_REQUEST_QUERY, * // * this is not needed. see strip_query_terms */
+ LFT_REQUEST_VERSION,
+
+ LFT_REQUEST_SIZE_TOTAL,
+ /*LFT_REQUEST_SIZE_LINE, */
+ LFT_REQUEST_SIZE_HEADERS,
+ /*LFT_REQUEST_SIZE_BODY, */
+ /*LFT_REQUEST_SIZE_BODY_NO_TE, */
+
+ LFT_REPLY_SIZE_TOTAL,
+ LFT_REPLY_HIGHOFFSET,
+ LFT_REPLY_OBJECTSIZE,
+ /*LFT_REPLY_SIZE_LINE, */
+ LFT_REPLY_SIZE_HEADERS,
+ /*LFT_REPLY_SIZE_BODY, */
+ /*LFT_REPLY_SIZE_BODY_NO_TE, */
+
+ LFT_TAG,
+ LFT_IO_SIZE_TOTAL,
+ LFT_EXT_LOG,
+
+ LFT_SEQUENCE_NUMBER,
+
+#if USE_ADAPTATION
+ LTF_ADAPTATION_SUM_XACT_TIMES,
+ LTF_ADAPTATION_ALL_XACT_TIMES,
+#endif
+
+#if ICAP_CLIENT
+
+ LFT_ICAP_TOTAL_TIME,
+ LFT_ICAP_LAST_MATCHED_HEADER,
+ LFT_ICAP_LAST_MATCHED_HEADER_ELEM,
+ LFT_ICAP_LAST_MATCHED_ALL_HEADERS,
+
+ LFT_ICAP_ADDR,
+ LFT_ICAP_SERV_NAME,
+ LFT_ICAP_REQUEST_URI,
+ LFT_ICAP_REQUEST_METHOD,
+ LFT_ICAP_BYTES_SENT,
+ LFT_ICAP_BYTES_READ,
+ LFT_ICAP_BODY_BYTES_READ,
+
+ LFT_ICAP_REQ_HEADER,
+ LFT_ICAP_REQ_HEADER_ELEM,
+ LFT_ICAP_REQ_ALL_HEADERS,
+
+ LFT_ICAP_REP_HEADER,
+ LFT_ICAP_REP_HEADER_ELEM,
+ LFT_ICAP_REP_ALL_HEADERS,
+
+ LFT_ICAP_TR_RESPONSE_TIME,
+ LFT_ICAP_IO_TIME,
+ LFT_ICAP_OUTCOME,
+ LFT_ICAP_STATUS_CODE,
+#endif
+
+ LFT_PERCENT /* special string cases for escaped chars */
+} logformat_bcode_t;
+
+enum log_quote {
+ LOG_QUOTE_NONE = 0,
+ LOG_QUOTE_QUOTES,
+ LOG_QUOTE_MIMEBLOB,
+ LOG_QUOTE_URL,
+ LOG_QUOTE_RAW
+};
+
+/* FIXME: public class so we can pre-define its type. */
+class logformat_token
+{
+public:
+ logformat_bcode_t type;
+ union {
+ char *string;
+
+ struct {
+ char *header;
+ char *element;
+ char separator;
+ } header;
+ char *timespec;
+ } data;
+ unsigned char width;
+ unsigned char precision;
+ enum log_quote quote;
+ unsigned int left:1;
+ unsigned int space:1;
+ unsigned int zero:1;
+ int divisor;
+ logformat_token *next; /* todo: move from linked list to array */
+};
+
+struct logformat_token_table_entry {
+ const char *config;
+ logformat_bcode_t token_type;
+ int options;
+};
+
+class logformat
+{
+public:
+ logformat(const char *name);
+ ~logformat();
+
+ char *name;
+ logformat_token *format;
+ logformat *next;
+};
+
+extern const char *log_tags[];
+extern struct logformat_token_table_entry logformat_token_table[];
+
+#if USE_ADAPTATION
+extern bool alLogformatHasAdaptToken;
+#endif
+
+#if ICAP_CLIENT
+extern bool alLogformatHasIcapToken;
+#endif
+
+/* parses a single token. Returns the token length in characters,
+ * and fills in the lt item with the token information.
+ * def is for sure null-terminated
+ */
+int accessLogGetNewLogFormatToken(logformat_token * lt, char *def, enum log_quote *quote);
+
+/* very inefficent parser, but who cares, this needs to be simple */
+/* First off, let's tokenize, we'll optimize in a second pass.
+ * A token can either be a %-prefixed sequence (usually a dynamic
+ * token but it can be an escaped sequence), or a string. */
+int accessLogParseLogFormat(logformat_token ** fmt, char *def);
+
+void accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions);
+
+void accessLogFreeLogFormat(logformat_token ** tokens);
+
+#endif /* _SQUID_LOG_TOKENS_H */
#include "HttpReply.h"
#include "HttpRequest.h"
#include "log/File.h"
+#include "log/Formats.h"
+#include "log/Gadgets.h"
+#include "log/Tokens.h"
#include "MemBuf.h"
#include "mgr/Registration.h"
#include "rfc1738.h"
#include "SquidTime.h"
-static void accessLogSquid(AccessLogEntry * al, Logfile * logfile);
-static void accessLogCommon(AccessLogEntry * al, Logfile * logfile);
-static void accessLogCustom(AccessLogEntry * al, customlog * log);
#if HEADERS_LOG
static Logfile *headerslog = NULL;
#endif
static void mcast_encode(unsigned int *, size_t, const unsigned int *);
#endif
-const char *log_tags[] = {
- "NONE",
- "TCP_HIT",
- "TCP_MISS",
- "TCP_REFRESH_UNMODIFIED",
- "TCP_REFRESH_FAIL", // same tag logged for LOG_TCP_REFRESH_FAIL_OLD and
- "TCP_REFRESH_FAIL", // LOG_TCP_REFRESH_FAIL_ERR for backward-compatibility
- "TCP_REFRESH_MODIFIED",
- "TCP_CLIENT_REFRESH_MISS",
- "TCP_IMS_HIT",
- "TCP_SWAPFAIL_MISS",
- "TCP_NEGATIVE_HIT",
- "TCP_MEM_HIT",
- "TCP_DENIED",
- "TCP_DENIED_REPLY",
- "TCP_OFFLINE_HIT",
-#if LOG_TCP_REDIRECTS
- "TCP_REDIRECT",
-#endif
- "UDP_HIT",
- "UDP_MISS",
- "UDP_DENIED",
- "UDP_INVALID",
- "UDP_MISS_NOFETCH",
- "ICP_QUERY",
- "LOG_TYPE_MAX"
-};
-
-#if USE_FORW_VIA_DB
-
-typedef struct {
- hash_link hash;
- int n;
-} fvdb_entry;
-static hash_table *via_table = NULL;
-static hash_table *forw_table = NULL;
-static void fvdbInit();
-static void fvdbDumpTable(StoreEntry * e, hash_table * hash);
-static void fvdbCount(hash_table * hash, const char *key);
-static OBJH fvdbDumpVia;
-static OBJH fvdbDumpForw;
-static FREE fvdbFreeEntry;
-static void fvdbClear(void);
-static void fvdbRegisterWithCacheManager();
-#endif
-
-int LogfileStatus = LOG_DISABLE;
-
-#if USE_ADAPTATION
-bool alLogformatHasAdaptToken = false;
-#endif
-
-#if ICAP_CLIENT
-bool alLogformatHasIcapToken = false;
-#endif
-
-#define LOG_BUF_SZ (MAX_URL<<2)
-
-static const char c2x[] =
- "000102030405060708090a0b0c0d0e0f"
- "101112131415161718191a1b1c1d1e1f"
- "202122232425262728292a2b2c2d2e2f"
- "303132333435363738393a3b3c3d3e3f"
- "404142434445464748494a4b4c4d4e4f"
- "505152535455565758595a5b5c5d5e5f"
- "606162636465666768696a6b6c6d6e6f"
- "707172737475767778797a7b7c7d7e7f"
- "808182838485868788898a8b8c8d8e8f"
- "909192939495969798999a9b9c9d9e9f"
- "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
- "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
- "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
- "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
- "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
- "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
-
-/* log_quote -- URL-style encoding on MIME headers. */
-
-char *
-log_quote(const char *header)
-{
- int c;
- int i;
- char *buf;
- char *buf_cursor;
-
- if (header == NULL) {
- buf = static_cast<char *>(xcalloc(1, 1));
- *buf = '\0';
- return buf;
- }
-
- buf = static_cast<char *>(xcalloc(1, (strlen(header) * 3) + 1));
- buf_cursor = buf;
- /*
- * We escape: \x00-\x1F"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF
- * which is the default escape list for the CPAN Perl5 URI module
- * modulo the inclusion of space (x40) to make the raw logs a bit
- * more readable.
- */
-
- while ((c = *(const unsigned char *) header++) != '\0') {
-#if !OLD_LOG_MIME
-
- if (c == '\r') {
- *buf_cursor++ = '\\';
- *buf_cursor++ = 'r';
- } else if (c == '\n') {
- *buf_cursor++ = '\\';
- *buf_cursor++ = 'n';
- } else
-#endif
- if (c <= 0x1F
- || c >= 0x7F
- || c == '%'
-#if OLD_LOG_MIME
- || c == '"'
- || c == '#'
- || c == ';'
- || c == '<'
- || c == '>'
- || c == '?'
- || c == '{'
- || c == '}'
- || c == '|'
- || c == '\\'
- || c == '^'
- || c == '~'
- || c == '`'
-#endif
- || c == '['
- || c == ']') {
- *buf_cursor++ = '%';
- i = c * 2;
- *buf_cursor++ = c2x[i];
- *buf_cursor++ = c2x[i + 1];
-#if !OLD_LOG_MIME
-
- } else if (c == '\\') {
- *buf_cursor++ = '\\';
- *buf_cursor++ = '\\';
-#endif
-
- } else {
- *buf_cursor++ = (char) c;
- }
- }
-
- *buf_cursor = '\0';
- return buf;
-}
-
-static char *
-username_quote(const char *header)
-/* copy of log_quote. Bugs there will be found here */
-{
- int c;
- int i;
- char *buf;
- char *buf_cursor;
-
- if (header == NULL) {
- buf = static_cast<char *>(xcalloc(1, 1));
- *buf = '\0';
- return buf;
- }
-
- buf = static_cast<char *>(xcalloc(1, (strlen(header) * 3) + 1));
- buf_cursor = buf;
- /*
- * We escape: space \x00-\x1F and space (0x40) and \x7F-\xFF
- * to prevent garbage in the logs. CR and LF are also there just in case.
- */
-
- while ((c = *(const unsigned char *) header++) != '\0') {
- if (c == '\r') {
- *buf_cursor++ = '\\';
- *buf_cursor++ = 'r';
- } else if (c == '\n') {
- *buf_cursor++ = '\\';
- *buf_cursor++ = 'n';
- } else if (c <= 0x1F
- || c >= 0x7F
- || c == '%'
- || c == ' ') {
- *buf_cursor++ = '%';
- i = c * 2;
- *buf_cursor++ = c2x[i];
- *buf_cursor++ = c2x[i + 1];
- } else {
- *buf_cursor++ = (char) c;
- }
- }
-
- *buf_cursor = '\0';
- return buf;
-}
-
-static char *
-accessLogFormatName(const char *name)
-{
- if (NULL == name)
- return NULL;
-
- if (name[0] == '\0')
- return NULL;
-
- return username_quote(name);
-}
-
-static char *
-log_quoted_string(const char *str)
-{
- char *out = (char *)xmalloc(strlen(str) * 2 + 1);
- char *p = out;
-
- while (*str) {
- int l = strcspn(str, "\"\\\r\n\t");
- memcpy(p, str, l);
- str += l;
- p += l;
-
- switch (*str) {
-
- case '\0':
- break;
-
- case '\r':
- *p++ = '\\';
- *p++ = 'r';
- str++;
- break;
-
- case '\n':
- *p++ = '\\';
- *p++ = 'n';
- str++;
- break;
-
- case '\t':
- *p++ = '\\';
- *p++ = 't';
- str++;
- break;
-
- default:
- *p++ = '\\';
- *p++ = *str;
- str++;
- break;
- }
- }
-
- *p++ = '\0';
- return out;
-}
-
-/*
- * Bytecodes for the configureable logformat stuff
- */
-typedef enum {
- LFT_NONE, /* dummy */
- LFT_STRING,
-
- LFT_CLIENT_IP_ADDRESS,
- LFT_CLIENT_FQDN,
- LFT_CLIENT_PORT,
-#if USE_SQUID_EUI
- LFT_CLIENT_EUI,
-#endif
-
- /*LFT_SERVER_IP_ADDRESS, */
- LFT_SERVER_IP_OR_PEER_NAME,
- /*LFT_SERVER_PORT, */
-
- LFT_LOCAL_IP,
- LFT_LOCAL_PORT,
- /*LFT_LOCAL_NAME, */
- LFT_PEER_LOCAL_PORT,
-
- LFT_TIME_SECONDS_SINCE_EPOCH,
- LFT_TIME_SUBSECOND,
- LFT_TIME_LOCALTIME,
- LFT_TIME_GMT,
- LFT_TIME_TO_HANDLE_REQUEST,
-
- LFT_PEER_RESPONSE_TIME,
- LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME,
- LFT_DNS_WAIT_TIME,
-
- LFT_REQUEST_HEADER,
- LFT_REQUEST_HEADER_ELEM,
- LFT_REQUEST_ALL_HEADERS,
-
- LFT_ADAPTED_REQUEST_HEADER,
- LFT_ADAPTED_REQUEST_HEADER_ELEM,
- LFT_ADAPTED_REQUEST_ALL_HEADERS,
-
- LFT_REPLY_HEADER,
- LFT_REPLY_HEADER_ELEM,
- LFT_REPLY_ALL_HEADERS,
-
- LFT_USER_NAME,
- LFT_USER_LOGIN,
- LFT_USER_IDENT,
- /*LFT_USER_REALM, */
- /*LFT_USER_SCHEME, */
- LFT_USER_EXTERNAL,
-
- LFT_HTTP_SENT_STATUS_CODE_OLD_30,
- LFT_HTTP_SENT_STATUS_CODE,
- LFT_HTTP_RECEIVED_STATUS_CODE,
- /*LFT_HTTP_STATUS, */
- LFT_HTTP_BODY_BYTES_READ,
-
- LFT_SQUID_STATUS,
- LFT_SQUID_ERROR,
- LFT_SQUID_ERROR_DETAIL,
- LFT_SQUID_HIERARCHY,
-
- LFT_MIME_TYPE,
-
- LFT_REQUEST_METHOD,
- LFT_REQUEST_URI,
- LFT_REQUEST_URLPATH,
- /*LFT_REQUEST_QUERY, * // * this is not needed. see strip_query_terms */
- LFT_REQUEST_VERSION,
-
- LFT_REQUEST_SIZE_TOTAL,
- /*LFT_REQUEST_SIZE_LINE, */
- LFT_REQUEST_SIZE_HEADERS,
- /*LFT_REQUEST_SIZE_BODY, */
- /*LFT_REQUEST_SIZE_BODY_NO_TE, */
-
- LFT_REPLY_SIZE_TOTAL,
- LFT_REPLY_HIGHOFFSET,
- LFT_REPLY_OBJECTSIZE,
- /*LFT_REPLY_SIZE_LINE, */
- LFT_REPLY_SIZE_HEADERS,
- /*LFT_REPLY_SIZE_BODY, */
- /*LFT_REPLY_SIZE_BODY_NO_TE, */
-
- LFT_TAG,
- LFT_IO_SIZE_TOTAL,
- LFT_EXT_LOG,
-
- LFT_SEQUENCE_NUMBER,
-
-#if USE_ADAPTATION
- LTF_ADAPTATION_SUM_XACT_TIMES,
- LTF_ADAPTATION_ALL_XACT_TIMES,
-#endif
-
-#if ICAP_CLIENT
-
- LFT_ICAP_TOTAL_TIME,
- LFT_ICAP_LAST_MATCHED_HEADER,
- LFT_ICAP_LAST_MATCHED_HEADER_ELEM,
- LFT_ICAP_LAST_MATCHED_ALL_HEADERS,
-
- LFT_ICAP_ADDR,
- LFT_ICAP_SERV_NAME,
- LFT_ICAP_REQUEST_URI,
- LFT_ICAP_REQUEST_METHOD,
- LFT_ICAP_BYTES_SENT,
- LFT_ICAP_BYTES_READ,
- LFT_ICAP_BODY_BYTES_READ,
-
- LFT_ICAP_REQ_HEADER,
- LFT_ICAP_REQ_HEADER_ELEM,
- LFT_ICAP_REQ_ALL_HEADERS,
-
- LFT_ICAP_REP_HEADER,
- LFT_ICAP_REP_HEADER_ELEM,
- LFT_ICAP_REP_ALL_HEADERS,
-
- LFT_ICAP_TR_RESPONSE_TIME,
- LFT_ICAP_IO_TIME,
- LFT_ICAP_OUTCOME,
- LFT_ICAP_STATUS_CODE,
-#endif
-
- LFT_PERCENT /* special string cases for escaped chars */
-} logformat_bcode_t;
-
-enum log_quote {
- LOG_QUOTE_NONE = 0,
- LOG_QUOTE_QUOTES,
- LOG_QUOTE_BRAKETS,
- LOG_QUOTE_URL,
- LOG_QUOTE_RAW
-};
-
-/* FIXME: public class so we can pre-define its type. */
-class logformat_token
-{
-public:
- logformat_bcode_t type;
- union {
- char *string;
-
- struct {
- char *header;
- char *element;
- char separator;
- } header;
- char *timespec;
- } data;
- unsigned char width;
- unsigned char precision;
- enum log_quote quote;
- unsigned int left:1;
- unsigned int space:1;
- unsigned int zero:1;
- int divisor;
- logformat_token *next; /* todo: move from linked list to array */
-};
-
-struct logformat_token_table_entry {
- const char *config;
- logformat_bcode_t token_type;
- int options;
-};
-
-struct logformat_token_table_entry logformat_token_table[] = {
-
- {">a", LFT_CLIENT_IP_ADDRESS},
- {">p", LFT_CLIENT_PORT},
- {">A", LFT_CLIENT_FQDN},
-#if USE_SQUID_EUI
- {">eui", LFT_CLIENT_EUI},
-#endif
-
- /*{ "<a", LFT_SERVER_IP_ADDRESS }, */
- /*{ "<p", LFT_SERVER_PORT }, */
- {"<A", LFT_SERVER_IP_OR_PEER_NAME},
-
- /* {"oa", LFT_OUTGOING_IP}, */
- /* {"ot", LFT_OUTGOING_TOS}, */
-
- {"la", LFT_LOCAL_IP},
- {"lp", LFT_LOCAL_PORT},
- /*{ "lA", LFT_LOCAL_NAME }, */
- {"<lp", LFT_PEER_LOCAL_PORT},
-
- {"ts", LFT_TIME_SECONDS_SINCE_EPOCH},
- {"tu", LFT_TIME_SUBSECOND},
- {"tl", LFT_TIME_LOCALTIME},
- {"tg", LFT_TIME_GMT},
- {"tr", LFT_TIME_TO_HANDLE_REQUEST},
-
- {"<pt", LFT_PEER_RESPONSE_TIME},
- {"<tt", LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME},
- {"dt", LFT_DNS_WAIT_TIME},
-
- {">ha", LFT_ADAPTED_REQUEST_HEADER},
- {">ha", LFT_ADAPTED_REQUEST_ALL_HEADERS},
- {">h", LFT_REQUEST_HEADER},
- {">h", LFT_REQUEST_ALL_HEADERS},
- {"<h", LFT_REPLY_HEADER},
- {"<h", LFT_REPLY_ALL_HEADERS},
-
- {"un", LFT_USER_NAME},
- {"ul", LFT_USER_LOGIN},
- /*{ "ur", LFT_USER_REALM }, */
- /*{ "us", LFT_USER_SCHEME }, */
- {"ui", LFT_USER_IDENT},
- {"ue", LFT_USER_EXTERNAL},
-
- {"Hs", LFT_HTTP_SENT_STATUS_CODE_OLD_30},
- {">Hs", LFT_HTTP_SENT_STATUS_CODE},
- {"<Hs", LFT_HTTP_RECEIVED_STATUS_CODE},
- /*{ "Ht", LFT_HTTP_STATUS }, */
- {"<bs", LFT_HTTP_BODY_BYTES_READ},
-
- {"Ss", LFT_SQUID_STATUS},
- { "err_code", LFT_SQUID_ERROR },
- { "err_detail", LFT_SQUID_ERROR_DETAIL },
- {"Sh", LFT_SQUID_HIERARCHY},
-
- {"mt", LFT_MIME_TYPE},
-
- {"rm", LFT_REQUEST_METHOD},
- {"ru", LFT_REQUEST_URI}, /* doesn't include the query-string */
- {"rp", LFT_REQUEST_URLPATH}, /* doesn't include the host */
- /* { "rq", LFT_REQUEST_QUERY }, * / / * the query-string, INCLUDING the leading ? */
- {">v", LFT_REQUEST_VERSION},
- {"rv", LFT_REQUEST_VERSION},
-
- { ">st", LFT_REQUEST_SIZE_TOTAL },
- /*{ ">sl", LFT_REQUEST_SIZE_LINE }, * / / * the request line "GET ... " */
- { ">sh", LFT_REQUEST_SIZE_HEADERS },
- /*{ ">sb", LFT_REQUEST_SIZE_BODY }, */
- /*{ ">sB", LFT_REQUEST_SIZE_BODY_NO_TE }, */
-
- {"<st", LFT_REPLY_SIZE_TOTAL},
- {"<sH", LFT_REPLY_HIGHOFFSET},
- {"<sS", LFT_REPLY_OBJECTSIZE},
- /*{ "<sl", LFT_REPLY_SIZE_LINE }, * / / * the reply line (protocol, code, text) */
- { "<sh", LFT_REPLY_SIZE_HEADERS },
- /*{ "<sb", LFT_REPLY_SIZE_BODY }, */
- /*{ "<sB", LFT_REPLY_SIZE_BODY_NO_TE }, */
-
- {"et", LFT_TAG},
- {"st", LFT_IO_SIZE_TOTAL},
- {"ea", LFT_EXT_LOG},
- {"sn", LFT_SEQUENCE_NUMBER},
-
- {"%", LFT_PERCENT},
-
-#if USE_ADAPTATION
- {"adapt::all_trs", LTF_ADAPTATION_ALL_XACT_TIMES},
- {"adapt::sum_trs", LTF_ADAPTATION_SUM_XACT_TIMES},
-#endif
-
-#if ICAP_CLIENT
- {"icap::tt", LFT_ICAP_TOTAL_TIME},
- {"icap::<last_h", LFT_ICAP_LAST_MATCHED_HEADER},
-
- {"icap::<A", LFT_ICAP_ADDR},
- {"icap::<service_name", LFT_ICAP_SERV_NAME},
- {"icap::ru", LFT_ICAP_REQUEST_URI},
- {"icap::rm", LFT_ICAP_REQUEST_METHOD},
- {"icap::>st", LFT_ICAP_BYTES_SENT},
- {"icap::<st", LFT_ICAP_BYTES_READ},
- {"icap::<bs", LFT_ICAP_BODY_BYTES_READ},
-
- {"icap::>h", LFT_ICAP_REQ_HEADER},
- {"icap::<h", LFT_ICAP_REP_HEADER},
-
- {"icap::tr", LFT_ICAP_TR_RESPONSE_TIME},
- {"icap::tio", LFT_ICAP_IO_TIME},
- {"icap::to", LFT_ICAP_OUTCOME},
- {"icap::Hs", LFT_ICAP_STATUS_CODE},
-#endif
-
- {NULL, LFT_NONE} /* this must be last */
-};
-
-static void
-accessLogCustom(AccessLogEntry * al, customlog * log)
-{
- logformat *lf;
- Logfile *logfile;
- logformat_token *fmt;
- static MemBuf mb;
- char tmp[1024];
- String sb;
-
- mb.reset();
-
- lf = log->logFormat;
- logfile = log->logfile;
-
- for (fmt = lf->format; fmt != NULL; fmt = fmt->next) { /* for each token */
- const char *out = NULL;
- int quote = 0;
- long int outint = 0;
- int doint = 0;
- int dofree = 0;
- int64_t outoff = 0;
- int dooff = 0;
-
- switch (fmt->type) {
-
- case LFT_NONE:
- out = "";
- break;
-
- case LFT_STRING:
- out = fmt->data.string;
- break;
-
- case LFT_CLIENT_IP_ADDRESS:
- if (al->cache.caddr.IsNoAddr()) // e.g., ICAP OPTIONS lack client
- out = "-";
- else
- out = al->cache.caddr.NtoA(tmp,1024);
- break;
-
- case LFT_CLIENT_FQDN:
- if (al->cache.caddr.IsAnyAddr()) // e.g., ICAP OPTIONS lack client
- out = "-";
- else
- out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
- if (!out) {
- out = al->cache.caddr.NtoA(tmp,1024);
- }
-
- break;
-
- case LFT_CLIENT_PORT:
- if (al->request) {
- outint = al->request->client_addr.GetPort();
- doint = 1;
- }
- break;
-
-#if USE_SQUID_EUI
- case LFT_CLIENT_EUI:
- if (al->request) {
- if (al->cache.caddr.IsIPv4())
- al->request->client_eui48.encode(tmp, 1024);
- else
- al->request->client_eui64.encode(tmp, 1024);
- out = tmp;
- }
- break;
-#endif
-
- /* case LFT_SERVER_IP_ADDRESS: */
-
- case LFT_SERVER_IP_OR_PEER_NAME:
- out = al->hier.host;
-
- break;
-
- /* case LFT_SERVER_PORT: */
-
- case LFT_LOCAL_IP:
- if (al->request) {
- out = al->request->my_addr.NtoA(tmp,1024);
- }
-
- break;
-
- case LFT_LOCAL_PORT:
- if (al->request) {
- outint = al->request->my_addr.GetPort();
- doint = 1;
- }
-
- break;
-
- case LFT_PEER_LOCAL_PORT:
- if (al->hier.peer_local_port) {
- outint = al->hier.peer_local_port;
- doint = 1;
- }
-
- break;
-
- case LFT_TIME_SECONDS_SINCE_EPOCH:
- // some platforms store time in 32-bit, some 64-bit...
- outoff = static_cast<int64_t>(current_time.tv_sec);
- dooff = 1;
- break;
-
- case LFT_TIME_SUBSECOND:
- outint = current_time.tv_usec / fmt->divisor;
- doint = 1;
- break;
-
-
- case LFT_TIME_LOCALTIME:
-
- case LFT_TIME_GMT: {
- const char *spec;
-
- struct tm *t;
- spec = fmt->data.timespec;
-
- if (fmt->type == LFT_TIME_LOCALTIME) {
- if (!spec)
- spec = "%d/%b/%Y:%H:%M:%S %z";
- t = localtime(&squid_curtime);
- } else {
- if (!spec)
- spec = "%d/%b/%Y:%H:%M:%S";
-
- t = gmtime(&squid_curtime);
- }
-
- strftime(tmp, sizeof(tmp), spec, t);
-
- out = tmp;
- }
-
- break;
-
- case LFT_TIME_TO_HANDLE_REQUEST:
- outint = al->cache.msec;
- doint = 1;
- break;
-
- case LFT_PEER_RESPONSE_TIME:
- if (al->hier.peer_response_time < 0) {
- out = "-";
- } else {
- outoff = al->hier.peer_response_time;
- dooff = 1;
- }
- break;
-
- case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME:
- if (al->hier.total_response_time < 0) {
- out = "-";
- } else {
- outoff = al->hier.total_response_time;
- dooff = 1;
- }
- break;
-
- case LFT_DNS_WAIT_TIME:
- if (al->request && al->request->dnsWait >= 0) {
- outint = al->request->dnsWait;
- doint = 1;
- }
- break;
-
- case LFT_REQUEST_HEADER:
-
- if (al->request)
- sb = al->request->header.getByName(fmt->data.header.header);
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_ADAPTED_REQUEST_HEADER:
-
- if (al->request)
- sb = al->adapted_request->header.getByName(fmt->data.header.header);
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_REPLY_HEADER:
- if (al->reply)
- sb = al->reply->header.getByName(fmt->data.header.header);
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
-#if USE_ADAPTATION
- case LTF_ADAPTATION_SUM_XACT_TIMES:
- if (al->request) {
- Adaptation::History::Pointer ah = al->request->adaptHistory();
- if (ah != NULL)
- ah->sumLogString(fmt->data.string, sb);
- out = sb.termedBuf();
- }
- break;
-
- case LTF_ADAPTATION_ALL_XACT_TIMES:
- if (al->request) {
- Adaptation::History::Pointer ah = al->request->adaptHistory();
- if (ah != NULL)
- ah->allLogString(fmt->data.string, sb);
- out = sb.termedBuf();
- }
- break;
-#endif
-
-#if ICAP_CLIENT
- case LFT_ICAP_LAST_MATCHED_HEADER:
- if (al->request) {
- Adaptation::Icap::History::Pointer ih = al->request->icapHistory();
- if (ih != NULL)
- sb = ih->mergeOfIcapHeaders.getByName(fmt->data.header.header);
- }
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_ICAP_LAST_MATCHED_HEADER_ELEM:
- if (al->request) {
- Adaptation::Icap::History::Pointer ih = al->request->icapHistory();
- if (ih != NULL)
- sb = ih->mergeOfIcapHeaders.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
- }
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_ICAP_LAST_MATCHED_ALL_HEADERS:
- out = al->headers.icap;
-
- quote = 1;
-
- break;
-
- case LFT_ICAP_ADDR:
- if (!out)
- out = al->icap.hostAddr.NtoA(tmp,1024);
- break;
-
- case LFT_ICAP_SERV_NAME:
- out = al->icap.serviceName.termedBuf();
- break;
-
- case LFT_ICAP_REQUEST_URI:
- out = al->icap.reqUri.termedBuf();
- break;
-
- case LFT_ICAP_REQUEST_METHOD:
- out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod);
- break;
-
- case LFT_ICAP_BYTES_SENT:
- outoff = al->icap.bytesSent;
- dooff = 1;
- break;
-
- case LFT_ICAP_BYTES_READ:
- outoff = al->icap.bytesRead;
- dooff = 1;
- break;
-
- case LFT_ICAP_BODY_BYTES_READ:
- if (al->icap.bodyBytesRead >= 0) {
- outoff = al->icap.bodyBytesRead;
- dooff = 1;
- }
- // else if icap.bodyBytesRead < 0, we do not have any http data,
- // so just print a "-" (204 responses etc)
- break;
-
- case LFT_ICAP_REQ_HEADER:
- if (NULL != al->icap.request) {
- sb = al->icap.request->header.getByName(fmt->data.header.header);
- out = sb.termedBuf();
- quote = 1;
- }
- break;
-
- case LFT_ICAP_REQ_HEADER_ELEM:
- if (al->request)
- sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_ICAP_REQ_ALL_HEADERS:
- if (al->icap.request) {
- HttpHeaderPos pos = HttpHeaderInitPos;
- while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) {
- sb.append(e->name);
- sb.append(": ");
- sb.append(e->value);
- sb.append("\r\n");
- }
- out = sb.termedBuf();
- quote = 1;
- }
- break;
-
- case LFT_ICAP_REP_HEADER:
- if (NULL != al->icap.reply) {
- sb = al->icap.reply->header.getByName(fmt->data.header.header);
- out = sb.termedBuf();
- quote = 1;
- }
- break;
-
- case LFT_ICAP_REP_HEADER_ELEM:
- if (NULL != al->icap.reply)
- sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_ICAP_REP_ALL_HEADERS:
- if (al->icap.reply) {
- HttpHeaderPos pos = HttpHeaderInitPos;
- while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) {
- sb.append(e->name);
- sb.append(": ");
- sb.append(e->value);
- sb.append("\r\n");
- }
- out = sb.termedBuf();
- quote = 1;
- }
- break;
-
- case LFT_ICAP_TR_RESPONSE_TIME:
- outint = al->icap.trTime;
- doint = 1;
- break;
-
- case LFT_ICAP_IO_TIME:
- outint = al->icap.ioTime;
- doint = 1;
- break;
-
- case LFT_ICAP_STATUS_CODE:
- outint = al->icap.resStatus;
- doint = 1;
- break;
-
- case LFT_ICAP_OUTCOME:
- out = al->icap.outcome;
- break;
-
- case LFT_ICAP_TOTAL_TIME:
- outint = al->icap.processingTime;
- doint = 1;
- break;
-#endif
- case LFT_REQUEST_HEADER_ELEM:
- if (al->request)
- sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_ADAPTED_REQUEST_HEADER_ELEM:
- if (al->adapted_request)
- sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_REPLY_HEADER_ELEM:
- if (al->reply)
- sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
-
- out = sb.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_REQUEST_ALL_HEADERS:
- out = al->headers.request;
-
- quote = 1;
-
- break;
-
- case LFT_ADAPTED_REQUEST_ALL_HEADERS:
- out = al->headers.adapted_request;
-
- quote = 1;
-
- break;
-
- case LFT_REPLY_ALL_HEADERS:
- out = al->headers.reply;
-
- quote = 1;
-
- break;
-
- case LFT_USER_NAME:
- out = accessLogFormatName(al->cache.authuser);
-
- if (!out)
- out = accessLogFormatName(al->cache.extuser);
-
-#if USE_SSL
-
- if (!out)
- out = accessLogFormatName(al->cache.ssluser);
-
-#endif
-
- if (!out)
- out = accessLogFormatName(al->cache.rfc931);
-
- dofree = 1;
-
- break;
-
- case LFT_USER_LOGIN:
- out = accessLogFormatName(al->cache.authuser);
-
- dofree = 1;
-
- break;
-
- case LFT_USER_IDENT:
- out = accessLogFormatName(al->cache.rfc931);
-
- dofree = 1;
-
- break;
-
- case LFT_USER_EXTERNAL:
- out = accessLogFormatName(al->cache.extuser);
-
- dofree = 1;
-
- break;
-
- /* case LFT_USER_REALM: */
- /* case LFT_USER_SCHEME: */
-
- // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
- // but compiler complains if ommited
- case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
- case LFT_HTTP_SENT_STATUS_CODE:
- outint = al->http.code;
-
- doint = 1;
-
- break;
-
- case LFT_HTTP_RECEIVED_STATUS_CODE:
- if (al->hier.peer_reply_status == HTTP_STATUS_NONE) {
- out = "-";
- } else {
- outint = al->hier.peer_reply_status;
- doint = 1;
- }
- break;
- /* case LFT_HTTP_STATUS:
- * out = statusline->text;
- * quote = 1;
- * break;
- */
- case LFT_HTTP_BODY_BYTES_READ:
- if (al->hier.bodyBytesRead >= 0) {
- outoff = al->hier.bodyBytesRead;
- dooff = 1;
- }
- // else if hier.bodyBytesRead < 0 we did not have any data exchange with
- // a peer server so just print a "-" (eg requests served from cache,
- // or internal error messages).
- break;
-
- case LFT_SQUID_STATUS:
- if (al->http.timedout || al->http.aborted) {
- snprintf(tmp, sizeof(tmp), "%s%s", log_tags[al->cache.code],
- al->http.statusSfx());
- out = tmp;
- } else {
- out = log_tags[al->cache.code];
- }
-
- break;
-
- case LFT_SQUID_ERROR:
- if (al->request && al->request->errType != ERR_NONE)
- out = errorPageName(al->request->errType);
- break;
-
- case LFT_SQUID_ERROR_DETAIL:
- if (al->request && al->request->errDetail != ERR_DETAIL_NONE) {
- if (al->request->errDetail > ERR_DETAIL_START &&
- al->request->errDetail < ERR_DETAIL_MAX)
- out = errorDetailName(al->request->errDetail);
- else {
- if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START)
- snprintf(tmp, sizeof(tmp), "%s=0x%X",
- errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail);
- else
- snprintf(tmp, sizeof(tmp), "%s=%d",
- errorDetailName(al->request->errDetail), al->request->errDetail);
- out = tmp;
- }
- }
- break;
-
- case LFT_SQUID_HIERARCHY:
- if (al->hier.ping.timedout)
- mb.append("TIMEOUT_", 8);
-
- out = hier_code_str[al->hier.code];
-
- break;
-
- case LFT_MIME_TYPE:
- out = al->http.content_type;
-
- break;
-
- case LFT_REQUEST_METHOD:
- out = al->_private.method_str;
-
- break;
-
- case LFT_REQUEST_URI:
- out = al->url;
-
- break;
-
- case LFT_REQUEST_URLPATH:
- if (al->request) {
- out = al->request->urlpath.termedBuf();
- quote = 1;
- }
- break;
-
- case LFT_REQUEST_VERSION:
- snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
- out = tmp;
- break;
-
- case LFT_REQUEST_SIZE_TOTAL:
- outoff = al->cache.requestSize;
- dooff = 1;
- break;
-
- /*case LFT_REQUEST_SIZE_LINE: */
- case LFT_REQUEST_SIZE_HEADERS:
- outoff = al->cache.requestHeadersSize;
- dooff =1;
- break;
- /*case LFT_REQUEST_SIZE_BODY: */
- /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
-
- case LFT_REPLY_SIZE_TOTAL:
- outoff = al->cache.replySize;
- dooff = 1;
- break;
-
- case LFT_REPLY_HIGHOFFSET:
- outoff = al->cache.highOffset;
-
- dooff = 1;
-
- break;
-
- case LFT_REPLY_OBJECTSIZE:
- outoff = al->cache.objectSize;
-
- dooff = 1;
-
- break;
-
- /*case LFT_REPLY_SIZE_LINE: */
- case LFT_REPLY_SIZE_HEADERS:
- outint = al->cache.replyHeadersSize;
- doint = 1;
- break;
- /*case LFT_REPLY_SIZE_BODY: */
- /*case LFT_REPLY_SIZE_BODY_NO_TE: */
-
- case LFT_TAG:
- if (al->request)
- out = al->request->tag.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_IO_SIZE_TOTAL:
- outint = al->cache.requestSize + al->cache.replySize;
- doint = 1;
- break;
-
- case LFT_EXT_LOG:
- if (al->request)
- out = al->request->extacl_log.termedBuf();
-
- quote = 1;
-
- break;
-
- case LFT_SEQUENCE_NUMBER:
- outoff = logfile->sequence_number;
- dooff = 1;
- break;
-
- case LFT_PERCENT:
- out = "%";
-
- break;
- }
-
- if (dooff) {
- snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero ? (int) fmt->width : 0, outoff);
- out = tmp;
-
- } else if (doint) {
- snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint);
- out = tmp;
- }
-
- if (out && *out) {
- if (quote || fmt->quote != LOG_QUOTE_NONE) {
- char *newout = NULL;
- int newfree = 0;
-
- switch (fmt->quote) {
-
- case LOG_QUOTE_NONE:
- newout = rfc1738_escape_unescaped(out);
- break;
-
- case LOG_QUOTE_QUOTES:
- newout = log_quoted_string(out);
- newfree = 1;
- break;
-
- case LOG_QUOTE_BRAKETS:
- newout = log_quote(out);
- newfree = 1;
- break;
-
- case LOG_QUOTE_URL:
- newout = rfc1738_escape(out);
- break;
-
- case LOG_QUOTE_RAW:
- break;
- }
-
- if (newout) {
- if (dofree)
- safe_free(out);
-
- out = newout;
-
- dofree = newfree;
- }
- }
-
- if (fmt->width) {
- if (fmt->left)
- mb.Printf("%-*s", (int) fmt->width, out);
- else
- mb.Printf("%*s", (int) fmt->width, out);
- } else
- mb.append(out, strlen(out));
- } else {
- mb.append("-", 1);
- }
-
- if (fmt->space)
- mb.append(" ", 1);
-
- sb.clean();
-
- if (dofree)
- safe_free(out);
- }
-
- logfilePrintf(logfile, "%s\n", mb.buf);
-}
-
-/* parses a single token. Returns the token length in characters,
- * and fills in the lt item with the token information.
- * def is for sure null-terminated
- */
-static int
-accessLogGetNewLogFormatToken(logformat_token * lt, char *def, enum log_quote *quote)
-{
- char *cur = def;
-
- struct logformat_token_table_entry *lte;
- int l;
-
- memset(lt, 0, sizeof(*lt));
- l = strcspn(cur, "%");
-
- if (l > 0) {
- char *cp;
- /* it's a string for sure, until \0 or the next % */
- cp = (char *)xmalloc(l + 1);
- xstrncpy(cp, cur, l + 1);
- lt->type = LFT_STRING;
- lt->data.string = cp;
-
- while (l > 0) {
- switch (*cur) {
-
- case '"':
-
- if (*quote == LOG_QUOTE_NONE)
- *quote = LOG_QUOTE_QUOTES;
- else if (*quote == LOG_QUOTE_QUOTES)
- *quote = LOG_QUOTE_NONE;
-
- break;
-
- case '[':
- if (*quote == LOG_QUOTE_NONE)
- *quote = LOG_QUOTE_BRAKETS;
-
- break;
-
- case ']':
- if (*quote == LOG_QUOTE_BRAKETS)
- *quote = LOG_QUOTE_NONE;
-
- break;
- }
-
- cur++;
- l--;
- }
-
- goto done;
- }
-
- if (!*cur)
- goto done;
-
- cur++;
-
- switch (*cur) {
-
- case '"':
- lt->quote = LOG_QUOTE_QUOTES;
- cur++;
- break;
-
- case '\'':
- lt->quote = LOG_QUOTE_RAW;
- cur++;
- break;
-
- case '[':
- lt->quote = LOG_QUOTE_BRAKETS;
- cur++;
- break;
-
- case '#':
- lt->quote = LOG_QUOTE_URL;
- cur++;
- break;
-
- default:
- lt->quote = *quote;
- break;
- }
-
- if (*cur == '-') {
- lt->left = 1;
- cur++;
- }
-
- if (*cur == '0') {
- lt->zero = 1;
- cur++;
- }
-
- if (xisdigit(*cur))
- lt->width = strtol(cur, &cur, 10);
-
- if (*cur == '.')
- lt->precision = strtol(cur + 1, &cur, 10);
-
- if (*cur == '{') {
- char *cp;
- cur++;
- l = strcspn(cur, "}");
- cp = (char *)xmalloc(l + 1);
- xstrncpy(cp, cur, l + 1);
- lt->data.string = cp;
- cur += l;
-
- if (*cur == '}')
- cur++;
- }
-
- // For upward compatibility, assume "http::" prefix as default prefix
- // for all log access formating codes, except those starting
- // from "icap::", "adapt::" and "%"
- if (strncmp(cur,"http::", 6) == 0 &&
- strncmp(cur+6, "icap::", 6) != 0 &&
- strncmp(cur+6, "adapt::", 12) != 0 && *(cur+6) != '%' ) {
- cur += 6;
- }
-
- lt->type = LFT_NONE;
-
- for (lte = logformat_token_table; lte->config != NULL; lte++) {
- if (strncmp(lte->config, cur, strlen(lte->config)) == 0) {
- lt->type = lte->token_type;
- cur += strlen(lte->config);
- break;
- }
- }
-
- if (lt->type == LFT_NONE) {
- fatalf("Can't parse configuration token: '%s'\n",
- def);
- }
-
- if (*cur == ' ') {
- lt->space = 1;
- cur++;
- }
-
-done:
-
- switch (lt->type) {
-
-#if ICAP_CLIENT
- case LFT_ICAP_LAST_MATCHED_HEADER:
-
- case LFT_ICAP_REQ_HEADER:
-
- case LFT_ICAP_REP_HEADER:
-#endif
-
- case LFT_ADAPTED_REQUEST_HEADER:
-
- case LFT_REQUEST_HEADER:
-
- case LFT_REPLY_HEADER:
-
- if (lt->data.string) {
- char *header = lt->data.string;
- char *cp = strchr(header, ':');
-
- if (cp) {
- *cp++ = '\0';
-
- if (*cp == ',' || *cp == ';' || *cp == ':')
- lt->data.header.separator = *cp++;
- else
- lt->data.header.separator = ',';
-
- lt->data.header.element = cp;
-
- switch (lt->type) {
- case LFT_REQUEST_HEADER:
- lt->type = LFT_REQUEST_HEADER_ELEM;
- break;
-
- case LFT_ADAPTED_REQUEST_HEADER:
- lt->type = LFT_ADAPTED_REQUEST_HEADER_ELEM;
- break;
-
- case LFT_REPLY_HEADER:
- lt->type = LFT_REPLY_HEADER_ELEM;
- break;
-#if ICAP_CLIENT
- case LFT_ICAP_LAST_MATCHED_HEADER:
- lt->type = LFT_ICAP_LAST_MATCHED_HEADER_ELEM;
- break;
- case LFT_ICAP_REQ_HEADER:
- lt->type = LFT_ICAP_REQ_HEADER_ELEM;
- break;
- case LFT_ICAP_REP_HEADER:
- lt->type = LFT_ICAP_REP_HEADER_ELEM;
- break;
-#endif
- default:
- break;
- }
- }
-
- lt->data.header.header = header;
- } else {
- switch (lt->type) {
- case LFT_REQUEST_HEADER:
- lt->type = LFT_REQUEST_ALL_HEADERS;
- break;
-
- case LFT_ADAPTED_REQUEST_HEADER:
- lt->type = LFT_ADAPTED_REQUEST_ALL_HEADERS;
- break;
-
- case LFT_REPLY_HEADER:
- lt->type = LFT_REPLY_ALL_HEADERS;
- break;
-#if ICAP_CLIENT
- case LFT_ICAP_LAST_MATCHED_HEADER:
- lt->type = LFT_ICAP_LAST_MATCHED_ALL_HEADERS;
- break;
- case LFT_ICAP_REQ_HEADER:
- lt->type = LFT_ICAP_REQ_ALL_HEADERS;
- break;
- case LFT_ICAP_REP_HEADER:
- lt->type = LFT_ICAP_REP_ALL_HEADERS;
- break;
-#endif
- default:
- break;
- }
- Config.onoff.log_mime_hdrs = 1;
- }
-
- break;
-
- case LFT_CLIENT_FQDN:
- Config.onoff.log_fqdn = 1;
- break;
-
- case LFT_TIME_SUBSECOND:
- lt->divisor = 1000;
-
- if (lt->precision) {
- int i;
- lt->divisor = 1000000;
-
- for (i = lt->precision; i > 1; i--)
- lt->divisor /= 10;
-
- if (!lt->divisor)
- lt->divisor = 0;
- }
-
- break;
-
- case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
- debugs(46, 0, "WARNING: the \"Hs\" formating code is deprecated use the \">Hs\" instead");
- lt->type = LFT_HTTP_SENT_STATUS_CODE;
- break;
- default:
- break;
- }
-
- return (cur - def);
-}
-
-int
-accessLogParseLogFormat(logformat_token ** fmt, char *def)
-{
- char *cur, *eos;
- logformat_token *new_lt, *last_lt;
- enum log_quote quote = LOG_QUOTE_NONE;
-
- debugs(46, 2, "accessLogParseLogFormat: got definition '" << def << "'");
-
- /* very inefficent parser, but who cares, this needs to be simple */
- /* First off, let's tokenize, we'll optimize in a second pass.
- * A token can either be a %-prefixed sequence (usually a dynamic
- * token but it can be an escaped sequence), or a string. */
- cur = def;
- eos = def + strlen(def);
- *fmt = new_lt = last_lt = (logformat_token *)xmalloc(sizeof(logformat_token));
- cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
-
- while (cur < eos) {
- new_lt = (logformat_token *)xmalloc(sizeof(logformat_token));
- last_lt->next = new_lt;
- last_lt = new_lt;
- cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
- }
-
- return 1;
-}
-
-void
-accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions)
-{
- logformat_token *t;
- logformat *format;
-
- struct logformat_token_table_entry *te;
- debugs(46, 4, "accessLogDumpLogFormat called");
-
- for (format = definitions; format; format = format->next) {
- debugs(46, 3, "Dumping logformat definition for " << format->name);
- storeAppendPrintf(entry, "logformat %s ", format->name);
-
- for (t = format->format; t; t = t->next) {
- if (t->type == LFT_STRING)
- storeAppendPrintf(entry, "%s", t->data.string);
- else {
- char argbuf[256];
- char *arg = NULL;
- logformat_bcode_t type = t->type;
-
- switch (type) {
- /* special cases */
-
- case LFT_STRING:
- break;
-#if ICAP_CLIENT
- case LFT_ICAP_LAST_MATCHED_HEADER_ELEM:
- case LFT_ICAP_REQ_HEADER_ELEM:
- case LFT_ICAP_REP_HEADER_ELEM:
-#endif
- case LFT_REQUEST_HEADER_ELEM:
- case LFT_ADAPTED_REQUEST_HEADER_ELEM:
- case LFT_REPLY_HEADER_ELEM:
-
- if (t->data.header.separator != ',')
- snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element);
- else
- snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element);
-
- arg = argbuf;
-
- switch (type) {
- case LFT_REQUEST_HEADER_ELEM:
- type = LFT_REQUEST_HEADER_ELEM;
- break;
- case LFT_ADAPTED_REQUEST_HEADER_ELEM:
- type = LFT_ADAPTED_REQUEST_HEADER_ELEM;
- break;
- case LFT_REPLY_HEADER_ELEM:
- type = LFT_REPLY_HEADER_ELEM;
- break;
-#if ICAP_CLIENT
- case LFT_ICAP_LAST_MATCHED_HEADER_ELEM:
- type = LFT_ICAP_LAST_MATCHED_HEADER;
- break;
- case LFT_ICAP_REQ_HEADER_ELEM:
- type = LFT_ICAP_REQ_HEADER;
- break;
- case LFT_ICAP_REP_HEADER_ELEM:
- type = LFT_ICAP_REP_HEADER;
- break;
-#endif
- default:
- break;
- }
-
- break;
-
- case LFT_REQUEST_ALL_HEADERS:
- case LFT_ADAPTED_REQUEST_ALL_HEADERS:
- case LFT_REPLY_ALL_HEADERS:
-
-#if ICAP_CLIENT
- case LFT_ICAP_LAST_MATCHED_ALL_HEADERS:
- case LFT_ICAP_REQ_ALL_HEADERS:
- case LFT_ICAP_REP_ALL_HEADERS:
-#endif
-
- switch (type) {
- case LFT_REQUEST_ALL_HEADERS:
- type = LFT_REQUEST_HEADER;
- break;
- case LFT_ADAPTED_REQUEST_ALL_HEADERS:
- type = LFT_ADAPTED_REQUEST_HEADER;
- break;
- case LFT_REPLY_ALL_HEADERS:
- type = LFT_REPLY_HEADER;
- break;
-#if ICAP_CLIENT
- case LFT_ICAP_LAST_MATCHED_ALL_HEADERS:
- type = LFT_ICAP_LAST_MATCHED_HEADER;
- break;
- case LFT_ICAP_REQ_ALL_HEADERS:
- type = LFT_ICAP_REQ_HEADER;
- break;
- case LFT_ICAP_REP_ALL_HEADERS:
- type = LFT_ICAP_REP_HEADER;
- break;
-#endif
- default:
- break;
- }
-
- break;
-
- default:
- if (t->data.string)
- arg = t->data.string;
-
- break;
- }
-
- entry->append("%", 1);
-
- switch (t->quote) {
-
- case LOG_QUOTE_QUOTES:
- entry->append("\"", 1);
- break;
-
- case LOG_QUOTE_BRAKETS:
- entry->append("[", 1);
- break;
-
- case LOG_QUOTE_URL:
- entry->append("#", 1);
- break;
-
- case LOG_QUOTE_RAW:
- entry->append("'", 1);
- break;
-
- case LOG_QUOTE_NONE:
- break;
- }
-
- if (t->left)
- entry->append("-", 1);
-
- if (t->zero)
- entry->append("0", 1);
-
- if (t->width)
- storeAppendPrintf(entry, "%d", (int) t->width);
-
- if (t->precision)
- storeAppendPrintf(entry, ".%d", (int) t->precision);
-
- if (arg)
- storeAppendPrintf(entry, "{%s}", arg);
-
- for (te = logformat_token_table; te->config != NULL; te++) {
- if (te->token_type == type) {
- storeAppendPrintf(entry, "%s", te->config);
- break;
- }
- }
-
- if (t->space)
- entry->append(" ", 1);
-
- assert(te->config != NULL);
- }
- }
-
- entry->append("\n", 1);
- }
-
-}
-
-void
-accessLogFreeLogFormat(logformat_token ** tokens)
-{
- while (*tokens) {
- logformat_token *token = *tokens;
- *tokens = token->next;
- safe_free(token->data.string);
- xfree(token);
- }
-}
-
-static void
-accessLogSquid(AccessLogEntry * al, Logfile * logfile)
-{
- const char *client = NULL;
- const char *user = NULL;
- char buf[MAX_IPSTRLEN];
-
- if (Config.onoff.log_fqdn) {
- client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
- }
-
- if (client == NULL) {
- client = al->cache.caddr.NtoA(buf,MAX_IPSTRLEN);
- }
-
- user = accessLogFormatName(al->cache.authuser);
-
- if (!user)
- user = accessLogFormatName(al->cache.extuser);
-
-#if USE_SSL
-
- if (!user)
- user = accessLogFormatName(al->cache.ssluser);
-
-#endif
-
- if (!user)
- user = accessLogFormatName(al->cache.rfc931);
-
- if (user && !*user)
- safe_free(user);
-
- if (!Config.onoff.log_mime_hdrs) {
- logfilePrintf(logfile, "%9ld.%03d %6d %s %s%s/%03d %"PRId64" %s %s %s %s%s/%s %s\n",
- (long int) current_time.tv_sec,
- (int) current_time.tv_usec / 1000,
- al->cache.msec,
- client,
- log_tags[al->cache.code],
- al->http.statusSfx(),
- al->http.code,
- al->cache.replySize,
- al->_private.method_str,
- al->url,
- user ? user : dash_str,
- al->hier.ping.timedout ? "TIMEOUT_" : "",
- hier_code_str[al->hier.code],
- al->hier.host,
- al->http.content_type);
- } else {
- char *ereq = log_quote(al->headers.request);
- char *erep = log_quote(al->headers.reply);
- logfilePrintf(logfile, "%9ld.%03d %6d %s %s%s/%03d %"PRId64" %s %s %s %s%s/%s %s [%s] [%s]\n",
- (long int) current_time.tv_sec,
- (int) current_time.tv_usec / 1000,
- al->cache.msec,
- client,
- log_tags[al->cache.code],
- al->http.statusSfx(),
- al->http.code,
- al->cache.replySize,
- al->_private.method_str,
- al->url,
- user ? user : dash_str,
- al->hier.ping.timedout ? "TIMEOUT_" : "",
- hier_code_str[al->hier.code],
- al->hier.host,
- al->http.content_type,
- ereq,
- erep);
- safe_free(ereq);
- safe_free(erep);
- }
- safe_free(user);
-}
-
-static void
-accessLogCommon(AccessLogEntry * al, Logfile * logfile)
-{
- const char *client = NULL;
- char *user1 = NULL, *user2 = NULL;
- char buf[MAX_IPSTRLEN];
-
- if (Config.onoff.log_fqdn) {
- client = fqdncache_gethostbyaddr(al->cache.caddr, 0);
- }
-
- if (client == NULL) {
- client = al->cache.caddr.NtoA(buf,MAX_IPSTRLEN);
- }
-
- user1 = accessLogFormatName(al->cache.authuser);
-
- user2 = accessLogFormatName(al->cache.rfc931);
-
- logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %"PRId64" %s%s:%s%s",
- client,
- user2 ? user2 : dash_str,
- user1 ? user1 : dash_str,
- mkhttpdlogtime(&squid_curtime),
- al->_private.method_str,
- al->url,
- al->http.version.major, al->http.version.minor,
- al->http.code,
- al->cache.replySize,
- log_tags[al->cache.code],
- al->http.statusSfx(),
- hier_code_str[al->hier.code],
- (Config.onoff.log_mime_hdrs?"":"\n"));
-
- safe_free(user1);
-
- safe_free(user2);
-
- if (Config.onoff.log_mime_hdrs) {
- char *ereq = log_quote(al->headers.request);
- char *erep = log_quote(al->headers.reply);
- logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
- safe_free(ereq);
- safe_free(erep);
- }
-}
-
-#if ICAP_CLIENT
-static void
-accessLogICAPSquid(AccessLogEntry * al, Logfile * logfile)
-{
- const char *client = NULL;
- const char *user = NULL;
- char tmp[MAX_IPSTRLEN], clientbuf[MAX_IPSTRLEN];
-
- if (al->cache.caddr.IsAnyAddr()) { // ICAP OPTIONS xactions lack client
- client = "-";
- } else {
- if (Config.onoff.log_fqdn)
- client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
- if (!client)
- client = al->cache.caddr.NtoA(clientbuf, MAX_IPSTRLEN);
- }
-
- user = accessLogFormatName(al->cache.authuser);
-
- if (!user)
- user = accessLogFormatName(al->cache.extuser);
-
-#if USE_SSL
-
- if (!user)
- user = accessLogFormatName(al->cache.ssluser);
+#if USE_FORW_VIA_DB
+typedef struct {
+ hash_link hash;
+ int n;
+} fvdb_entry;
+static hash_table *via_table = NULL;
+static hash_table *forw_table = NULL;
+static void fvdbInit();
+static void fvdbDumpTable(StoreEntry * e, hash_table * hash);
+static void fvdbCount(hash_table * hash, const char *key);
+static OBJH fvdbDumpVia;
+static OBJH fvdbDumpForw;
+static FREE fvdbFreeEntry;
+static void fvdbClear(void);
+static void fvdbRegisterWithCacheManager();
#endif
- if (!user)
- user = accessLogFormatName(al->cache.rfc931);
-
- if (user && !*user)
- safe_free(user);
-
- logfilePrintf(logfile, "%9ld.%03d %6d %s -/%03d %"PRId64" %s %s %s -/%s -\n",
- (long int) current_time.tv_sec,
- (int) current_time.tv_usec / 1000,
-
- al->icap.trTime,
- client,
-
- al->icap.resStatus,
- al->icap.bytesRead,
- Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod),
- al->icap.reqUri.termedBuf(),
- user ? user : dash_str,
- al->icap.hostAddr.NtoA(tmp, MAX_IPSTRLEN));
- safe_free(user);
-}
-#endif
+int LogfileStatus = LOG_DISABLE;
void
accessLogLogTo(customlog* log, AccessLogEntry * al, ACLChecklist * checklist)
switch (log->type) {
- case CLF_AUTO:
- if (Config.onoff.common_log)
- accessLogCommon(al, log->logfile);
- else
- accessLogSquid(al, log->logfile);
+ case Log::Format::CLF_SQUID:
+ Log::Format::SquidNative(al, log->logfile);
+ break;
+
+ case Log::Format::CLF_COMBINED:
+ Log::Format::HttpdCombined(al, log->logfile);
+ break;
+
+ case Log::Format::CLF_COMMON:
+ Log::Format::HttpdCommon(al, log->logfile);
break;
- case CLF_SQUID:
- accessLogSquid(al, log->logfile);
+ case Log::Format::CLF_REFERER:
+ Log::Format::SquidReferer(al, log->logfile);
break;
- case CLF_COMMON:
- accessLogCommon(al, log->logfile);
+ case Log::Format::CLF_USERAGENT:
+ Log::Format::SquidUserAgent(al, log->logfile);
break;
- case CLF_CUSTOM:
- accessLogCustom(al, log);
+ case Log::Format::CLF_CUSTOM:
+ Log::Format::SquidCustom(al, log);
break;
#if ICAP_CLIENT
- case CLF_ICAP_SQUID:
- accessLogICAPSquid(al, log->logfile);
+ case Log::Format::CLF_ICAP_SQUID:
+ Log::Format::SquidIcap(al, log->logfile);
break;
#endif
- case CLF_NONE:
+ case Log::Format::CLF_NONE:
return; // abort!
default:
accessLogRegisterWithCacheManager();
- assert(sizeof(log_tags) == (LOG_TYPE_MAX + 1) * sizeof(char *));
-
#if USE_ADAPTATION
alLogformatHasAdaptToken = false;
#endif
#endif
for (log = Config.Log.accesslogs; log; log = log->next) {
- if (log->type == CLF_NONE)
+ if (log->type == Log::Format::CLF_NONE)
continue;
log->logfile = logfileOpen(log->filename, MAX_URL << 2, 1);
#endif
}
-const char *
-accessLogTime(time_t t)
-{
-
- struct tm *tm;
- static char buf[128];
- static time_t last_t = 0;
-
- if (t != last_t) {
- tm = localtime(&t);
- strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
- last_t = t;
- }
-
- return buf;
-}
-
-
#if USE_FORW_VIA_DB
static void
#if USE_DELAY_POOLS
#include "ClientDelayConfig.h"
#endif
+#include "comm.h"
#include "ConfigParser.h"
#include "CpuAffinity.h"
#if USE_DELAY_POOLS
#include "htcp.h"
#include "StoreFileSystem.h"
#include "DiskIO/DiskIOModule.h"
-#include "comm.h"
#include "ipc/Kids.h"
#include "ipc/Coordinator.h"
#include "ipc/Strand.h"
#include "ip/tools.h"
-#if USE_EPOLL
-#include "comm_epoll.h"
-#endif
-#if USE_KQUEUE
-#include "comm_kqueue.h"
-#endif
-#if USE_POLL
-#include "comm_poll.h"
-#endif
-#if defined(USE_SELECT) || defined(USE_SELECT_WIN32)
-#include "comm_select.h"
-#endif
#include "SquidTime.h"
#include "SwapDir.h"
#include "forward.h"
#if ICAP_CLIENT
icapLogClose();
#endif
- useragentLogClose();
- refererCloseLog();
eventAdd("mainReconfigureFinish", &mainReconfigureFinish, NULL, 0, 1,
false);
icapLogOpen();
#endif
storeLogOpen();
- useragentOpenLog();
- refererOpenLog();
#if USE_DNSSERVERS
dnsInit();
storeDirWriteCleanLogs(1);
storeLogRotate(); /* store.log */
accessLogRotate(); /* access.log */
- useragentRotateLog(); /* useragent.log */
- refererRotateLog(); /* referer.log */
#if ICAP_CLIENT
icapLogRotate(); /*icap.log*/
#endif
-#if WIP_FWD_LOG
- fwdLogRotate();
-#endif
-
icmpEngine.Open();
#if USE_DNSSERVERS
dnsInit();
debugs(1, 0, "Starting Squid Cache version " << version_string << " for " << CONFIG_HOST_TYPE << "...");
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
debugs(1, 0, "Running as " << WIN32_Service_name << " Windows System Service on " << WIN32_OS_string);
debugs(1, 0, "Service command line is: " << WIN32_Service_Command_Line);
} else
debugs(1, 0, "Running on " << WIN32_OS_string);
-
#endif
debugs(1, 1, "Process ID " << getpid());
externalAclInit();
- useragentOpenLog();
-
- refererOpenLog();
-
httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
httpReplyInitModule(); /* must go before accepting replies */
{
ConfigureCurrentKid(argv[0]);
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
int WIN32_init_err;
#endif
#endif
-#ifdef _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
if ((WIN32_init_err = WIN32_Subsystem_Init(&argc, &argv)))
return WIN32_init_err;
-
#endif
/* call mallopt() before anything else */
comm_init();
- comm_select_init();
-
mainInitialize();
test_access();
/* init comm module */
comm_init();
- comm_select_init();
-
if (opt_no_daemon) {
/* we have to init fdstat here. */
fd_open(0, FD_LOG, "stdin");
Store::Root().sync(); /* Flush log writes */
storeLogClose();
accessLogClose();
- useragentLogClose();
- refererCloseLog();
-#if WIP_FWD_LOG
-
- fwdUninit();
-#endif
-
Store::Root().sync(); /* Flush log close */
StoreFileSystem::FreeAllFs();
DiskIOModule::FreeAllModules();
CBDATA_NAMESPACED_CLASS_INIT(Mgr, Forwarder);
-Mgr::Forwarder::RequestsMap Mgr::Forwarder::TheRequestsMap;
-unsigned int Mgr::Forwarder::LastRequestId = 0;
Mgr::Forwarder::Forwarder(int aFd, const ActionParams &aParams,
HttpRequest* aRequest, StoreEntry* anEntry):
- AsyncJob("Mgr::Forwarder"),
- params(aParams),
- request(aRequest), entry(anEntry), fd(aFd), requestId(0), closer(NULL)
+ Ipc::Forwarder(new Request(KidIdentifier, 0, aFd, aParams), 10),
+ httpRequest(aRequest), entry(anEntry), fd(aFd)
{
- debugs(16, 5, HERE << "FD " << aFd);
+ debugs(16, 5, HERE << "FD " << fd);
Must(fd >= 0);
- Must(request != NULL);
+ Must(httpRequest != NULL);
Must(entry != NULL);
- HTTPMSGLOCK(request);
+ HTTPMSGLOCK(httpRequest);
entry->lock();
EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT);
Mgr::Forwarder::~Forwarder()
{
debugs(16, 5, HERE);
- Must(request != NULL);
+ Must(httpRequest != NULL);
Must(entry != NULL);
- Must(requestId == 0);
- HTTPMSGUNLOCK(request);
+ HTTPMSGUNLOCK(httpRequest);
entry->unregisterAbort();
entry->unlock();
- close();
+ cleanup();
}
/// closes our copy of the client HTTP connection socket
void
-Mgr::Forwarder::close()
+Mgr::Forwarder::cleanup()
{
if (fd >= 0) {
if (closer != NULL) {
}
void
-Mgr::Forwarder::start()
+Mgr::Forwarder::handleError()
{
- debugs(16, 3, HERE);
- entry->registerAbort(&Forwarder::Abort, this);
-
- typedef NullaryMemFunT<Mgr::Forwarder> Dialer;
- AsyncCall::Pointer callback = JobCallback(16, 5, Dialer, this,
- Forwarder::handleRemoteAck);
- if (++LastRequestId == 0) // don't use zero value as requestId
- ++LastRequestId;
- requestId = LastRequestId;
- TheRequestsMap[requestId] = callback;
- Request mgrRequest(KidIdentifier, requestId, fd, params);
- Ipc::TypedMsgHdr message;
-
- try {
- mgrRequest.pack(message);
- } catch (...) {
- // assume the pack() call failed because the message did not fit
- // TODO: add a more specific exception?
- debugs(16, DBG_CRITICAL, "ERROR: uri " << entry->url() << " exceeds buffer size");
- quitOnError("long URI", errorCon(ERR_INVALID_URL, HTTP_REQUEST_URI_TOO_LARGE, request));
- }
-
- Ipc::SendMessage(Ipc::coordinatorAddr, message);
- const double timeout = 10; // in seconds
- eventAdd("Mgr::Forwarder::requestTimedOut", &Forwarder::RequestTimedOut,
- this, timeout, 0, false);
+ debugs(16, DBG_CRITICAL, "ERROR: uri " << entry->url() << " exceeds buffer size");
+ sendError(errorCon(ERR_INVALID_URL, HTTP_REQUEST_URI_TOO_LARGE, httpRequest));
+ mustStop("long URI");
}
void
-Mgr::Forwarder::swanSong()
+Mgr::Forwarder::handleTimeout()
{
- debugs(16, 5, HERE);
- removeTimeoutEvent();
- if (requestId > 0) {
- DequeueRequest(requestId);
- requestId = 0;
- }
- close();
+ sendError(errorCon(ERR_LIFETIME_EXP, HTTP_REQUEST_TIMEOUT, httpRequest));
+ Ipc::Forwarder::handleTimeout();
}
-bool
-Mgr::Forwarder::doneAll() const
+void
+Mgr::Forwarder::handleException(const std::exception& e)
{
- debugs(16, 5, HERE);
- return requestId == 0;
+ if (entry != NULL && httpRequest != NULL && fd >= 0)
+ sendError(errorCon(ERR_INVALID_RESP, HTTP_INTERNAL_SERVER_ERROR, httpRequest));
+ Ipc::Forwarder::handleException(e);
}
/// called when the client socket gets closed by some external force
void
-Mgr::Forwarder::noteCommClosed(const CommCloseCbParams &io)
+Mgr::Forwarder::noteCommClosed(const CommCloseCbParams& params)
{
debugs(16, 5, HERE);
- Must(fd == io.fd);
+ Must(fd == params.fd);
fd = -1;
mustStop("commClosed");
}
void
Mgr::Forwarder::handleRemoteAck()
{
- debugs(16, 3, HERE);
- Must(entry != NULL);
+ Ipc::Forwarder::handleRemoteAck();
- requestId = 0;
+ Must(entry != NULL);
EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
entry->complete();
}
-/// Mgr::Forwarder::requestTimedOut wrapper
+/// send error page
void
-Mgr::Forwarder::RequestTimedOut(void* param)
+Mgr::Forwarder::sendError(ErrorState *error)
{
debugs(16, 3, HERE);
- Must(param != NULL);
- Forwarder* mgrFwdr = static_cast<Forwarder*>(param);
- // use async call to enable job call protection that time events lack
- CallJobHere(16, 5, mgrFwdr, Mgr::Forwarder, requestTimedOut);
-}
-
-/// called when Coordinator fails to start processing the request [in time]
-void
-Mgr::Forwarder::requestTimedOut()
-{
- debugs(16, 3, HERE);
- quitOnError("timeout", errorCon(ERR_LIFETIME_EXP, HTTP_REQUEST_TIMEOUT, request));
-}
-
-/// terminate with an error
-void
-Mgr::Forwarder::quitOnError(const char *reason, ErrorState *error)
-{
- debugs(16, 3, HERE);
- Must(reason != NULL);
Must(error != NULL);
Must(entry != NULL);
- Must(request != NULL);
+ Must(httpRequest != NULL);
EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
entry->buffer();
errorStateFree(error);
entry->flush();
entry->complete();
-
- mustStop(reason);
-}
-
-void
-Mgr::Forwarder::callException(const std::exception& e)
-{
- try {
- if (entry != NULL && request != NULL && fd >= 0)
- quitOnError("exception", errorCon(ERR_INVALID_RESP, HTTP_INTERNAL_SERVER_ERROR, request));
- } catch (const std::exception& ex) {
- debugs(16, DBG_CRITICAL, HERE << ex.what());
- }
- AsyncJob::callException(e);
-}
-
-/// returns and forgets the right Forwarder callback for the request
-AsyncCall::Pointer
-Mgr::Forwarder::DequeueRequest(unsigned int requestId)
-{
- debugs(16, 3, HERE);
- Must(requestId != 0);
- AsyncCall::Pointer call;
- RequestsMap::iterator request = TheRequestsMap.find(requestId);
- if (request != TheRequestsMap.end()) {
- call = request->second;
- Must(call != NULL);
- TheRequestsMap.erase(request);
- }
- return call;
-}
-
-/// called when we are no longer waiting for Coordinator to respond
-void
-Mgr::Forwarder::removeTimeoutEvent()
-{
- if (eventFind(&Forwarder::RequestTimedOut, this))
- eventDelete(&Forwarder::RequestTimedOut, this);
-}
-
-void
-Mgr::Forwarder::HandleRemoteAck(unsigned int requestId)
-{
- debugs(16, 3, HERE);
- Must(requestId != 0);
-
- AsyncCall::Pointer call = DequeueRequest(requestId);
- if (call != NULL)
- ScheduleCallHere(call);
-}
-
-/// called when something goes wrong with the Store entry
-void
-Mgr::Forwarder::Abort(void* param)
-{
- Forwarder* mgrFwdr = static_cast<Forwarder*>(param);
- if (mgrFwdr->fd >= 0)
- comm_close(mgrFwdr->fd);
}
#ifndef SQUID_MGR_FORWARDER_H
#define SQUID_MGR_FORWARDER_H
-#include "base/AsyncJob.h"
+#include "ipc/Forwarder.h"
#include "mgr/ActionParams.h"
-#include <map>
class CommCloseCbParams;
* Waits for an ACK from Coordinator while holding the Store entry.
* Fills the store entry with an error response if forwarding fails.
*/
-class Forwarder: public AsyncJob
+class Forwarder: public Ipc::Forwarder
{
public:
Forwarder(int aFd, const ActionParams &aParams, HttpRequest* aRequest,
StoreEntry* anEntry);
virtual ~Forwarder();
- /// finds and calls the right Forwarder upon Coordinator's response
- static void HandleRemoteAck(unsigned int requestId);
-
- /* has-to-be-public AsyncJob API */
- virtual void callException(const std::exception& e);
-
protected:
- /* AsyncJob API */
- virtual void start();
- virtual void swanSong();
- virtual bool doneAll() const;
+ /* Ipc::Forwarder API */
+ virtual void cleanup(); ///< perform cleanup actions
+ virtual void handleError();
+ virtual void handleTimeout();
+ virtual void handleException(const std::exception& e);
+ virtual void handleRemoteAck();
private:
- void handleRemoteAck();
- static void RequestTimedOut(void* param);
- void requestTimedOut();
- void quitOnError(const char *reason, ErrorState *error);
void noteCommClosed(const CommCloseCbParams& params);
- void removeTimeoutEvent();
- static AsyncCall::Pointer DequeueRequest(unsigned int requestId);
- static void Abort(void* param);
- void close();
+ void sendError(ErrorState* error);
private:
- ActionParams params; ///< action parameters to pass to the other side
- HttpRequest* request; ///< HTTP client request for detailing errors
+ HttpRequest* httpRequest; ///< HTTP client request for detailing errors
StoreEntry* entry; ///< Store entry expecting the response
int fd; ///< HTTP client connection descriptor
- unsigned int requestId; ///< request id
AsyncCall::Pointer closer; ///< comm_close handler for the HTTP connection
- /// maps requestId to Forwarder::handleRemoteAck callback
- typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
- static RequestsMap TheRequestsMap; ///< pending Coordinator requests
-
- static unsigned int LastRequestId; ///< last requestId used
-
CBDATA_CLASS2(Forwarder);
};
#include "config.h"
#include "base/TextException.h"
+#include "ipc/UdsOp.h"
#include "mgr/Command.h"
#include "mgr/Filler.h"
#include "mgr/FunAction.h"
Mgr::FunAction::respond(const Request& request)
{
debugs(16, 5, HERE);
- const int fd = ImportHttpFdIntoComm(request.fd);
+ const int fd = Ipc::ImportFdIntoComm(request.fd, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket);
Must(fd >= 0);
Must(request.requestId != 0);
AsyncJob::Start(new Mgr::Filler(this, fd, request.requestId));
#include "base/TextException.h"
#include "HttpReply.h"
#include "ipc/Messages.h"
+#include "ipc/UdsOp.h"
#include "ipc/TypedMsgHdr.h"
#include "mgr/Filler.h"
#include "mgr/InfoAction.h"
Mgr::InfoAction::respond(const Request& request)
{
debugs(16, 5, HERE);
- int fd = ImportHttpFdIntoComm(request.fd);
+ int fd = Ipc::ImportFdIntoComm(request.fd, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket);
Must(fd >= 0);
Must(request.requestId != 0);
AsyncJob::Start(new Mgr::Filler(this, fd, request.requestId));
#include "comm/Write.h"
#include "CommCalls.h"
#include "HttpReply.h"
-#include "ipc/Coordinator.h"
+#include "ipc/UdsOp.h"
#include "mgr/ActionWriter.h"
-#include "mgr/Command.h"
#include "mgr/Inquirer.h"
#include "mgr/Request.h"
#include "mgr/Response.h"
#include "SquidTime.h"
#include <memory>
-#include <algorithm>
CBDATA_NAMESPACED_CLASS_INIT(Mgr, Inquirer);
-Mgr::Inquirer::RequestsMap Mgr::Inquirer::TheRequestsMap;
-unsigned int Mgr::Inquirer::LastRequestId = 0;
-/// compare Ipc::StrandCoord using kidId, for std::sort() below
-static bool
-LesserStrandByKidId(const Ipc::StrandCoord &c1, const Ipc::StrandCoord &c2)
-{
- return c1.kidId < c2.kidId;
-}
-
-Mgr::Inquirer::Inquirer(Action::Pointer anAction, int aFd,
+Mgr::Inquirer::Inquirer(Action::Pointer anAction,
const Request &aCause, const Ipc::StrandCoords &coords):
- AsyncJob("Mgr::Inquirer"),
+ Ipc::Inquirer(aCause.clone(), coords, anAction->atomic() ? 10 : 100),
aggrAction(anAction),
- cause(aCause),
- fd(aFd),
- strands(coords), pos(strands.begin()),
- requestId(0), closer(NULL), timeout(aggrAction->atomic() ? 10 : 100)
+ fd(Ipc::ImportFdIntoComm(aCause.fd, SOCK_STREAM, IPPROTO_TCP, Ipc::fdnHttpSocket))
{
- debugs(16, 5, HERE << "FD " << aFd << " action: " << aggrAction);
-
- // order by ascending kid IDs; useful for non-aggregatable stats
- std::sort(strands.begin(), strands.end(), LesserStrandByKidId);
+ debugs(16, 5, HERE << "FD " << fd << " action: " << aggrAction);
closer = asyncCall(16, 5, "Mgr::Inquirer::noteCommClosed",
CommCbMemFunT<Inquirer, CommCloseCbParams>(this, &Inquirer::noteCommClosed));
comm_add_close_handler(fd, closer);
}
-Mgr::Inquirer::~Inquirer()
-{
- debugs(16, 5, HERE);
- close();
-}
-
/// closes our copy of the client HTTP connection socket
void
-Mgr::Inquirer::close()
+Mgr::Inquirer::cleanup()
{
if (fd >= 0) {
removeCloseHandler();
Mgr::Inquirer::start()
{
debugs(16, 5, HERE);
+ Ipc::Inquirer::start();
Must(fd >= 0);
Must(aggrAction != NULL);
inquire();
}
-void
-Mgr::Inquirer::inquire()
-{
- if (pos == strands.end()) {
- Must(done());
- return;
- }
-
- Must(requestId == 0);
- AsyncCall::Pointer callback = asyncCall(16, 5, "Mgr::Inquirer::handleRemoteAck",
- HandleAckDialer(this, &Inquirer::handleRemoteAck, Response()));
- if (++LastRequestId == 0) // don't use zero value as requestId
- ++LastRequestId;
- requestId = LastRequestId;
- const int kidId = pos->kidId;
- debugs(16, 4, HERE << "inquire kid: " << kidId << status());
- TheRequestsMap[requestId] = callback;
- Request mgrRequest(KidIdentifier, requestId, fd,
- aggrAction->command().params);
- Ipc::TypedMsgHdr message;
- mgrRequest.pack(message);
- Ipc::SendMessage(Ipc::Port::MakeAddr(Ipc::strandAddrPfx, kidId), message);
- eventAdd("Mgr::Inquirer::requestTimedOut", &Inquirer::RequestTimedOut,
- this, timeout, 0, false);
-}
-
-/// called when a strand is done writing its output
-void
-Mgr::Inquirer::handleRemoteAck(const Response& response)
-{
- debugs(16, 4, HERE << status());
- requestId = 0;
- removeTimeoutEvent();
- if (response.hasAction())
- aggrAction->add(response.getAction());
- Must(!done()); // or we should not be called
- ++pos; // advance after a successful inquiry
- inquire();
-}
-
/// called when the HTTP client or some external force closed our socket
void
Mgr::Inquirer::noteCommClosed(const CommCloseCbParams& params)
mustStop("commClosed");
}
+bool
+Mgr::Inquirer::aggregate(Ipc::Response::Pointer aResponse)
+{
+ Mgr::Response& response = static_cast<Response&>(*aResponse);
+ if (response.hasAction())
+ aggrAction->add(response.getAction());
+ return true;
+}
+
void
-Mgr::Inquirer::swanSong()
+Mgr::Inquirer::sendResponse()
{
- debugs(16, 5, HERE);
- removeTimeoutEvent();
- if (requestId > 0) {
- DequeueRequest(requestId);
- requestId = 0;
- }
if (aggrAction->aggregatable()) {
removeCloseHandler();
AsyncJob::Start(new ActionWriter(aggrAction, fd));
fd = -1; // should not close fd because we passed it to ActionWriter
}
- close();
}
bool
Mgr::Inquirer::doneAll() const
{
- return !writer && pos == strands.end();
-}
-
-/// returns and forgets the right Inquirer callback for strand request
-AsyncCall::Pointer
-Mgr::Inquirer::DequeueRequest(unsigned int requestId)
-{
- debugs(16, 3, HERE << " requestId " << requestId);
- Must(requestId != 0);
- AsyncCall::Pointer call;
- RequestsMap::iterator request = TheRequestsMap.find(requestId);
- if (request != TheRequestsMap.end()) {
- call = request->second;
- Must(call != NULL);
- TheRequestsMap.erase(request);
- }
- return call;
-}
-
-void
-Mgr::Inquirer::HandleRemoteAck(const Mgr::Response& response)
-{
- Must(response.requestId != 0);
- AsyncCall::Pointer call = DequeueRequest(response.requestId);
- if (call != NULL) {
- HandleAckDialer* dialer = dynamic_cast<HandleAckDialer*>(call->getDialer());
- Must(dialer);
- dialer->arg1 = response;
- ScheduleCallHere(call);
- }
-}
-
-/// called when we are no longer waiting for the strand to respond
-void
-Mgr::Inquirer::removeTimeoutEvent()
-{
- if (eventFind(&Inquirer::RequestTimedOut, this))
- eventDelete(&Inquirer::RequestTimedOut, this);
-}
-
-/// Mgr::Inquirer::requestTimedOut wrapper
-void
-Mgr::Inquirer::RequestTimedOut(void* param)
-{
- debugs(16, 3, HERE);
- Must(param != NULL);
- Inquirer* cmi = static_cast<Inquirer*>(param);
- // use async call to enable job call protection that time events lack
- CallJobHere(16, 5, cmi, Mgr::Inquirer, requestTimedOut);
-}
-
-/// called when the strand failed to respond (or finish responding) in time
-void
-Mgr::Inquirer::requestTimedOut()
-{
- debugs(16, 3, HERE);
- if (requestId != 0) {
- DequeueRequest(requestId);
- requestId = 0;
- Must(!done()); // or we should not be called
- ++pos; // advance after a failed inquiry
- inquire();
- }
-}
-
-const char*
-Mgr::Inquirer::status() const
-{
- static MemBuf buf;
- buf.reset();
- buf.Printf(" [FD %d, requestId %u]", fd, requestId);
- buf.terminate();
- return buf.content();
+ return !writer && Ipc::Inquirer::doneAll();
}
#ifndef SQUID_MGR_INQUIRER_H
#define SQUID_MGR_INQUIRER_H
-#include "base/AsyncJobCalls.h"
-#include "base/AsyncJob.h"
-#include "ipc/StrandCoords.h"
-#include "MemBuf.h"
+#include "ipc/Inquirer.h"
#include "mgr/Action.h"
-#include "mgr/Request.h"
-#include <map>
class CommIoCbParams;
class CommCloseCbParams;
/// Coordinator's job that sends a cache manage request to each strand,
/// aggregating individual strand responses and dumping the result if needed
-class Inquirer: public AsyncJob
+class Inquirer: public Ipc::Inquirer
{
public:
- Inquirer(Action::Pointer anAction, int aFd, const Request &aCause,
+ Inquirer(Action::Pointer anAction, const Request &aCause,
const Ipc::StrandCoords &coords);
- virtual ~Inquirer();
-
- /// finds and calls the right Inquirer upon strand's response
- static void HandleRemoteAck(const Mgr::Response& response);
protected:
/* AsyncJob API */
virtual void start();
- virtual void swanSong();
virtual bool doneAll() const;
- virtual const char *status() const;
-private:
- typedef UnaryMemFunT<Inquirer, Response, const Response&> HandleAckDialer;
+ /* Ipc::Inquirer API */
+ virtual void cleanup();
+ virtual void sendResponse();
+ virtual bool aggregate(Ipc::Response::Pointer aResponse);
- void inquire();
+private:
void noteWroteHeader(const CommIoCbParams& params);
void noteCommClosed(const CommCloseCbParams& params);
-
- void handleRemoteAck(const Response& response);
-
- static AsyncCall::Pointer DequeueRequest(unsigned int requestId);
-
- static void RequestTimedOut(void* param);
- void requestTimedOut();
- void removeTimeoutEvent();
-
- void close();
void removeCloseHandler();
private:
Action::Pointer aggrAction; //< action to aggregate
- Request cause; ///< cache manager request received from HTTP client
int fd; ///< HTTP client socket descriptor
- Ipc::StrandCoords strands; ///< all strands we want to query, in order
- Ipc::StrandCoords::const_iterator pos; ///< strand we should query now
-
- unsigned int requestId; ///< ID of our outstanding request to strand
AsyncCall::Pointer writer; ///< comm_write callback
AsyncCall::Pointer closer; ///< comm_close handler
- const double timeout; ///< number of seconds to wait for strand response
-
- /// maps requestId to Inquirer::handleRemoteAck callback
- typedef std::map<unsigned int, AsyncCall::Pointer> RequestsMap;
- static RequestsMap TheRequestsMap; ///< pending strand requests
-
- static unsigned int LastRequestId; ///< last requestId used
CBDATA_CLASS2(Inquirer);
};
#include "config.h"
#include "base/TextException.h"
#include "ipc/Messages.h"
+#include "ipc/TypedMsgHdr.h"
#include "mgr/ActionParams.h"
#include "mgr/Request.h"
Mgr::Request::Request(int aRequestorId, unsigned int aRequestId, int aFd,
const ActionParams &aParams):
- requestorId(aRequestorId), requestId(aRequestId),
+ Ipc::Request(aRequestorId, aRequestId),
fd(aFd), params(aParams)
{
Must(requestorId > 0);
- Must(requestId != 0);
}
-Mgr::Request::Request(const Ipc::TypedMsgHdr& msg)
+Mgr::Request::Request(const Request& request):
+ Ipc::Request(request.requestorId, request.requestId),
+ fd(request.fd), params(request.params)
+{
+}
+
+Mgr::Request::Request(const Ipc::TypedMsgHdr& msg):
+ Ipc::Request(0, 0)
{
msg.checkType(Ipc::mtCacheMgrRequest);
msg.getPod(requestorId);
msg.putFd(fd);
}
+
+Ipc::Request::Pointer
+Mgr::Request::clone() const
+{
+ return new Request(*this);
+}
#ifndef SQUID_MGR_REQUEST_H
#define SQUID_MGR_REQUEST_H
-#include "ipc/TypedMsgHdr.h"
+#include "ipc/forward.h"
+#include "ipc/Request.h"
#include "mgr/ActionParams.h"
{
/// cache manager request
-class Request
+class Request: public Ipc::Request
{
public:
Request(int aRequestorId, unsigned int aRequestId, int aFd,
const ActionParams &aParams);
explicit Request(const Ipc::TypedMsgHdr& msg); ///< from recvmsg()
- void pack(Ipc::TypedMsgHdr& msg) const; ///< prepare for sendmsg()
+ /* Ipc::Request API */
+ virtual void pack(Ipc::TypedMsgHdr& msg) const;
+ virtual Pointer clone() const;
+
+private:
+ Request(const Request& request);
public:
- int requestorId; ///< kidId of the requestor; used for response destination
- unsigned int requestId; ///< unique for sender; matches request w/ response
int fd; ///< HTTP client connection descriptor
ActionParams params; ///< action name and parameters
#include "mgr/Response.h"
-std::ostream& Mgr::operator << (std::ostream &os, const Response& response)
+Mgr::Response::Response(unsigned int aRequestId, Action::Pointer anAction):
+ Ipc::Response(aRequestId), action(anAction)
{
- os << "response: {requestId: " << response.requestId << '}';
- return os;
+ Must(!action || action->name()); // if there is an action, it must be named
}
-Mgr::Response::Response(unsigned int aRequestId, Action::Pointer anAction):
- requestId(aRequestId), action(anAction)
+Mgr::Response::Response(const Response& response):
+ Ipc::Response(response.requestId), action(response.action)
{
- Must(!action || action->name()); // if there is an action, it must be named
}
-Mgr::Response::Response(const Ipc::TypedMsgHdr& msg)
+Mgr::Response::Response(const Ipc::TypedMsgHdr& msg):
+ Ipc::Response(0)
{
msg.checkType(Ipc::mtCacheMgrResponse);
msg.getPod(requestId);
}
}
+Ipc::Response::Pointer
+Mgr::Response::clone() const
+{
+ return new Response(*this);
+}
+
bool
Mgr::Response::hasAction() const
{
#ifndef SQUID_MGR_RESPONSE_H
#define SQUID_MGR_RESPONSE_H
+#include "ipc/forward.h"
+#include "ipc/Response.h"
#include "mgr/Action.h"
/// A response to Mgr::Request.
/// May carry strand action data to be aggregated with data from other strands.
-class Response
+class Response: public Ipc::Response
{
public:
- Response(unsigned int aRequestId = 0, Action::Pointer anAction = NULL);
+ Response(unsigned int aRequestId, Action::Pointer anAction = NULL);
explicit Response(const Ipc::TypedMsgHdr& msg); ///< from recvmsg()
- void pack(Ipc::TypedMsgHdr& msg) const; ///< prepare for sendmsg()
+
+ /* Ipc::Response API */
+ virtual void pack(Ipc::TypedMsgHdr& msg) const;
+ virtual Ipc::Response::Pointer clone() const;
+
bool hasAction() const; ///< whether response contain action object
const Action& getAction() const; ///< returns action object
+private:
+ Response(const Response& response);
+
public:
- unsigned int requestId; ///< ID of request we are responding to
Action::Pointer action; ///< action relating to response
};
-extern std::ostream& operator <<(std::ostream &os, const Response &response);
-
} // namespace Mgr
#endif /* SQUID_MGR_RESPONSE_H */
if (mgrWriter->fd >= 0)
comm_close(mgrWriter->fd);
}
-
-
-int
-Mgr::ImportHttpFdIntoComm(int fd)
-{
- struct sockaddr_in addr;
- socklen_t len = sizeof(addr);
- if (getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
- Ip::Address ipAddr(addr);
- struct addrinfo* addr_info = NULL;
- ipAddr.GetAddrInfo(addr_info);
- addr_info->ai_socktype = SOCK_STREAM;
- addr_info->ai_protocol = IPPROTO_TCP;
- comm_import_opened(fd, ipAddr, COMM_NONBLOCKING, Ipc::FdNote(Ipc::fdnHttpSocket), addr_info);
- ipAddr.FreeAddrInfo(addr_info);
- } else {
- debugs(16, DBG_CRITICAL, HERE << "ERROR: FD " << fd << ' ' << xstrerror());
- ::close(fd);
- fd = -1;
- }
- return fd;
-}
CBDATA_CLASS2(StoreToCommWriter);
};
-/// import HTTP socket fd from another strand into our Comm state
-extern int ImportHttpFdIntoComm(int fd);
-
} // namespace Mgr
#endif /* SQUID_MGR_STORE_TO_COMM_WRITER_H */
public:
MimeIcon ();
+ ~MimeIcon ();
void setName (char const *);
char const * getName () const;
void _free();
MimeIcon::MimeIcon () : icon (NULL), url (NULL)
{}
+MimeIcon::~MimeIcon ()
+{
+ _free();
+}
+
void
MimeIcon::setName (char const *aString)
{
return;
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(fileno(fp), O_TEXT);
-
#endif
mimeFreeMemory();
print "/*"
print " * Auto-Generated File. Changes will be destroyed."
print " */"
- print "#include \"squid.h\""
+ print "#include \"config.h\""
codeSkip = 1
e = 0
+ nspath = ""
+}
+
+# when namespace is encountered store it
+/^namespace [a-zA-Z]+/ {
+ nspath = tolower($2) "/" # nested folder
+ namespace = $2 # code namespace reconstruct
+ next
}
# Skip all lines outside of typedef {}
type = t[1]
codeSkip = 1
- print "#include \"" type ".h\""
+ print "#include \"" nspath type ".h\""
+
+ # if namesapce is not empty ??
+ if (namespace) print "namespace " namespace
+ if (namespace) print "{"
+
print "\nconst char *" type "_str[] = {"
for ( i = 1; i < e; ++i)
print "\t\"" Element[i] "\","
print "\t\"" Element[i] "\""
print "};"
+ if (namespace) print "}; // namespace " namespace
next
}
if (e->stats.last_connect_failure) {
storeAppendPrintf(sentry, "Last failed connect() at: %s\n",
- mkhttpdlogtime(&(e->stats.last_connect_failure)));
+ Time::FormatHttpd(e->stats.last_connect_failure));
}
if (e->peer_domain != NULL) {
nfds_alloc <<= 1;
int *old = fds;
fds = (int *)xmalloc(nfds_alloc * sizeof(int));
- xmemcpy(fds, old, nfds * sizeof(int));
+ memcpy(fds, old, nfds * sizeof(int));
if (nfds == PCONN_FDS_SZ)
pconn_fds_pool->freeOne(old);
}
void
-
-PconnModule::add
-(PconnPool *aPool)
+PconnModule::add(PconnPool *aPool)
{
assert(poolCount < MAX_NUM_PCONN_POOLS);
*(pools+poolCount) = aPool;
*/
newsize = fetch->bufofs - retsize;
- xmemmove(fetch->buf, fetch->buf + retsize, fetch->bufofs - newsize);
+ memmove(fetch->buf, fetch->buf + retsize, fetch->bufofs - newsize);
fetch->bufofs = newsize;
* NOTENOTENOTENOTENOTE: buf doesn't point to pd->cd->mask anymore!
* we need to do the copy ourselves!
*/
- xmemcpy(pd->cd->mask + fetch->mask_offset, buf, size);
+ memcpy(pd->cd->mask + fetch->mask_offset, buf, size);
/* NOTE! buf points to the middle of pd->cd->mask! */
int freed_size = 0;
const char *host = pd->host.termedBuf();
- xmemcpy(&cblock, buf, sizeof(cblock));
+ memcpy(&cblock, buf, sizeof(cblock));
/* network -> host conversions */
cblock.ver.current = ntohs(cblock.ver.current);
cblock.ver.required = ntohs(cblock.ver.required);
* Hosted at http://sourceforge.net/projects/squidkerbauth
*/
-#include "squid.h"
+#include "config.h"
#include "base64.h"
+#include "Debug.h"
#if HAVE_KRB5 && HAVE_GSSAPI
#ifdef __cplusplus
#if HEADERS_LOG
SQUIDCEXTERN void headersLog(int cs, int pq, const HttpRequestMethod& m, void *data);
#endif
-SQUIDCEXTERN char *log_quote(const char *header);
SQUIDCEXTERN int logTypeIsATcpHit(log_type);
/*
SQUIDCEXTERN void oid2addr(oid *Dest, Ip::Address &addr, u_int code);
SQUIDCEXTERN Ip::Address *client_entry(Ip::Address *current);
-SQUIDCEXTERN variable_list *snmp_basicFn(variable_list *, snint *);
-SQUIDCEXTERN variable_list *snmp_confFn(variable_list *, snint *);
-SQUIDCEXTERN variable_list *snmp_sysFn(variable_list *, snint *);
-SQUIDCEXTERN variable_list *snmp_prfSysFn(variable_list *, snint *);
-SQUIDCEXTERN variable_list *snmp_prfProtoFn(variable_list *, snint *);
-SQUIDCEXTERN variable_list *snmp_prfPeerFn(variable_list *, snint *);
-SQUIDCEXTERN variable_list *snmp_netIpFn(variable_list *, snint *);
-SQUIDCEXTERN variable_list *snmp_netFqdnFn(variable_list *, snint *);
+extern variable_list *snmp_basicFn(variable_list *, snint *);
+extern variable_list *snmp_confFn(variable_list *, snint *);
+extern variable_list *snmp_sysFn(variable_list *, snint *);
+extern variable_list *snmp_prfSysFn(variable_list *, snint *);
+extern variable_list *snmp_prfProtoFn(variable_list *, snint *);
+extern variable_list *snmp_prfPeerFn(variable_list *, snint *);
+extern variable_list *snmp_netIpFn(variable_list *, snint *);
+extern variable_list *snmp_netFqdnFn(variable_list *, snint *);
#if USE_DNSSERVERS
-SQUIDCEXTERN variable_list *snmp_netDnsFn(variable_list *, snint *);
+extern variable_list *snmp_netDnsFn(variable_list *, snint *);
#else
-SQUIDCEXTERN variable_list *snmp_netIdnsFn(variable_list *, snint *);
+extern variable_list *snmp_netIdnsFn(variable_list *, snint *);
#endif /* USE_DNSSERVERS */
-SQUIDCEXTERN variable_list *snmp_meshPtblFn(variable_list *, snint *);
-SQUIDCEXTERN variable_list *snmp_meshCtblFn(variable_list *, snint *);
+extern variable_list *snmp_meshPtblFn(variable_list *, snint *);
+extern variable_list *snmp_meshCtblFn(variable_list *, snint *);
#endif /* SQUID_SNMP */
#if USE_WCCP
SQUIDCEXTERN void storeDigestNoteStoreReady(void);
SQUIDCEXTERN void storeDigestScheduleRebuild(void);
SQUIDCEXTERN void storeDigestDel(const StoreEntry * entry);
-SQUIDCEXTERN void storeDigestReport(StoreEntry *);
+extern void storeDigestReport(StoreEntry *);
/*
* store_rebuild.c
SQUIDCEXTERN const char *getMyHostname(void);
SQUIDCEXTERN const char *uniqueHostname(void);
SQUIDCEXTERN void safeunlink(const char *path, int quiet);
+
+#include "fatal.h"
void death(int sig);
-SQUIDCEXTERN void fatal(const char *message);
-SQUIDCEXTERN void fatalf(const char *fmt,...) PRINTF_FORMAT_ARG1;
-SQUIDCEXTERN void fatal_dump(const char *message);
void sigusr2_handle(int sig);
void sig_child(int sig);
SQUIDCEXTERN void leave_suid(void);
SQUIDCEXTERN void setSocketShutdownLifetimes(int);
SQUIDCEXTERN void setMaxFD(void);
SQUIDCEXTERN void setSystemLimits(void);
-SQUIDCEXTERN void squid_signal(int sig, SIGHDLR *, int flags);
+extern void squid_signal(int sig, SIGHDLR *, int flags);
SQUIDCEXTERN pid_t readPidFile(void);
SQUIDCEXTERN void keepCapabilities(void);
SQUIDCEXTERN void BroadcastSignalIfAny(int& sig);
SQUIDCEXTERN char *urlHostname(const char *url);
SQUIDCEXTERN void urlExtMethodConfigure(void);
-SQUIDCEXTERN void useragentOpenLog(void);
-SQUIDCEXTERN void useragentRotateLog(void);
-SQUIDCEXTERN void logUserAgent(const char *, const char *);
-SQUIDCEXTERN void useragentLogClose(void);
-SQUIDCEXTERN void refererOpenLog(void);
-SQUIDCEXTERN void refererRotateLog(void);
-SQUIDCEXTERN void logReferer(const char *, const char *, const char *);
-SQUIDCEXTERN void refererCloseLog(void);
SQUIDCEXTERN peer_t parseNeighborType(const char *s);
/* tools.c */
/* CygWin & Windows NT Port */
/* win32.c */
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
SQUIDCEXTERN int WIN32_Subsystem_Init(int *, char ***);
SQUIDCEXTERN void WIN32_sendSignal(int);
SQUIDCEXTERN void WIN32_Abort(int);
SQUIDCEXTERN void WIN32_InstallService(void);
SQUIDCEXTERN void WIN32_RemoveService(void);
SQUIDCEXTERN int SquidMain(int, char **);
-#endif /* _SQUID_WIN32_ */
+#endif /* _SQUID_WINDOWS_ */
#ifdef _SQUID_MSWIN_
SQUIDCEXTERN int WIN32_pipe(int[2]);
exit(2);
}
- xmemcpy(ip, &R.sin_addr.s_addr, 4);
+ memcpy(ip, &R.sin_addr.s_addr, 4);
hp = gethostbyaddr(ip, 4, AF_INET);
ipa = R.sin_addr;
printf("==============================================================================\n");
#include "acl/Checklist.h"
#include "HttpRequest.h"
#include "client_side.h"
+#include "client_side_reply.h"
#include "helper.h"
#include "rfc1738.h"
+#if USE_SSL
+#include "ssl/support.h"
+#endif
+
+/// url maximum lengh + extra informations passed to redirector
+#define MAX_REDIRECTOR_REQUEST_STRLEN (MAX_URL + 1024)
typedef struct {
void *data;
ConnStateData * conn = http->getConn();
redirectStateData *r = NULL;
const char *fqdn;
- char buf[8192];
+ char buf[MAX_REDIRECTOR_REQUEST_STRLEN];
+ int sz;
+ http_status status;
char claddr[MAX_IPSTRLEN];
char myaddr[MAX_IPSTRLEN];
assert(http);
if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL)
fqdn = dash_str;
- snprintf(buf, 8192, "%s %s/%s %s %s myip=%s myport=%d\n",
- r->orig_url,
- r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
- fqdn,
- r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
- r->method_s,
- http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
- http->request->my_addr.GetPort());
+ sz = snprintf(buf, MAX_REDIRECTOR_REQUEST_STRLEN, "%s %s/%s %s %s myip=%s myport=%d\n",
+ r->orig_url,
+ r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
+ fqdn,
+ r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
+ r->method_s,
+ http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
+ http->request->my_addr.GetPort());
+
+ if ((sz<=0) || (sz>=MAX_REDIRECTOR_REQUEST_STRLEN)) {
+ if (sz<=0) {
+ status = HTTP_INTERNAL_SERVER_ERROR;
+ debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Can not build request to be passed to redirector. Request ABORTED.");
+ } else {
+ status = HTTP_REQUEST_URI_TOO_LARGE;
+ debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Request passed to redirector exceeds MAX_REDIRECTOR_REQUEST_STRLEN (" << MAX_REDIRECTOR_REQUEST_STRLEN << "). Request ABORTED.");
+ }
+
+ clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data;
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ Ip::Address tmpnoaddr;
+ tmpnoaddr.SetNoAddr();
+ repContext->setReplyToError(ERR_GATEWAY_FAILURE, status,
+ http->request->method, NULL,
+ http->getConn() != NULL ? http->getConn()->peer : tmpnoaddr,
+ http->request,
+ NULL,
+ http->getConn() != NULL && http->getConn()->auth_user_request != NULL ?
+ http->getConn()->auth_user_request : http->request->auth_user_request);
+
+ node = (clientStreamNode *)http->client_stream.tail->data;
+ clientStreamRead(node, http, node->readBuffer);
+ return;
+ }
helperSubmit(redirectors, buf, redirectHandleReply, r);
}
STALE_EXPIRES,
STALE_MAX_RULE,
STALE_LMFACTOR_RULE,
+ STALE_MAX_STALE,
STALE_DEFAULT = 299
};
debugs(22, 3, "Staleness = " << staleness);
+ // stale-if-error requires any failure be passed thru when its period is over.
+ if (request && entry->mem_obj && entry->mem_obj->getReply() && entry->mem_obj->getReply()->cache_control &&
+ EBIT_TEST(entry->mem_obj->getReply()->cache_control->mask, CC_STALE_IF_ERROR) &&
+ entry->mem_obj->getReply()->cache_control->stale_if_error < staleness) {
+
+ debugs(22, 3, "refreshCheck: stale-if-error period expired.");
+ request->flags.fail_on_validation_err = 1;
+ }
+
if (EBIT_TEST(entry->flags, ENTRY_REVALIDATE) && staleness > -1
#if USE_HTTP_VIOLATIONS
&& !R->flags.ignore_must_revalidate
/*
* At this point the response is stale, unless one of
* the override options kicks in.
+ * NOTE: max-stale config blocks the overrides.
*/
+ int max_stale = (R->max_stale >= 0 ? R->max_stale : Config.maxStale);
+ if ( max_stale >= 0 && staleness < max_stale) {
+ debugs(22, 3, "refreshCheck: YES: max-stale limit");
+ if (request)
+ request->flags.fail_on_validation_err = 1;
+ return STALE_MAX_STALE;
+ }
+
if (sf.expires) {
#if USE_HTTP_VIOLATIONS
snprintf(tbuf, 256, "generated %d [%s]\n",
(int) squid_curtime,
- mkhttpdlogtime(&squid_curtime));
+ Time::FormatHttpd(squid_curtime));
strcat(sndbuf, tbuf);
l = strlen(sndbuf);
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#include "config.h"
+#include "base/TextException.h"
+#include "CommCalls.h"
+#include "ipc/Port.h"
+#include "snmp_core.h"
+#include "snmp/Forwarder.h"
+#include "snmp/Request.h"
+#include "snmp/Response.h"
+
+
+CBDATA_NAMESPACED_CLASS_INIT(Snmp, Forwarder);
+
+
+Snmp::Forwarder::Forwarder(const Pdu& aPdu, const Session& aSession, int aFd,
+ const Ip::Address& anAddress):
+ Ipc::Forwarder(new Request(KidIdentifier, 0, aPdu, aSession, aFd, anAddress), 2),
+ fd(aFd)
+{
+ debugs(49, 5, HERE << "FD " << aFd);
+ Must(fd >= 0);
+ closer = asyncCall(49, 5, "Snmp::Forwarder::noteCommClosed",
+ CommCbMemFunT<Forwarder, CommCloseCbParams>(this, &Forwarder::noteCommClosed));
+ comm_add_close_handler(fd, closer);
+}
+
+/// removes our cleanup handler of the client connection socket
+void
+Snmp::Forwarder::cleanup()
+{
+ if (fd >= 0) {
+ if (closer != NULL) {
+ comm_remove_close_handler(fd, closer);
+ closer = NULL;
+ }
+ fd = -1;
+ }
+}
+
+/// called when the client socket gets closed by some external force
+void
+Snmp::Forwarder::noteCommClosed(const CommCloseCbParams& params)
+{
+ debugs(49, 5, HERE);
+ Must(fd == params.fd);
+ fd = -1;
+ mustStop("commClosed");
+}
+
+void
+Snmp::Forwarder::handleTimeout()
+{
+ sendError(SNMP_ERR_RESOURCEUNAVAILABLE);
+ Ipc::Forwarder::handleTimeout();
+}
+
+void
+Snmp::Forwarder::handleException(const std::exception& e)
+{
+ debugs(49, 3, HERE << e.what());
+ if (fd >= 0)
+ sendError(SNMP_ERR_GENERR);
+ Ipc::Forwarder::handleException(e);
+}
+
+/// send error SNMP response
+void
+Snmp::Forwarder::sendError(int error)
+{
+ debugs(49, 3, HERE);
+ Snmp::Request& req = static_cast<Snmp::Request&>(*request);
+ req.pdu.command = SNMP_PDU_RESPONSE;
+ req.pdu.errstat = error;
+ u_char buffer[SNMP_REQUEST_SIZE];
+ int len = sizeof(buffer);
+ snmp_build(&req.session, &req.pdu, buffer, &len);
+ comm_udp_sendto(fd, req.address, buffer, len);
+}
+
+void
+Snmp::SendResponse(unsigned int requestId, const Pdu& pdu)
+{
+ debugs(49, 5, HERE);
+ // snmpAgentResponse() can modify arg
+ Pdu tmp = pdu;
+ Snmp::Response response(requestId);
+ snmp_pdu* response_pdu = NULL;
+ try {
+ response_pdu = snmpAgentResponse(&tmp);
+ Must(response_pdu != NULL);
+ response.pdu = static_cast<Pdu&>(*response_pdu);
+ snmp_free_pdu(response_pdu);
+ } catch (const std::exception& e) {
+ debugs(49, DBG_CRITICAL, HERE << e.what());
+ response.pdu.command = SNMP_PDU_RESPONSE;
+ response.pdu.errstat = SNMP_ERR_GENERR;
+ }
+ Ipc::TypedMsgHdr message;
+ response.pack(message);
+ Ipc::SendMessage(Ipc::coordinatorAddr, message);
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#ifndef SQUID_SNMPX_FORWARDER_H
+#define SQUID_SNMPX_FORWARDER_H
+
+#include "ipc/Forwarder.h"
+#include "snmp/Pdu.h"
+#include "snmp/Session.h"
+
+
+class CommCloseCbParams;
+
+namespace Snmp
+{
+
+/** Forwards a single client SNMP request to Coordinator.
+ * Waits for an ACK from Coordinator
+ * Send the data unit with an error response if forwarding fails.
+ */
+class Forwarder: public Ipc::Forwarder
+{
+public:
+ Forwarder(const Pdu& aPdu, const Session& aSession, int aFd,
+ const Ip::Address& anAddress);
+
+protected:
+ /* Ipc::Forwarder API */
+ virtual void cleanup(); ///< perform cleanup actions
+ virtual void handleTimeout();
+ virtual void handleException(const std::exception& e);
+
+private:
+ void noteCommClosed(const CommCloseCbParams& params);
+ void sendError(int error);
+
+private:
+ int fd; ///< client connection descriptor
+ AsyncCall::Pointer closer; ///< comm_close handler for the connection
+
+ CBDATA_CLASS2(Forwarder);
+};
+
+extern void SendResponse(unsigned int requestId, const Pdu& pdu);
+
+} // namespace Snmp
+
+#endif /* SQUID_SNMPX_FORWARDER_H */
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#include "config.h"
+#include "base/TextException.h"
+#include "CommCalls.h"
+#include "ipc/UdsOp.h"
+#include "snmp_core.h"
+#include "snmp/Inquirer.h"
+#include "snmp/Response.h"
+#include "snmp/Request.h"
+
+
+CBDATA_NAMESPACED_CLASS_INIT(Snmp, Inquirer);
+
+
+Snmp::Inquirer::Inquirer(const Request& aRequest, const Ipc::StrandCoords& coords):
+ Ipc::Inquirer(aRequest.clone(), coords, 2),
+ aggrPdu(aRequest.pdu),
+ fd(ImportFdIntoComm(aRequest.fd, SOCK_DGRAM, IPPROTO_UDP, Ipc::fdnInSnmpSocket))
+{
+ debugs(49, 5, HERE);
+ closer = asyncCall(49, 5, "Snmp::Inquirer::noteCommClosed",
+ CommCbMemFunT<Inquirer, CommCloseCbParams>(this, &Inquirer::noteCommClosed));
+ comm_add_close_handler(fd, closer);
+}
+
+/// closes our copy of the client connection socket
+void
+Snmp::Inquirer::cleanup()
+{
+ if (fd >= 0) {
+ if (closer != NULL) {
+ comm_remove_close_handler(fd, closer);
+ closer = NULL;
+ }
+ comm_close(fd);
+ fd = -1;
+ }
+}
+
+void
+Snmp::Inquirer::start()
+{
+ debugs(49, 5, HERE);
+ Ipc::Inquirer::start();
+ Must(fd >= 0);
+ inquire();
+}
+
+void
+Snmp::Inquirer::handleException(const std::exception& e)
+{
+ aggrPdu.errstat = SNMP_ERR_GENERR;
+ Ipc::Inquirer::handleException(e);
+}
+
+bool
+Snmp::Inquirer::aggregate(Response::Pointer aResponse)
+{
+ Snmp::Response& response = static_cast<Snmp::Response&>(*aResponse);
+ bool error = response.pdu.errstat != SNMP_ERR_NOERROR;
+ if (error) {
+ aggrPdu = response.pdu;
+ } else {
+ aggrPdu.aggregate(response.pdu);
+ }
+ return !error;
+}
+
+/// called when the some external force closed our socket
+void
+Snmp::Inquirer::noteCommClosed(const CommCloseCbParams& params)
+{
+ debugs(49, 5, HERE);
+ Must(fd < 0 || fd == params.fd);
+ fd = -1;
+ mustStop("commClosed");
+}
+
+bool
+Snmp::Inquirer::doneAll() const
+{
+ return !writer && Ipc::Inquirer::doneAll();
+}
+
+void
+Snmp::Inquirer::sendResponse()
+{
+ debugs(49, 5, HERE);
+ aggrPdu.fixAggregate();
+ aggrPdu.command = SNMP_PDU_RESPONSE;
+ u_char buffer[SNMP_REQUEST_SIZE];
+ int len = sizeof(buffer);
+ Snmp::Request& req = static_cast<Snmp::Request&>(*request);
+ snmp_build(&req.session, &aggrPdu, buffer, &len);
+ comm_udp_sendto(fd, req.address, buffer, len);
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#ifndef SQUID_SNMPX_INQUIRER_H
+#define SQUID_SNMPX_INQUIRER_H
+
+#include "ipc/Inquirer.h"
+#include "snmp/forward.h"
+#include "snmp/Pdu.h"
+
+
+class CommCloseCbParams;
+
+namespace Snmp
+{
+
+/// Coordinator's job that sends a PDU request to each strand,
+/// aggregates strand responses and send back the result to client
+class Inquirer: public Ipc::Inquirer
+{
+public:
+ Inquirer(const Request& aRequest, const Ipc::StrandCoords& coords);
+
+protected:
+ /* AsyncJob API */
+ virtual void start();
+ virtual bool doneAll() const;
+
+ /* Ipc::Inquirer API */
+ virtual void cleanup();
+ virtual void handleException(const std::exception& e);
+ virtual void sendResponse();
+ virtual bool aggregate(Ipc::Response::Pointer aResponse);
+
+private:
+ void noteCommClosed(const CommCloseCbParams& params);
+
+private:
+ Pdu aggrPdu; ///< aggregated pdu
+ int fd; ///< client connection descriptor
+
+ AsyncCall::Pointer writer; ///< comm_write callback
+ AsyncCall::Pointer closer; ///< comm_close handler
+
+ CBDATA_CLASS2(Inquirer);
+};
+
+} // namespace Snmp
+
+#endif /* SQUID_SNMPX_INQUIRER_H */
--- /dev/null
+include $(top_srcdir)/src/Common.am
+include $(top_srcdir)/src/TestHeaders.am
+
+
+noinst_LTLIBRARIES = libsnmp.la
+
+libsnmp_la_SOURCES = \
+ Forwarder.cc \
+ Forwarder.h \
+ forward.h \
+ Inquirer.cc \
+ Inquirer.h \
+ Pdu.cc \
+ Pdu.h \
+ Request.cc \
+ Request.h \
+ Response.cc \
+ Response.h \
+ Session.cc \
+ Session.h \
+ Var.cc \
+ Var.h
+
+DEFS += -DDEFAULT_PREFIX=\"$(prefix)\"
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#include "config.h"
+#include "base/TextException.h"
+#include "ipc/TypedMsgHdr.h"
+#include "protos.h"
+#include "snmp_core.h"
+#include "snmp/Pdu.h"
+#include "snmp/Var.h"
+
+
+Snmp::Pdu::Pdu()
+{
+ init();
+}
+
+Snmp::Pdu::Pdu(const Pdu& pdu)
+{
+ init();
+ assign(pdu);
+}
+
+Snmp::Pdu::~Pdu()
+{
+ clear();
+}
+
+Snmp::Pdu&
+Snmp::Pdu::operator = (const Pdu& pdu)
+{
+ clear();
+ assign(pdu);
+ return *this;
+}
+
+void
+Snmp::Pdu::init()
+{
+ xmemset(this, 0, sizeof(*this));
+ errstat = SNMP_DEFAULT_ERRSTAT;
+ errindex = SNMP_DEFAULT_ERRINDEX;
+}
+
+void
+Snmp::Pdu::aggregate(const Pdu& pdu)
+{
+ Must(varCount() == pdu.varCount());
+ aggrCount++;
+ for (variable_list* p_aggr = variables, *p_var = pdu.variables; p_var != NULL;
+ p_aggr = p_aggr->next_variable, p_var = p_var->next_variable) {
+ Must(p_aggr != NULL);
+ Var& aggr = static_cast<Var&>(*p_aggr);
+ Var& var = static_cast<Var&>(*p_var);
+ if (aggr.isNull()) {
+ aggr.setName(var.getName());
+ aggr.copyValue(var);
+ } else {
+ switch (snmpAggrType(aggr.name, aggr.name_length)) {
+ case atSum:
+ case atAverage:
+ // The mean-average division is done later
+ // when the Snmp::Pdu::fixAggregate() called
+ aggr += var;
+ break;
+ case atMax:
+ if (var > aggr)
+ aggr.copyValue(var);
+ break;
+ case atMin:
+ if (var < aggr)
+ aggr.copyValue(var);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void
+Snmp::Pdu::clear()
+{
+ clearSystemOid();
+ clearVars();
+ init();
+}
+
+void
+Snmp::Pdu::assign(const Pdu& pdu)
+{
+ command = pdu.command;
+ address.sin_addr.s_addr = pdu.address.sin_addr.s_addr;
+ reqid = pdu.reqid;
+ errstat = pdu.errstat;
+ errindex = pdu.errindex;
+ non_repeaters = pdu.non_repeaters;
+ max_repetitions = pdu.max_repetitions;
+ agent_addr.sin_addr.s_addr = pdu.agent_addr.sin_addr.s_addr;
+ trap_type = pdu.trap_type;
+ specific_type = pdu.specific_type;
+ time = pdu.time;
+ aggrCount = pdu.aggrCount;
+ setSystemOid(pdu.getSystemOid());
+ setVars(pdu.variables);
+}
+
+void
+Snmp::Pdu::clearVars()
+{
+ variable_list* var = variables;
+ while (var != NULL) {
+ variable_list* tmp = var;
+ var = var->next_variable;
+ snmp_var_free(tmp);
+ }
+ variables = NULL;
+}
+
+void
+Snmp::Pdu::setVars(variable_list* vars)
+{
+ clearVars();
+ for (variable_list** p_var = &variables; vars != NULL;
+ vars = vars->next_variable, p_var = &(*p_var)->next_variable) {
+ *p_var = new Var(static_cast<Var&>(*vars));
+ }
+}
+
+void
+Snmp::Pdu::clearSystemOid()
+{
+ if (enterprise != NULL) {
+ xfree(enterprise);
+ enterprise = NULL;
+ }
+ enterprise_length = 0;
+}
+
+Range<const oid*>
+Snmp::Pdu::getSystemOid() const
+{
+ return Range<const oid*>(enterprise, enterprise + enterprise_length);
+}
+
+void
+Snmp::Pdu::setSystemOid(const Range<const oid*>& systemOid)
+{
+ clearSystemOid();
+ if (systemOid.start != NULL && systemOid.size() != 0) {
+ enterprise_length = systemOid.size();
+ enterprise = static_cast<oid*>(xmalloc(enterprise_length * sizeof(oid)));
+ std::copy(systemOid.start, systemOid.end, enterprise);
+ }
+}
+
+void
+Snmp::Pdu::pack(Ipc::TypedMsgHdr& msg) const
+{
+ msg.putPod(command);
+ msg.putPod(address);
+ msg.putPod(reqid);
+ msg.putPod(errstat);
+ msg.putPod(errindex);
+ msg.putPod(non_repeaters);
+ msg.putPod(max_repetitions);
+ msg.putInt(enterprise_length);
+ if (enterprise_length > 0) {
+ Must(enterprise != NULL);
+ msg.putFixed(enterprise, enterprise_length * sizeof(oid));
+ }
+ msg.putPod(agent_addr);
+ msg.putPod(trap_type);
+ msg.putPod(specific_type);
+ msg.putPod(time);
+ msg.putInt(varCount());
+ for (variable_list* var = variables; var != NULL; var = var->next_variable)
+ static_cast<Var*>(var)->pack(msg);
+}
+
+void
+Snmp::Pdu::unpack(const Ipc::TypedMsgHdr& msg)
+{
+ clear();
+ msg.getPod(command);
+ msg.getPod(address);
+ msg.getPod(reqid);
+ msg.getPod(errstat);
+ msg.getPod(errindex);
+ msg.getPod(non_repeaters);
+ msg.getPod(max_repetitions);
+ enterprise_length = msg.getInt();
+ if (enterprise_length > 0) {
+ enterprise = static_cast<oid*>(xmalloc(enterprise_length * sizeof(oid)));
+ msg.getFixed(enterprise, enterprise_length * sizeof(oid));
+ }
+ msg.getPod(agent_addr);
+ msg.getPod(trap_type);
+ msg.getPod(specific_type);
+ msg.getPod(time);
+ int count = msg.getInt();
+ for (variable_list** p_var = &variables; count > 0;
+ p_var = &(*p_var)->next_variable, --count) {
+ Var* var = new Var();
+ var->unpack(msg);
+ *p_var = var;
+ }
+}
+
+int
+Snmp::Pdu::varCount() const
+{
+ int count = 0;
+ for (variable_list* var = variables; var != NULL; var = var->next_variable)
+ ++count;
+ return count;
+}
+
+void
+Snmp::Pdu::fixAggregate()
+{
+ if (aggrCount < 2)
+ return;
+ for (variable_list* p_aggr = variables; p_aggr != NULL; p_aggr = p_aggr->next_variable) {
+ Var& aggr = static_cast<Var&>(*p_aggr);
+ if (snmpAggrType(aggr.name, aggr.name_length) == atAverage) {
+ aggr /= aggrCount;
+ }
+ }
+ aggrCount = 0;
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#ifndef SQUID_SNMPX_PDU_H
+#define SQUID_SNMPX_PDU_H
+
+#include "config.h"
+#include "ipc/forward.h"
+#include "Range.h"
+#include "snmp.h"
+
+
+namespace Snmp
+{
+
+/// snmp_pdu wrapper introduce the feature
+/// to aggregate variables and to pack/unpack message
+class Pdu: public snmp_pdu
+{
+public:
+ Pdu();
+ Pdu(const Pdu& pdu);
+ Pdu& operator = (const Pdu& pdu);
+ ~Pdu();
+
+ void aggregate(const Pdu& pdu);
+ void fixAggregate();
+ void pack(Ipc::TypedMsgHdr& msg) const; ///< prepare for sendmsg()
+ void unpack(const Ipc::TypedMsgHdr& msg); ///< restore struct from the message
+ int varCount() const; ///< size of variables list
+ void clear(); ///< clear all internal members
+ void setVars(variable_list* vars); ///< perform assignment of variables list
+ void clearVars(); ///< clear variables list
+ Range<const oid*> getSystemOid() const;
+ void setSystemOid(const Range<const oid*>& systemOid);
+ void clearSystemOid();
+
+private:
+ void init(); ///< initialize members
+ void assign(const Pdu& pdu); ///< perform full assignment
+ unsigned int aggrCount; ///< The number of other Pdus merged into
+};
+
+} // namespace Snmp
+
+#endif /* SQUID_SNMPX_PDU_H */
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#include "config.h"
+#include "ipc/Messages.h"
+#include "ipc/TypedMsgHdr.h"
+#include "snmp/Request.h"
+
+
+Snmp::Request::Request(int aRequestorId, unsigned int aRequestId,
+ const Pdu& aPdu, const Session& aSession,
+ int aFd, const Ip::Address& anAddress):
+ Ipc::Request(aRequestorId, aRequestId),
+ pdu(aPdu), session(aSession), fd(aFd), address(anAddress)
+{
+}
+
+Snmp::Request::Request(const Request& request):
+ Ipc::Request(request.requestorId, request.requestId),
+ pdu(request.pdu), session(request.session),
+ fd(request.fd), address(request.address)
+{
+}
+
+Snmp::Request::Request(const Ipc::TypedMsgHdr& msg):
+ Ipc::Request(0, 0)
+{
+ msg.checkType(Ipc::mtSnmpRequest);
+ msg.getPod(requestorId);
+ msg.getPod(requestId);
+ pdu.unpack(msg);
+ session.unpack(msg);
+ msg.getPod(address);
+
+ fd = msg.getFd();
+}
+
+void
+Snmp::Request::pack(Ipc::TypedMsgHdr& msg) const
+{
+ msg.setType(Ipc::mtSnmpRequest);
+ msg.putPod(requestorId);
+ msg.putPod(requestId);
+ pdu.pack(msg);
+ session.pack(msg);
+ msg.putPod(address);
+
+ msg.putFd(fd);
+}
+
+Ipc::Request::Pointer
+Snmp::Request::clone() const
+{
+ return new Request(*this);
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#ifndef SQUID_SNMPX_REQUEST_H
+#define SQUID_SNMPX_REQUEST_H
+
+#include "ip/Address.h"
+#include "ipc/forward.h"
+#include "ipc/Request.h"
+#include "snmp/Pdu.h"
+#include "snmp/Session.h"
+
+
+namespace Snmp
+{
+
+/// SNMP request
+class Request: public Ipc::Request
+{
+public:
+ Request(int aRequestorId, unsigned int aRequestId, const Pdu& aPdu,
+ const Session& aSession, int aFd, const Ip::Address& anAddress);
+
+ explicit Request(const Ipc::TypedMsgHdr& msg); ///< from recvmsg()
+ /* Ipc::Request API */
+ virtual void pack(Ipc::TypedMsgHdr& msg) const;
+ virtual Pointer clone() const;
+
+private:
+ Request(const Request& request);
+
+public:
+ Pdu pdu; ///< SNMP protocol data unit
+ Session session; ///< SNMP session
+ int fd; ///< client connection descriptor
+ Ip::Address address; ///< client address
+};
+
+
+} // namespace Snmp
+
+#endif /* SQUID_SNMPX_REQUEST_H */
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#include "config.h"
+#include "base/TextException.h"
+#include "ipc/Messages.h"
+#include "ipc/TypedMsgHdr.h"
+#include "snmp/Response.h"
+
+
+std::ostream& Snmp::operator << (std::ostream& os, const Response& response)
+{
+ os << "response: {requestId: " << response.requestId << '}';
+ return os;
+}
+
+Snmp::Response::Response(unsigned int aRequestId):
+ Ipc::Response(aRequestId), pdu()
+{
+}
+
+Snmp::Response::Response(const Response& response):
+ Ipc::Response(response.requestId), pdu(response.pdu)
+{
+}
+
+Snmp::Response::Response(const Ipc::TypedMsgHdr& msg):
+ Ipc::Response(0)
+{
+ msg.checkType(Ipc::mtSnmpResponse);
+ msg.getPod(requestId);
+ pdu.unpack(msg);
+}
+
+void
+Snmp::Response::pack(Ipc::TypedMsgHdr& msg) const
+{
+ msg.setType(Ipc::mtSnmpResponse);
+ msg.putPod(requestId);
+ pdu.pack(msg);
+}
+
+Ipc::Response::Pointer
+Snmp::Response::clone() const
+{
+ return new Response(*this);
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#ifndef SQUID_SNMPX_RESPONSE_H
+#define SQUID_SNMPX_RESPONSE_H
+
+#include "ipc/forward.h"
+#include "ipc/Response.h"
+#include "snmp/Pdu.h"
+#include <ostream>
+
+namespace Snmp
+{
+
+///
+class Response: public Ipc::Response
+{
+public:
+ Response(unsigned int aRequestId);
+ explicit Response(const Ipc::TypedMsgHdr& msg); ///< from recvmsg()
+ /* Ipc::Response API */
+ virtual void pack(Ipc::TypedMsgHdr& msg) const;
+ virtual Ipc::Response::Pointer clone() const;
+
+private:
+ Response(const Response& response);
+
+public:
+ Pdu pdu; ///< SNMP protocol data unit
+};
+
+extern std::ostream& operator << (std::ostream& os, const Response& response);
+
+} // namespace Snmp
+
+#endif /* SQUID_SNMPX_RESPONSE_H */
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#include "config.h"
+#include "base/TextException.h"
+#include "ipc/TypedMsgHdr.h"
+#include "protos.h"
+#include "snmp/Session.h"
+
+
+Snmp::Session::Session()
+{
+ clear();
+}
+
+Snmp::Session::Session(const Session& session)
+{
+ assign(session);
+}
+
+Snmp::Session::~Session()
+{
+ free();
+}
+
+Snmp::Session&
+Snmp::Session::operator = (const Session& session)
+{
+ free();
+ assign(session);
+ return *this;
+}
+
+void
+Snmp::Session::clear()
+{
+ xmemset(this, 0, sizeof(*this));
+}
+
+void
+Snmp::Session::free()
+{
+ if (community_len > 0) {
+ Must(community != NULL);
+ xfree(community);
+ }
+ if (peername != NULL)
+ xfree(peername);
+ clear();
+}
+
+void
+Snmp::Session::assign(const Session& session)
+{
+ memcpy(this, &session, sizeof(*this));
+ if (session.community != NULL) {
+ community = (u_char*)xstrdup((char*)session.community);
+ Must(community != NULL);
+ }
+ if (session.peername != NULL) {
+ peername = xstrdup(session.peername);
+ Must(peername != NULL);
+ }
+}
+
+void
+Snmp::Session::pack(Ipc::TypedMsgHdr& msg) const
+{
+ msg.putPod(Version);
+ msg.putInt(community_len);
+ if (community_len > 0) {
+ Must(community != NULL);
+ msg.putFixed(community, community_len);
+ }
+ msg.putPod(retries);
+ msg.putPod(timeout);
+ int len = peername != NULL ? strlen(peername) : 0;
+ msg.putInt(len);
+ if (len > 0)
+ msg.putFixed(peername, len);
+ msg.putPod(remote_port);
+ msg.putPod(local_port);
+}
+
+void
+Snmp::Session::unpack(const Ipc::TypedMsgHdr& msg)
+{
+ free();
+ msg.getPod(Version);
+ community_len = msg.getInt();
+ if (community_len > 0) {
+ community = static_cast<u_char*>(xmalloc(community_len + 1));
+ Must(community != NULL);
+ msg.getFixed(community, community_len);
+ community[community_len] = 0;
+ }
+ msg.getPod(retries);
+ msg.getPod(timeout);
+ int len = msg.getInt();
+ if (len > 0) {
+ peername = static_cast<char*>(xmalloc(len + 1));
+ Must(peername != NULL);
+ msg.getFixed(peername, len);
+ peername[len] = 0;
+ }
+ msg.getPod(remote_port);
+ msg.getPod(local_port);
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#ifndef SQUID_SNMPX_SESSION_H
+#define SQUID_SNMPX_SESSION_H
+
+#include "config.h"
+#include "ipc/forward.h"
+#include "snmp.h"
+#include "snmp_session.h"
+
+
+namespace Snmp
+{
+
+/// snmp_session wrapper add pack/unpack feature
+class Session: public snmp_session
+{
+public:
+ Session();
+ Session(const Session& session);
+ Session& operator = (const Session& session);
+ ~Session();
+
+ void pack(Ipc::TypedMsgHdr& msg) const; ///< prepare for sendmsg()
+ void unpack(const Ipc::TypedMsgHdr& msg); ///< restore struct from the message
+ void clear(); ///< clear internal members
+
+private:
+ void free(); ///< free internal members
+ void assign(const Session& session); ///< perform full assignment
+};
+
+} // namespace Snmp
+
+#endif /* SQUID_SNMPX_SESSION_H */
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#include "config.h"
+#include "base/TextException.h"
+#include "ipc/TypedMsgHdr.h"
+#include "protos.h"
+#include "snmp/Var.h"
+
+
+Snmp::Var::Var()
+{
+ init();
+}
+
+Snmp::Var::Var(const Var& var)
+{
+ init();
+ assign(var);
+}
+
+Snmp::Var::~Var()
+{
+ clear();
+}
+
+Snmp::Var&
+Snmp::Var::operator = (const Var& var)
+{
+ clear();
+ assign(var);
+ return *this;
+}
+
+void
+Snmp::Var::init()
+{
+ xmemset(this, 0, sizeof(*this));
+}
+
+Snmp::Var&
+Snmp::Var::operator += (const Var& var)
+{
+ switch (type) {
+ case SMI_INTEGER:
+ setInt(asInt() + var.asInt());
+ break;
+ case SMI_GAUGE32:
+ setGauge(asGauge() + var.asGauge());
+ break;
+ case SMI_COUNTER32:
+ setCounter(asCounter() + var.asCounter());
+ break;
+ case SMI_COUNTER64:
+ setCounter64(asCounter64() + var.asCounter64());
+ break;
+ case SMI_TIMETICKS:
+ setTimeTicks(asTimeTicks() + var.asTimeTicks());
+ break;
+ default:
+ debugs(49, DBG_CRITICAL, HERE << "Unsupported type: " << type);
+ throw TexcHere("Unsupported type");
+ break;
+ }
+ return *this;
+}
+
+Snmp::Var&
+Snmp::Var::operator /= (int num)
+{
+ Must(num != 0);
+ switch (type) {
+ case SMI_INTEGER:
+ setInt(asInt() / num);
+ break;
+ case SMI_GAUGE32:
+ setGauge(asGauge() / num);
+ break;
+ case SMI_COUNTER32:
+ setCounter(asCounter() / num);
+ break;
+ case SMI_COUNTER64:
+ setCounter64(asCounter64() / num);
+ break;
+ case SMI_TIMETICKS:
+ setTimeTicks(asTimeTicks() / num);
+ break;
+ default:
+ debugs(49, DBG_CRITICAL, HERE << "Unsupported type: " << type);
+ throw TexcHere("Unsupported type");
+ break;
+ }
+ return *this;
+}
+
+bool
+Snmp::Var::operator < (const Var& var) const
+{
+ switch (type) {
+ case SMI_INTEGER:
+ return asInt() < var.asInt();
+ case SMI_GAUGE32:
+ return asGauge() < var.asGauge();
+ case SMI_COUNTER32:
+ return asCounter() < var.asCounter();
+ case SMI_COUNTER64:
+ return asCounter64() < var.asCounter64();
+ case SMI_TIMETICKS:
+ return asTimeTicks() < var.asTimeTicks();
+ default:
+ debugs(49, DBG_CRITICAL, HERE << "Unsupported type: " << type);
+ throw TexcHere("Unsupported type");
+ break;
+ }
+ return false; // unreachable
+}
+
+bool
+Snmp::Var::operator > (const Var& var) const
+{
+ switch (type) {
+ case SMI_INTEGER:
+ return asInt() > var.asInt();
+ case SMI_GAUGE32:
+ return asGauge() > var.asGauge();
+ case SMI_COUNTER32:
+ return asCounter() > var.asCounter();
+ case SMI_COUNTER64:
+ return asCounter64() > var.asCounter64();
+ case SMI_TIMETICKS:
+ return asTimeTicks() > var.asTimeTicks();
+ default:
+ debugs(49, DBG_CRITICAL, HERE << "Unsupported type: " << type);
+ throw TexcHere("Unsupported type");
+ break;
+ }
+ return false; // unreachable
+}
+
+void
+Snmp::Var::assign(const Var& var)
+{
+ setName(var.getName());
+ copyValue(var);
+}
+
+void
+Snmp::Var::clearName()
+{
+ if (name != NULL) {
+ xfree(name);
+ name = NULL;
+ }
+ name_length = 0;
+}
+
+Range<const oid*>
+Snmp::Var::getName() const
+{
+ return Range<const oid*>(name, name + name_length);
+}
+
+void
+Snmp::Var::setName(const Range<const oid*>& aName)
+{
+ clearName();
+ if (aName.start != NULL && aName.size() != 0) {
+ name_length = aName.size();
+ name = static_cast<oid*>(xmalloc(name_length * sizeof(oid)));
+ std::copy(aName.start, aName.end, name);
+ }
+}
+
+void
+Snmp::Var::clearValue()
+{
+ if (val.string != NULL) {
+ xfree(val.string);
+ val.string = NULL;
+ }
+ val_len = 0;
+ type = 0;
+}
+
+bool
+Snmp::Var::isNull() const
+{
+ return type == SMI_NULLOBJ;
+}
+
+int
+Snmp::Var::asInt() const
+{
+ Must(type == SMI_INTEGER);
+ Must(val.integer != NULL && val_len == sizeof(int));
+ return *val.integer;
+}
+
+unsigned int
+Snmp::Var::asGauge() const
+{
+ Must(type == SMI_GAUGE32);
+ Must(val.integer != NULL && val_len == 4);
+ return *reinterpret_cast<unsigned int*>(val.integer);
+}
+
+int
+Snmp::Var::asCounter() const
+{
+ Must(type == SMI_COUNTER32);
+ Must(val.integer != NULL && val_len == 4);
+ return *reinterpret_cast<int*>(val.integer);
+}
+
+long long int
+Snmp::Var::asCounter64() const
+{
+ Must(type == SMI_COUNTER64);
+ Must(val.integer != NULL && val_len == 8);
+ return *reinterpret_cast<long long int*>(val.integer);
+}
+
+unsigned int
+Snmp::Var::asTimeTicks() const
+{
+ Must(type == SMI_TIMETICKS);
+ Must(val.integer != NULL && val_len == sizeof(unsigned int));
+ return *reinterpret_cast<unsigned int*>(val.integer);
+}
+
+Range<const oid*>
+Snmp::Var::asObject() const
+{
+ Must(type == SMI_OBJID);
+ Must(val_len % sizeof(oid) == 0);
+ int length = val_len / sizeof(oid);
+ Must(val.objid != NULL && length > 0);
+ return Range<const oid*>(val.objid, val.objid + length);
+}
+
+Range<const u_char*>
+Snmp::Var::asString() const
+{
+ Must(type == SMI_STRING);
+ Must(val.string != NULL && val_len > 0);
+ return Range<const u_char*>(val.string, val.string + val_len);
+}
+
+void
+Snmp::Var::setInt(int value)
+{
+ setValue(&value, sizeof(value), SMI_INTEGER);
+}
+
+void
+Snmp::Var::setCounter(int value)
+{
+ setValue(&value, sizeof(value), SMI_COUNTER32);
+}
+
+void
+Snmp::Var::setGauge(unsigned int value)
+{
+ setValue(&value, sizeof(value), SMI_GAUGE32);
+}
+
+void
+Snmp::Var::setString(const Range<const u_char*>& string)
+{
+ setValue(string.start, string.size(), SMI_STRING);
+}
+
+void
+Snmp::Var::setObject(const Range<const oid*>& object)
+{
+ setValue(object.start, object.size() * sizeof(oid), SMI_OBJID);
+}
+
+void
+Snmp::Var::setCounter64(long long int counter)
+{
+ setValue(&counter, sizeof(counter), SMI_COUNTER64);
+}
+
+void
+Snmp::Var::setTimeTicks(unsigned int ticks)
+{
+ setValue(&ticks, sizeof(ticks), SMI_TIMETICKS);
+}
+
+void
+Snmp::Var::copyValue(const Var& var)
+{
+ setValue(var.val.string, var.val_len, var.type);
+}
+
+void
+Snmp::Var::setValue(const void* value, int length, int aType)
+{
+ clearValue();
+ if (value != NULL) {
+ Must(length > 0 && aType > 0);
+ val.string = static_cast<u_char*>(xmalloc(length));
+ memcpy(val.string, value, length);
+ }
+ val_len = length;
+ type = aType;
+}
+
+void
+Snmp::Var::clear()
+{
+ clearName();
+ clearValue();
+ init();
+}
+
+void
+Snmp::Var::pack(Ipc::TypedMsgHdr& msg) const
+{
+ msg.putInt(name_length);
+ if (name_length > 0) {
+ Must(name != NULL);
+ msg.putFixed(name, name_length * sizeof(oid));
+ }
+ msg.putPod(type);
+ msg.putPod(val_len);
+ if (val_len > 0) {
+ Must(val.string != NULL);
+ msg.putFixed(val.string, val_len);
+ }
+}
+
+void
+Snmp::Var::unpack(const Ipc::TypedMsgHdr& msg)
+{
+ clearName();
+ clearValue();
+ name_length = msg.getInt();
+ Must(name_length >= 0);
+ if (name_length > 0) {
+ name = static_cast<oid*>(xmalloc(name_length * sizeof(oid)));
+ msg.getFixed(name, name_length * sizeof(oid));
+ }
+ msg.getPod(type);
+ val_len = msg.getInt();
+ Must(val_len >= 0);
+ if (val_len > 0) {
+ val.string = static_cast<u_char*>(xmalloc(val_len));
+ msg.getFixed(val.string, val_len);
+ }
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#ifndef SQUID_SNMPX_VAR_H
+#define SQUID_SNMPX_VAR_H
+
+#include "config.h"
+#include "ipc/forward.h"
+#include "Range.h"
+#include "snmp_vars.h"
+
+
+namespace Snmp
+{
+
+/// variable_list wrapper implement the feature to change
+/// the name/value of variable and to pack/unpack message
+class Var: public variable_list
+{
+public:
+ Var();
+ Var(const Var& var);
+ Var& operator = (const Var& var);
+ ~Var();
+
+ Var& operator += (const Var& var);
+ Var& operator /= (int num);
+ bool operator < (const Var& var) const;
+ bool operator > (const Var& var) const;
+
+ void pack(Ipc::TypedMsgHdr& msg) const; ///< prepare for sendmsg()
+ void unpack(const Ipc::TypedMsgHdr& msg); ///< restore struct from the message
+
+ Range<const oid*> getName() const; ///< returns variable name
+ void setName(const Range<const oid*>& aName); ///< set new variable name
+ void clearName(); ///< clear variable name
+
+ bool isNull() const;
+
+ int asInt() const; ///< returns variable value as integer
+ unsigned int asGauge() const; ///< returns variable value as unsigned int
+ int asCounter() const; ///< returns variable value as Counter32
+ long long int asCounter64() const; ///< returns variable value as Counter64
+ unsigned int asTimeTicks() const; ///< returns variable value as time ticks
+ Range<const oid*> asObject() const; ///< returns variable value as object oid
+ Range<const u_char*> asString() const; ///< returns variable value as chars string
+
+ void setInt(int value); ///< assign int value to variable
+ void setCounter(int value); ///< assign Counter32 value to variable
+ void setGauge(unsigned int value); ///< assign unsigned int value to variable
+ void setString(const Range<const u_char*>& string); ///< assign string to variable
+ void setObject(const Range<const oid*>& object); ///< assign object oid to variable
+ void setTimeTicks(unsigned int ticks); ///<assign unsigned int (time) value to variable
+ void setCounter64(long long int counter); ///< assign Counter64 value to variable
+
+ void copyValue(const Var& var); ///< copy variable from another one
+ void clearValue(); ///< clear .val member
+ void clear(); ///< clear all internal members
+
+private:
+ void init(); ///< initialize members
+ void assign(const Var& var); ///< perform full assignment
+ void setValue(const void* value, int length, int aType); ///< set new variable value
+};
+
+} // namespace Snmp
+
+#endif /* SQUID_SNMPX_VAR_H */
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#ifndef SQUID_SNMPX_FORWARD_H
+#define SQUID_SNMPX_FORWARD_H
+
+#include "config.h"
+
+namespace Snmp
+{
+
+class Pdu;
+class Request;
+class Response;
+class Session;
+class Var;
+
+} // namespace Snmp
+
+#endif /* SQUID_SNMPX_FORWARD_H */
*/
#include "squid.h"
#include "acl/FilledChecklist.h"
-#include "cache_snmp.h"
+#include "base/CbcPointer.h"
#include "comm.h"
+#include "comm/Loops.h"
#include "ipc/StartListening.h"
#include "ip/Address.h"
#include "ip/tools.h"
+#include "snmp_core.h"
+#include "snmp/Forwarder.h"
-#define SNMP_REQUEST_SIZE 4096
-#define MAX_PROTOSTAT 5
/// dials snmpConnectionOpened call
class SnmpListeningStartedDialer: public CallDialer,
Ip::Address theOutSNMPAddr;
-typedef struct _mib_tree_entry mib_tree_entry;
-typedef oid *(instance_Fn) (oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
-
-struct _mib_tree_entry {
- oid *name;
- int len;
- oid_ParseFn *parsefunction;
- instance_Fn *instancefunction;
- int children;
-
- struct _mib_tree_entry **leaves;
-
- struct _mib_tree_entry *parent;
-};
-
mib_tree_entry *mib_tree_head;
mib_tree_entry *mib_tree_last;
static void snmpIncomingConnectionOpened(int fd, int errNo);
static void snmpOutgoingConnectionOpened(int fd, int errNo);
-static mib_tree_entry * snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction);
-static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...);
+static mib_tree_entry * snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType = atNone);
+static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType, int children,...);
static oid *snmpCreateOid(int length,...);
mib_tree_entry * snmpLookupNodeStr(mib_tree_entry *entry, const char *str);
int snmpCreateOidFromStr(const char *str, oid **name, int *nl);
static void snmpDecodePacket(snmp_request_t * rq);
static void snmpConstructReponse(snmp_request_t * rq);
-static struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU);
static oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen);
static oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen);
static mib_tree_entry *snmpTreeEntry(oid entry, snint len, mib_tree_entry * current);
static mib_tree_entry *snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current);
-static void snmpSnmplibDebug(int lvl, char *buf);
+extern "C" void snmpSnmplibDebug(int lvl, char *buf);
/*
* The functions used during startup:
* without having a "search" function. A search function should be written
* to make this and the other code much less evil.
*/
- mib_tree_head = snmpAddNode(snmpCreateOid(1, 1), 1, NULL, NULL, 0);
+ mib_tree_head = snmpAddNode(snmpCreateOid(1, 1), 1, NULL, NULL, atNone, 0);
assert(mib_tree_head);
debugs(49, 5, "snmpInit: root is " << mib_tree_head);
/* SQ_SYS - 1.3.6.1.4.1.3495.1.1 */
snmpAddNodeStr("1.3.6.1.4.1.3495.1", 1, NULL, NULL);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.1", SYSVMSIZ, snmp_sysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.1", SYSSTOR, snmp_sysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.1", SYS_UPTIME, snmp_sysFn, static_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.1", SYSVMSIZ, snmp_sysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.1", SYSSTOR, snmp_sysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.1", SYS_UPTIME, snmp_sysFn, static_Inst, atMax);
/* SQ_CONF - 1.3.6.1.4.1.3495.1.2 */
snmpAddNodeStr("1.3.6.1.4.1.3495.1", 2, NULL, NULL);
/* SQ_CONF + CONF_STORAGE - 1.3.6.1.4.1.3495.1.5 */
snmpAddNodeStr("1.3.6.1.4.1.3495.1.2", CONF_STORAGE, NULL, NULL);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_MMAXSZ, snmp_confFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_SWMAXSZ, snmp_confFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_SWHIWM, snmp_confFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_SWLOWM, snmp_confFn, static_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_MMAXSZ, snmp_confFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_SWMAXSZ, snmp_confFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_SWHIWM, snmp_confFn, static_Inst, atMin);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_SWLOWM, snmp_confFn, static_Inst, atMin);
snmpAddNodeStr("1.3.6.1.4.1.3495.1.2", CONF_UNIQNAME, snmp_confFn, static_Inst);
/* PERF_SYS - 1.3.6.1.4.1.3495.1.3.1 */
snmpAddNodeStr("1.3.6.1.4.1.3495.1.3", PERF_SYS, NULL, NULL);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_PF, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_NUMR, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_MEMUSAGE, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CPUTIME, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CPUUSAGE, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_MAXRESSZ, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_NUMOBJCNT, snmp_prfSysFn, static_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_PF, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_NUMR, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_MEMUSAGE, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CPUTIME, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CPUUSAGE, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_MAXRESSZ, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_NUMOBJCNT, snmp_prfSysFn, static_Inst, atSum);
+ /*
+ Amos comments:
+ The meaning of LRU is "oldest timestamped object in cache, if LRU algorithm is
+ used"...
+ What this SMP support needs to do is aggregate via a special filter equivalent to
+ min() to retain the semantic oldest-object meaning. A special one is needed that
+ works as unsigned and ignores '0' values.
+ */
snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURLRUEXP, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURUNLREQ, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURUNUSED_FD, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURRESERVED_FD, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURUSED_FD, snmp_prfSysFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURMAX_FD, snmp_prfSysFn, static_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURUNLREQ, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURUNUSED_FD, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURRESERVED_FD, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURUSED_FD, snmp_prfSysFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURMAX_FD, snmp_prfSysFn, static_Inst, atMax);
/* PERF_PROTO - 1.3.6.1.4.1.3495.1.3.2 */
snmpAddNodeStr("1.3.6.1.4.1.3495.1.3", PERF_PROTO, NULL, NULL);
snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2", PERF_PROTOSTAT_AGGR, NULL, NULL);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_REQ, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_HITS, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_ERRORS, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ICP_S, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ICP_R, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ICP_SKB, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ICP_RKB, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_REQ, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ERRORS, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_KBYTES_IN, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_KBYTES_OUT, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_CURSWAP, snmp_prfProtoFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_CLIENTS, snmp_prfProtoFn, static_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_REQ, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_HITS, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_ERRORS, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ICP_S, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ICP_R, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ICP_SKB, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ICP_RKB, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_REQ, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_ERRORS, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_KBYTES_IN, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_KBYTES_OUT, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_CURSWAP, snmp_prfProtoFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.1", PERF_PROTOSTAT_AGGR_CLIENTS, snmp_prfProtoFn, static_Inst, atSum);
/* Note this is time-series rather than 'static' */
/* cacheMedianSvcTable */
/* cacheMedianSvcEntry */
snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2", 1, NULL, NULL);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_TIME, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_ALL, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_MISS, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_NM, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_HIT, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_ICP_QUERY, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_ICP_REPLY, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_DNS, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_RHR, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_BHR, snmp_prfProtoFn, time_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_NH, snmp_prfProtoFn, time_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_TIME, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_ALL, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_MISS, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_NM, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_HIT, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_ICP_QUERY, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_ICP_REPLY, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_DNS, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_RHR, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_BHR, snmp_prfProtoFn, time_Inst, atAverage);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_NH, snmp_prfProtoFn, time_Inst, atAverage);
/* SQ_NET - 1.3.6.1.4.1.3495.1.4 */
snmpAddNodeStr("1.3.6.1.4.1.3495.1", 4, NULL, NULL);
snmpAddNodeStr("1.3.6.1.4.1.3495.1.4", NET_IP_CACHE, NULL, NULL);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_ENT, snmp_netIpFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_REQ, snmp_netIpFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_HITS, snmp_netIpFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_PENDHIT, snmp_netIpFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_NEGHIT, snmp_netIpFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_MISS, snmp_netIpFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_GHBN, snmp_netIpFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_LOC, snmp_netIpFn, static_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_ENT, snmp_netIpFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_REQ, snmp_netIpFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_HITS, snmp_netIpFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_PENDHIT, snmp_netIpFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_NEGHIT, snmp_netIpFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_MISS, snmp_netIpFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_GHBN, snmp_netIpFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_LOC, snmp_netIpFn, static_Inst, atSum);
snmpAddNodeStr("1.3.6.1.4.1.3495.1.4", NET_FQDN_CACHE, NULL, NULL);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_ENT, snmp_netFqdnFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_REQ, snmp_netFqdnFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_HITS, snmp_netFqdnFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_PENDHIT, snmp_netFqdnFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_NEGHIT, snmp_netFqdnFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_MISS, snmp_netFqdnFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_GHBN, snmp_netFqdnFn, static_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_ENT, snmp_netFqdnFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_REQ, snmp_netFqdnFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_HITS, snmp_netFqdnFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_PENDHIT, snmp_netFqdnFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_NEGHIT, snmp_netFqdnFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_MISS, snmp_netFqdnFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_GHBN, snmp_netFqdnFn, static_Inst, atSum);
snmpAddNodeStr("1.3.6.1.4.1.3495.1.4", NET_DNS_CACHE, NULL, NULL);
#if USE_DNSSERVERS
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REQ, snmp_netDnsFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REP, snmp_netDnsFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_SERVERS, snmp_netDnsFn, static_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REQ, snmp_netDnsFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REP, snmp_netDnsFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_SERVERS, snmp_netDnsFn, static_Inst, atSum);
#else
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REQ, snmp_netIdnsFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REP, snmp_netIdnsFn, static_Inst);
- snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_SERVERS, snmp_netIdnsFn, static_Inst);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REQ, snmp_netIdnsFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REP, snmp_netIdnsFn, static_Inst, atSum);
+ snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_SERVERS, snmp_netIdnsFn, static_Inst, atSum);
#endif
/* SQ_MESH - 1.3.6.1.4.1.3495.1.5 */
if (theInSnmpConnection < 0)
fatal("Cannot open Incoming SNMP Port");
- commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL,
- 0);
+ Comm::SetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
debugs(1, 1, "Accepting SNMP messages on " << Config.Addrs.snmp_incoming <<
", FD " << theInSnmpConnection << ".");
if (theOutSnmpConnection < 0)
fatal("Cannot open Outgoing SNMP Port");
- commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL,
- 0);
+ Comm::SetSelect(theOutSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
debugs(1, 1, "Outgoing SNMP messages on " << Config.Addrs.snmp_outgoing <<
", FD " << theOutSnmpConnection << ".");
*/
assert(theOutSnmpConnection > -1);
- commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);
}
void
debugs(49, 5, "snmpHandleUdp: Called.");
- commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
+ Comm::SetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
memset(buf, '\0', SNMP_REQUEST_SIZE);
struct snmp_pdu *RespPDU;
debugs(49, 5, "snmpConstructReponse: Called.");
+
+ if (UsingSmp() && IamWorkerProcess()) {
+ AsyncJob::Start(new Snmp::Forwarder(static_cast<Snmp::Pdu&>(*rq->PDU),
+ static_cast<Snmp::Session&>(rq->session), rq->sock, rq->from));
+ snmp_free_pdu(rq->PDU);
+ return;
+ }
+
RespPDU = snmpAgentResponse(rq->PDU);
snmp_free_pdu(rq->PDU);
* return the response to the requester.
*/
-static struct snmp_pdu *
+struct snmp_pdu *
snmpAgentResponse(struct snmp_pdu *PDU) {
struct snmp_pdu *Answer = NULL;
return (Fn);
}
+AggrType
+snmpAggrType(oid* Current, snint CurrentLen)
+{
+ debugs(49, 5, HERE);
+
+ mib_tree_entry* mibTreeEntry = mib_tree_head;
+ AggrType type = atNone;
+ int count = 0;
+
+ if (Current[count] == mibTreeEntry->name[count]) {
+ count++;
+
+ while (mibTreeEntry != NULL && count < CurrentLen) {
+ mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
+ if (mibTreeEntry != NULL)
+ type = mibTreeEntry->aggrType;
+ count++;
+ }
+ }
+
+ return type;
+}
+
static oid_ParseFn *
snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
{
oid *instance = NULL;
if (*len <= current->len) {
instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
- xmemcpy(instance, name, (sizeof(name) * *len));
+ memcpy(instance, name, (sizeof(name) * *len));
instance[*len] = 0;
*len += 1;
}
if (*len <= current->len) {
instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
- xmemcpy(instance, name, (sizeof(name) * *len));
+ memcpy(instance, name, (sizeof(name) * *len));
instance[*len] = *index;
*len += 1;
} else {
if (loop < (TIME_INDEX_LEN - 1)) {
instance = (oid *)xmalloc(sizeof(name) * (*len));
- xmemcpy(instance, name, (sizeof(name) * *len));
+ memcpy(instance, name, (sizeof(name) * *len));
instance[*len - 1] = index[++loop];
}
}
} else if (*len <= current->len) {
debugs(49, 6, "snmp peer_Inst: *len <= current->len ???");
instance = (oid *)xmalloc(sizeof(name) * ( *len + 1));
- xmemcpy(instance, name, (sizeof(name) * *len));
+ memcpy(instance, name, (sizeof(name) * *len));
instance[*len] = 1 ;
*len += 1;
} else {
if (peers) {
debugs(49, 6, "snmp peer_Inst: Encode peer #" << i);
instance = (oid *)xmalloc(sizeof(name) * (current->len + 1 ));
- xmemcpy(instance, name, (sizeof(name) * current->len ));
+ memcpy(instance, name, (sizeof(name) * current->len ));
instance[current->len] = no + 1 ; // i.e. the next index on cache_peeer table.
} else {
debugs(49, 6, "snmp peer_Inst: We have " << i << " peers. Can't find #" << no);
debugs(49, 6, HERE << "len" << *len << ", current-len" << current->len << ", addr=" << laddr << ", size=" << size);
instance = (oid *)xmalloc(sizeof(name) * (*len + size ));
- xmemcpy(instance, name, (sizeof(name) * (*len)));
+ memcpy(instance, name, (sizeof(name) * (*len)));
if ( !laddr.IsAnyAddr() ) {
addr2oid(laddr, &instance[ *len]); // the addr
debugs(49, 6, HERE << "len" << *len << ", current-len" << current->len << ", addr=" << laddr << ", newshift=" << newshift);
instance = (oid *)xmalloc(sizeof(name) * (current->len + newshift));
- xmemcpy(instance, name, (sizeof(name) * (current->len)));
+ memcpy(instance, name, (sizeof(name) * (current->len)));
addr2oid(laddr, &instance[current->len]); // the addr.
*len = current->len + newshift ;
}
* on failure.
*/
static mib_tree_entry *
-snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction)
+snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType)
{
mib_tree_entry *m, *b;
oid *n;
return NULL;
/* Create a node */
- m = snmpAddNode(n, nl, parsefunction, instancefunction, 0);
+ m = snmpAddNode(n, nl, parsefunction, instancefunction, aggrType, 0);
/* Link it into the existing tree */
snmpAddNodeChild(b, m);
* Adds a node to the MIB tree structure and adds the appropriate children
*/
static mib_tree_entry *
-snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...)
+snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType, int children,...)
{
va_list args;
int loop;
entry->instancefunction = instancefunction;
entry->children = children;
entry->leaves = NULL;
+ entry->aggrType = aggrType;
if (children > 0) {
entry->leaves = (mib_tree_entry **)xmalloc(sizeof(mib_tree_entry *) * children);
return outbuf.content();
}
-static void
+void
snmpSnmplibDebug(int lvl, char *buf)
{
debugs(49, lvl, buf);
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 49 SNMP Interface
+ *
+ */
+
+#ifndef SQUID_SNMP_CORE_H
+#define SQUID_SNMP_CORE_H
+
+#include "config.h"
+#include "cache_snmp.h"
+
+#define SNMP_REQUEST_SIZE 4096
+#define MAX_PROTOSTAT 5
+
+
+typedef struct _mib_tree_entry mib_tree_entry;
+typedef oid *(instance_Fn) (oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
+typedef enum {atNone = 0, atSum, atAverage, atMax, atMin} AggrType;
+
+struct _mib_tree_entry {
+ oid *name;
+ int len;
+ oid_ParseFn *parsefunction;
+ instance_Fn *instancefunction;
+ int children;
+
+ struct _mib_tree_entry **leaves;
+
+ struct _mib_tree_entry *parent;
+ AggrType aggrType;
+};
+
+extern struct snmp_pdu* snmpAgentResponse(struct snmp_pdu* PDU);
+extern AggrType snmpAggrType(oid* Current, snint CurrentLen);
+
+#endif /* SQUID_SNMP_CORE_H */
#if HAVE_LIMITS_H
#include <limits.h>
#endif
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#include <io.h>
#endif
#if HAVE_SYS_MOUNT_H
#endif
#include "md5.h"
-#if USE_SSL
-#include "ssl/support.h"
-#endif
#if SQUID_SNMP
#include "cache_snmp.h"
#endif
--- /dev/null
+#include "squid.h"
+#include "ssl/ErrorDetail.h"
+
+struct SslErrorDetailEntry {
+ Ssl::ssl_error_t value;
+ const char *name;
+ const char *detail;
+};
+
+// TODO: optimize by replacing with std::map or similar
+static SslErrorDetailEntry TheSslDetailMap[] = {
+ { SQUID_X509_V_ERR_DOMAIN_MISMATCH,
+ "SQUID_X509_V_ERR_DOMAIN_MISMATCH",
+ "%err_name: The hostname you are connecting to (%H), does not match any of the Certificate valid names: %ssl_cn"},
+ { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
+ "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT",
+ "%err_name: SSL Certficate error: certificate issuer (CA) not known: %ssl_ca_name" },
+ { X509_V_ERR_CERT_NOT_YET_VALID,
+ "X509_V_ERR_CERT_NOT_YET_VALID",
+ "%err_name: SSL Certficate is not valid before: %ssl_notbefore" },
+ { X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD,
+ "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD",
+ "%err_name: SSL Certificate has invalid start date (the 'not before' field): %subject" },
+ { X509_V_ERR_CERT_HAS_EXPIRED,
+ "X509_V_ERR_CERT_HAS_EXPIRED",
+ "%err_name: SSL Certificate expired on %ssl_notafter" },
+ { X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD,
+ "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD",
+ "%err_name: SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" },
+ {X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
+ "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT",
+ "%err_name: Self-signed SSL Certificate: %ssl_subject"},
+ { X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
+ "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
+ "%err_name: SSL Certficate error: certificate issuer (CA) not known: %ssl_ca_name" },
+ { SSL_ERROR_NONE, "SSL_ERROR_NONE", "%err_name: No error" },
+ {SSL_ERROR_NONE, NULL, NULL }
+};
+
+Ssl::ssl_error_t
+Ssl::parseErrorString(const char *name)
+{
+ assert(name);
+
+ for (int i = 0; TheSslDetailMap[i].name; ++i) {
+ if (strcmp(name, TheSslDetailMap[i].name) == 0)
+ return TheSslDetailMap[i].value;
+ }
+
+ if (xisdigit(*name)) {
+ const long int value = strtol(name, NULL, 0);
+ if (SQUID_SSL_ERROR_MIN <= value && value <= SQUID_SSL_ERROR_MAX)
+ return value;
+ fatalf("Too small or too bug SSL error code '%s'", name);
+ }
+
+ fatalf("Unknown SSL error name '%s'", name);
+ return SSL_ERROR_SSL; // not reached
+}
+
+const char *
+Ssl::getErrorName(Ssl::ssl_error_t value)
+{
+
+ for (int i = 0; TheSslDetailMap[i].name; ++i) {
+ if (TheSslDetailMap[i].value == value)
+ return TheSslDetailMap[i].name;
+ }
+
+ return NULL;
+}
+
+static const char *getErrorDetail(Ssl::ssl_error_t value)
+{
+ for (int i = 0; TheSslDetailMap[i].name; ++i) {
+ if (TheSslDetailMap[i].value == value)
+ return TheSslDetailMap[i].detail;
+ }
+
+ return NULL;
+}
+
+Ssl::ErrorDetail::err_frm_code Ssl::ErrorDetail::ErrorFormatingCodes[] = {
+ {"ssl_subject", &Ssl::ErrorDetail::subject},
+ {"ssl_ca_name", &Ssl::ErrorDetail::ca_name},
+ {"ssl_cn", &Ssl::ErrorDetail::cn},
+ {"ssl_notbefore", &Ssl::ErrorDetail::notbefore},
+ {"ssl_notafter", &Ssl::ErrorDetail::notafter},
+ {"err_name", &Ssl::ErrorDetail::err_code},
+ {NULL,NULL}
+};
+
+/**
+ * The subject of the current certification in text form
+ */
+const char *Ssl::ErrorDetail::subject() const
+{
+ if (!peer_cert)
+ return "[Not available]";
+
+ static char tmpBuffer[256]; // A temporary buffer
+ X509_NAME_oneline(X509_get_subject_name(peer_cert.get()), tmpBuffer,
+ sizeof(tmpBuffer));
+ return tmpBuffer;
+}
+
+// helper function to be used with Ssl::matchX509CommonNames
+static int copy_cn(void *check_data, ASN1_STRING *cn_data)
+{
+ String *str = (String *)check_data;
+ if (!str) // no data? abort
+ return 0;
+ if (str->defined())
+ str->append(", ");
+ str->append((const char *)cn_data->data, cn_data->length);
+ return 1;
+}
+
+/**
+ * The list with certificates cn and alternate names
+ */
+const char *Ssl::ErrorDetail::cn() const
+{
+ if (!peer_cert)
+ return "[Not available]";
+
+ static String tmpStr; ///< A temporary string buffer
+ tmpStr.clean();
+ Ssl::matchX509CommonNames(peer_cert.get(), &tmpStr, copy_cn);
+ return tmpStr.termedBuf();
+}
+
+/**
+ * The issuer name
+ */
+const char *Ssl::ErrorDetail::ca_name() const
+{
+ if (!peer_cert)
+ return "[Not available]";
+
+ static char tmpBuffer[256]; // A temporary buffer
+ X509_NAME_oneline(X509_get_issuer_name(peer_cert.get()), tmpBuffer, sizeof(tmpBuffer));
+ return tmpBuffer;
+}
+
+/**
+ * The certificate "not before" field
+ */
+const char *Ssl::ErrorDetail::notbefore() const
+{
+ if (!peer_cert)
+ return "[Not available]";
+
+ static char tmpBuffer[256]; // A temporary buffer
+ ASN1_UTCTIME * tm = X509_get_notBefore(peer_cert.get());
+ Ssl::asn1timeToString(tm, tmpBuffer, sizeof(tmpBuffer));
+ return tmpBuffer;
+}
+
+/**
+ * The certificate "not after" field
+ */
+const char *Ssl::ErrorDetail::notafter() const
+{
+ if (!peer_cert)
+ return "[Not available]";
+
+ static char tmpBuffer[256]; // A temporary buffer
+ ASN1_UTCTIME * tm = X509_get_notAfter(peer_cert.get());
+ Ssl::asn1timeToString(tm, tmpBuffer, sizeof(tmpBuffer));
+ return tmpBuffer;
+}
+
+/**
+ * The string representation of the error_no
+ */
+const char *Ssl::ErrorDetail::err_code() const
+{
+ const char *err = getErrorName(error_no);
+ if (!err)
+ return "[Not available]";
+ return err;
+}
+
+/**
+ * It converts the code to a string value. Currently the following
+ * formating codes are supported:
+ * %err_name: The name of the SSL error
+ * %ssl_cn: The comma-separated list of common and alternate names
+ * %ssl_subject: The certificate subject
+ * %ssl_ca_name: The certificate issuer name
+ * %ssl_notbefore: The certificate "not before" field
+ * %ssl_notafter: The certificate "not after" field
+ \retval the length of the code (the number of characters will be replaced by value)
+*/
+int Ssl::ErrorDetail::convert(const char *code, const char **value) const
+{
+ *value = "-";
+ for (int i=0; ErrorFormatingCodes[i].code!=NULL; i++) {
+ const int len = strlen(ErrorFormatingCodes[i].code);
+ if (strncmp(code,ErrorFormatingCodes[i].code, len)==0) {
+ ErrorDetail::fmt_action_t action = ErrorFormatingCodes[i].fmt_action;
+ *value = (this->*action)();
+ return len;
+ }
+ }
+ return 0;
+}
+
+/**
+ * It uses the convert method to build the string errDetailStr using
+ * a template message for the current SSL error. The template messages
+ * can also contain normal error pages formating codes.
+ * Currently the error template messages are hard-coded
+ */
+void Ssl::ErrorDetail::buildDetail() const
+{
+ char const *s = getErrorDetail(error_no);
+ char const *p;
+ char const *t;
+ int code_len = 0;
+
+ if (!s) //May be add a default detail string?
+ return;
+
+ while ((p = strchr(s, '%'))) {
+ errDetailStr.append(s, p - s);
+ code_len = convert(++p, &t);
+ if (code_len)
+ errDetailStr.append(t);
+ else
+ errDetailStr.append("%");
+ s = p + code_len;
+ }
+ errDetailStr.append(s, strlen(s));
+}
+
+const String &Ssl::ErrorDetail::toString() const
+{
+ if (!errDetailStr.defined())
+ buildDetail();
+ return errDetailStr;
+}
+
+/* We may do not want to use X509_dup but instead
+ internal SSL locking:
+ CRYPTO_add(&(cert->references),1,CRYPTO_LOCK_X509);
+ peer_cert.reset(cert);
+*/
+Ssl::ErrorDetail::ErrorDetail( Ssl::ssl_error_t err_no, X509 *cert): error_no (err_no)
+{
+ peer_cert.reset(X509_dup(cert));
+}
+
+Ssl::ErrorDetail::ErrorDetail(Ssl::ErrorDetail const &anErrDetail)
+{
+ error_no = anErrDetail.error_no;
+ if (anErrDetail.peer_cert.get()) {
+ peer_cert.reset(X509_dup(anErrDetail.peer_cert.get()));
+ }
+}
--- /dev/null
+#ifndef _SQUID_SSL_ERROR_DETAIL_H
+#define _SQUID_SSL_ERROR_DETAIL_H
+
+#include "err_detail_type.h"
+#include "ssl/support.h"
+#include "ssl/gadgets.h"
+
+#if HAVE_OPENSSL_SSL_H
+#include <openssl/ssl.h>
+#endif
+
+// Custom SSL errors; assumes all official errors are positive
+#define SQUID_X509_V_ERR_DOMAIN_MISMATCH -1
+// All SSL errors range: from smallest (negative) custom to largest SSL error
+#define SQUID_SSL_ERROR_MIN SQUID_X509_V_ERR_DOMAIN_MISMATCH
+#define SQUID_SSL_ERROR_MAX INT_MAX
+
+namespace Ssl
+{
+/// Squid defined error code (<0), an error code returned by SSL X509 api, or SSL_ERROR_NONE
+typedef int ssl_error_t;
+
+/**
+ \ingroup ServerProtocolSSLAPI
+ * The ssl_error_t representation of the error described by "name".
+ */
+ssl_error_t parseErrorString(const char *name);
+
+/**
+ \ingroup ServerProtocolSSLAPI
+ * The string representation of the SSL error "value"
+ */
+const char *getErrorName(ssl_error_t value);
+
+/**
+ \ingroup ServerProtocolSSLAPI
+ * Used to pass SSL error details to the error pages returned to the
+ * end user.
+ */
+class ErrorDetail
+{
+public:
+ ErrorDetail(ssl_error_t err_no, X509 *cert);
+ ErrorDetail(ErrorDetail const &);
+ const String &toString() const; ///< An error detail string to embed in squid error pages
+
+private:
+ typedef const char * (ErrorDetail::*fmt_action_t)() const;
+ /**
+ * Holds a formating code and its conversion method
+ */
+ class err_frm_code
+ {
+ public:
+ const char *code; ///< The formating code
+ fmt_action_t fmt_action; ///< A pointer to the conversion method
+ };
+ static err_frm_code ErrorFormatingCodes[]; ///< The supported formating codes
+
+ const char *subject() const;
+ const char *ca_name() const;
+ const char *cn() const;
+ const char *notbefore() const;
+ const char *notafter() const;
+ const char *err_code() const;
+
+ int convert(const char *code, const char **value) const;
+ void buildDetail() const;
+
+ mutable String errDetailStr; ///< Caches the error detail message
+ ssl_error_t error_no; ///< The error code
+ X509_Pointer peer_cert; ///< A pointer to the peer certificate
+};
+
+}//namespace Ssl
+#endif
context_storage.cc \
context_storage.h \
Config.cc \
- Config.h
+ Config.h \
+ ErrorDetail.cc \
+ ErrorDetail.h \
+ support.cc \
+ support.h
libsslutil_la_SOURCES = \
- support.cc \
- support.h \
gadgets.cc \
gadgets.h \
crtd_message.cc \
body += i->first + "=" + i->second;
}
if (!other_part.empty())
- body += other_part;
+ body += '\n' + other_part;
}
const std::string Ssl::CrtdMessage::code_new_certificate("new_certificate");
Ssl::X509_NAME_Pointer name(X509_REQ_get_subject_name(request.get()));
if (!name)
return false;
- if (!X509_NAME_add_entry_by_txt(name.get(), "CN", MBSTRING_ASC, (unsigned char *)cn, -1, -1, 0))
+
+ // The second argument of the X509_NAME_add_entry_by_txt declared as
+ // "char *" on some OS. Use cn_name to avoid compile warnings.
+ static char cn_name[3] = "CN";
+ if (!X509_NAME_add_entry_by_txt(name.get(), cn_name, MBSTRING_ASC, (unsigned char *)cn, -1, -1, 0))
return false;
name.release();
return true;
return true;
}
-void Ssl::BIO_free_wrapper(BIO * bio)
-{
- BIO_free(bio);
-}
-
EVP_PKEY * Ssl::createSslPrivateKey()
{
Ssl::EVP_PKEY_Pointer pkey(EVP_PKEY_new());
because they are used by ssl_crtd.
*/
-/**
- \ingroup SslCrtdSslAPI
- * Function for BIO delete for Deleter template.
-*/
-void BIO_free_wrapper(BIO * bio);
+// Macro to be used to define the C++ equivalent function of an extern "C"
+// function. The C++ function suffixed with the _cpp extension
+#define CtoCpp1(function, argument) \
+ extern "C++" inline void function ## _cpp(argument a) { \
+ function(a); \
+ }
/**
\ingroup SslCrtdSslAPI
* TidyPointer typedefs for common SSL objects
*/
-typedef TidyPointer<X509, X509_free> X509_Pointer;
-typedef TidyPointer<EVP_PKEY, EVP_PKEY_free> EVP_PKEY_Pointer;
-typedef TidyPointer<BIGNUM, BN_free> BIGNUM_Pointer;
-typedef TidyPointer<BIO, BIO_free_wrapper> BIO_Pointer;
-typedef TidyPointer<ASN1_INTEGER, ASN1_INTEGER_free> ASN1_INT_Pointer;
-typedef TidyPointer<TXT_DB, TXT_DB_free> TXT_DB_Pointer;
-typedef TidyPointer<X509_NAME, X509_NAME_free> X509_NAME_Pointer;
-typedef TidyPointer<RSA, RSA_free> RSA_Pointer;
-typedef TidyPointer<X509_REQ, X509_REQ_free> X509_REQ_Pointer;
-typedef TidyPointer<SSL_CTX, SSL_CTX_free> SSL_CTX_Pointer;
-typedef TidyPointer<SSL, SSL_free> SSL_Pointer;
+CtoCpp1(X509_free, X509 *)
+typedef TidyPointer<X509, X509_free_cpp> X509_Pointer;
+
+CtoCpp1(EVP_PKEY_free, EVP_PKEY *)
+typedef TidyPointer<EVP_PKEY, EVP_PKEY_free_cpp> EVP_PKEY_Pointer;
+
+CtoCpp1(BN_free, BIGNUM *)
+typedef TidyPointer<BIGNUM, BN_free_cpp> BIGNUM_Pointer;
+
+CtoCpp1(BIO_free, BIO *)
+typedef TidyPointer<BIO, BIO_free_cpp> BIO_Pointer;
+
+CtoCpp1(ASN1_INTEGER_free, ASN1_INTEGER *)
+typedef TidyPointer<ASN1_INTEGER, ASN1_INTEGER_free_cpp> ASN1_INT_Pointer;
+
+CtoCpp1(TXT_DB_free, TXT_DB *)
+typedef TidyPointer<TXT_DB, TXT_DB_free_cpp> TXT_DB_Pointer;
+
+CtoCpp1(X509_NAME_free, X509_NAME *)
+typedef TidyPointer<X509_NAME, X509_NAME_free_cpp> X509_NAME_Pointer;
+
+CtoCpp1(RSA_free, RSA *)
+typedef TidyPointer<RSA, RSA_free_cpp> RSA_Pointer;
+
+CtoCpp1(X509_REQ_free, X509_REQ *)
+typedef TidyPointer<X509_REQ, X509_REQ_free_cpp> X509_REQ_Pointer;
+
+CtoCpp1(SSL_CTX_free, SSL_CTX *)
+typedef TidyPointer<SSL_CTX, SSL_CTX_free_cpp> SSL_CTX_Pointer;
+
+CtoCpp1(SSL_free, SSL *)
+typedef TidyPointer<SSL, SSL_free_cpp> SSL_Pointer;
/**
#include "fde.h"
#include "acl/FilledChecklist.h"
+#include "ssl/ErrorDetail.h"
+#include "ssl/support.h"
#include "ssl/gadgets.h"
/**
return rsa;
}
+int Ssl::asn1timeToString(ASN1_TIME *tm, char *buf, int len)
+{
+ BIO *bio;
+ int write = 0;
+ bio = BIO_new(BIO_s_mem());
+ if (bio) {
+ if (ASN1_TIME_print(bio, tm))
+ write = BIO_read(bio, buf, len-1);
+ BIO_free(bio);
+ }
+ buf[write]='\0';
+ return write;
+}
+
+int Ssl::matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data))
+{
+ assert(peer_cert);
+
+ X509_NAME *name = X509_get_subject_name(peer_cert);
+
+ for (int i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
+
+ ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
+
+ if ( (*check_func)(check_data, cn_data) == 0)
+ return 1;
+ }
+
+ STACK_OF(GENERAL_NAME) * altnames;
+ altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL);
+
+ if (altnames) {
+ int numalts = sk_GENERAL_NAME_num(altnames);
+ for (int i = 0; i < numalts; i++) {
+ const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
+ if (check->type != GEN_DNS) {
+ continue;
+ }
+ ASN1_STRING *cn_data = check->d.dNSName;
+
+ if ( (*check_func)(check_data, cn_data) == 0)
+ return 1;
+ }
+ sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
+ }
+ return 0;
+}
+
+static int check_domain( void *check_data, ASN1_STRING *cn_data)
+{
+ char cn[1024];
+ const char *server = (const char *)check_data;
+
+ if (cn_data->length > (int)sizeof(cn) - 1) {
+ return 1; //if does not fit our buffer just ignore
+ }
+ memcpy(cn, cn_data->data, cn_data->length);
+ cn[cn_data->length] = '\0';
+ debugs(83, 4, "Verifying server domain " << server << " to certificate name/subjectAltName " << cn);
+ return matchDomainName(server, cn[0] == '*' ? cn + 1 : cn);
+}
+
/// \ingroup ServerProtocolSSLInternal
static int
ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
X509 *peer_cert = ctx->cert;
+ Ssl::ssl_error_t error_no = SSL_ERROR_NONE;
X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer,
sizeof(buffer));
debugs(83, 5, "SSL Certificate signature OK: " << buffer);
if (server) {
- int i;
- int found = 0;
- char cn[1024];
-
- STACK_OF(GENERAL_NAME) * altnames;
- altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL);
- if (altnames) {
- int numalts = sk_GENERAL_NAME_num(altnames);
- debugs(83, 3, "Verifying server domain " << server << " to certificate subjectAltName");
- for (i = 0; i < numalts; i++) {
- const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
- if (check->type != GEN_DNS) {
- continue;
- }
- ASN1_STRING *data = check->d.dNSName;
- if (data->length > (int)sizeof(cn) - 1) {
- continue;
- }
- memcpy(cn, data->data, data->length);
- cn[data->length] = '\0';
- debugs(83, 4, "Verifying server domain " << server << " to certificate name " << cn);
- if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) {
- found = 1;
- break;
- }
- }
- }
-
- X509_NAME *name = X509_get_subject_name(peer_cert);
- debugs(83, 3, "Verifying server domain " << server << " to certificate dn " << buffer);
-
- for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
- ASN1_STRING *data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
-
- if (data->length > (int)sizeof(cn) - 1)
- continue;
-
- memcpy(cn, data->data, data->length);
-
- cn[data->length] = '\0';
-
- debugs(83, 4, "Verifying server domain " << server << " to certificate cn " << cn);
-
- if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) {
- found = 1;
- break;
- }
- }
+ int found = Ssl::matchX509CommonNames(peer_cert, (void *)server, check_domain);
if (!found) {
debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server);
ok = 0;
+ error_no = SQUID_X509_V_ERR_DOMAIN_MISMATCH;
+
if (check)
Filled(check)->ssl_error = SQUID_X509_V_ERR_DOMAIN_MISMATCH;
}
}
} else {
+ error_no = ctx->error;
switch (ctx->error) {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
debugs(83, 5, "SSL Certficate error: CA not known: " << buffer);
break;
debugs(83, 5, "SSL Certificate has invalid \'not after\' field: " << buffer);
break;
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ debugs(83, 5, "SSL Certificate is self signed: " << buffer);
+ break;
+
default:
debugs(83, 1, "SSL unknown certificate error " << ctx->error << " in " << buffer);
break;
if (!dont_verify_domain && server) {}
+ if (error_no != SSL_ERROR_NONE && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) {
+ Ssl::ErrorDetail *errDetail = new Ssl::ErrorDetail(error_no, peer_cert);
+ if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, errDetail)) {
+ debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer);
+ delete errDetail;
+ }
+ }
+
return ok;
}
return fl;
}
-struct SslErrorMapEntry {
- const char *name;
- ssl_error_t value;
-};
-
-static SslErrorMapEntry TheSslErrorMap[] = {
- { "SQUID_X509_V_ERR_DOMAIN_MISMATCH", SQUID_X509_V_ERR_DOMAIN_MISMATCH },
- { "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT", X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT },
- { "X509_V_ERR_CERT_NOT_YET_VALID", X509_V_ERR_CERT_NOT_YET_VALID },
- { "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD", X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD },
- { "X509_V_ERR_CERT_HAS_EXPIRED", X509_V_ERR_CERT_HAS_EXPIRED },
- { "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD", X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD },
- { "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY", X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY },
- { "SSL_ERROR_NONE", SSL_ERROR_NONE },
- { NULL, SSL_ERROR_NONE }
-};
-
-ssl_error_t
-sslParseErrorString(const char *name)
-{
- assert(name);
-
- for (int i = 0; TheSslErrorMap[i].name; ++i) {
- if (strcmp(name, TheSslErrorMap[i].name) == 0)
- return TheSslErrorMap[i].value;
- }
-
- if (xisdigit(*name)) {
- const long int value = strtol(name, NULL, 0);
- if (SQUID_SSL_ERROR_MIN <= value && value <= SQUID_SSL_ERROR_MAX)
- return value;
- fatalf("Too small or too bug SSL error code '%s'", name);
- }
-
- fatalf("Unknown SSL error name '%s'", name);
- return SSL_ERROR_SSL; // not reached
-}
-
-const char *
-sslFindErrorString(ssl_error_t value)
-{
- for (int i = 0; TheSslErrorMap[i].name; ++i) {
- if (TheSslErrorMap[i].value == value)
- return TheSslErrorMap[i].name;
- }
-
- return NULL;
-}
-
// "dup" function for SSL_get_ex_new_index("cert_err_check")
static int
ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *,
delete static_cast<ACLChecklist *>(ptr); // may be NULL
}
+// "free" function for SSL_get_ex_new_index("ssl_error_detail")
+static void
+ssl_free_ErrorDetail(void *, void *ptr, CRYPTO_EX_DATA *,
+ int, long, void *)
+{
+ Ssl::ErrorDetail *errDetail = static_cast <Ssl::ErrorDetail *>(ptr);
+ delete errDetail;
+}
+
/// \ingroup ServerProtocolSSLInternal
static void
ssl_initialize(void)
ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL);
ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL, &ssl_dupAclChecklist, &ssl_freeAclChecklist);
+ ssl_ex_index_ssl_error_detail = SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL, NULL, &ssl_free_ErrorDetail);
}
/// \ingroup ServerProtocolSSLInternal
/// \ingroup ServerProtocolSSLAPI
const char *sslGetUserCertificateChainPEM(SSL *ssl);
-typedef int ssl_error_t;
-ssl_error_t sslParseErrorString(const char *name);
-const char *sslFindErrorString(ssl_error_t value);
-
namespace Ssl
{
/**
*/
SSL_CTX * generateSslContextUsingPkeyAndCertFromMemory(const char * data);
-} //namespace Ssl
+/**
+ \ingroup ServerProtocolSSLAPI
+ * Iterates over the X509 common and alternate names and to see if matches with given data
+ * using the check_func.
+ \param peer_cert The X509 cert to check
+ \param check_data The data with which the X509 CNs compared
+ \param check_func The function used to match X509 CNs. The CN data passed as ASN1_STRING data
+ \return 1 if any of the certificate CN matches, 0 if none matches.
+ */
+int matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data));
-// Custom SSL errors; assumes all official errors are positive
-#define SQUID_X509_V_ERR_DOMAIN_MISMATCH -1
-// All SSL errors range: from smallest (negative) custom to largest SSL error
-#define SQUID_SSL_ERROR_MIN SQUID_X509_V_ERR_DOMAIN_MISMATCH
-#define SQUID_SSL_ERROR_MAX INT_MAX
+/**
+ \ingroup ServerProtocolSSLAPI
+ * Convert a given ASN1_TIME to a string form.
+ \param tm the time in ASN1_TIME form
+ \param buf the buffer to write the output
+ \param len write at most len bytes
+ \return The number of bytes written
+ */
+int asn1timeToString(ASN1_TIME *tm, char *buf, int len);
+
+} //namespace Ssl
#ifdef _SQUID_MSWIN_
#include "mgr/Registration.h"
#include "Store.h"
#include "HttpRequest.h"
+#include "log/Tokens.h"
#include "MemObject.h"
#include "fde.h"
#include "mem_node.h"
#include "mgr/IntervalAction.h"
#include "mgr/IoAction.h"
#include "mgr/ServiceTimesAction.h"
+#if USE_SSL
+#include "ssl/support.h"
+#endif
/* these are included because they expose stats calls */
/* TODO: provide a self registration mechanism for those classes
stats.mem_pool_allocated = mp_stats.TheMeter->alloc.level;
#endif
- stats.gb_freed_count = mp_stats.TheMeter->gb_saved.count;
+ stats.gb_saved_count = mp_stats.TheMeter->gb_saved.count;
stats.gb_freed_count = mp_stats.TheMeter->gb_freed.count;
}
storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n",
version_string);
-#if _SQUID_WIN32_
-
+#if _SQUID_WINDOWS_
if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
storeAppendPrintf(sentry,"\nRunning as %s Windows System Service on %s\n",
WIN32_Service_name, WIN32_OS_string);
storeAppendPrintf(sentry,"Service command line is: %s\n", WIN32_Service_Command_Line);
} else
storeAppendPrintf(sentry,"Running on %s\n",WIN32_OS_string);
-
#endif
storeAppendPrintf(sentry, "Start Time:\t%s\n",
stats.request_failure_ratio / fct);
storeAppendPrintf(sentry, "\tAverage HTTP requests per minute since start:\t%.1f\n",
- stats.avg_client_http_requests / fct);
+ stats.avg_client_http_requests);
storeAppendPrintf(sentry, "\tAverage ICP messages per minute since start:\t%.1f\n",
- stats.avg_icp_messages / fct);
+ stats.avg_icp_messages);
storeAppendPrintf(sentry, "\tSelect loop called: %.0f times, %0.3f ms avg\n",
stats.select_loops, stats.avg_loop_time / fct);
stats.request_hit_disk_ratio60 / fct);
storeAppendPrintf(sentry, "\tStorage Swap size:\t%.0f KB\n",
- stats.store_swap_size / 1024);
+ stats.store_swap_size);
storeAppendPrintf(sentry, "\tStorage Swap capacity:\t%4.1f%% used, %4.1f%% free\n",
Math::doublePercent(stats.store_swap_size, stats.store_swap_max_size),
c->timestamp = current_time;
/* even if NCountHist is small, we already Init()ed the tail */
statCountersClean(CountHist + N_COUNT_HIST - 1);
- xmemmove(p, t, (N_COUNT_HIST - 1) * sizeof(StatCounters));
+ memmove(p, t, (N_COUNT_HIST - 1) * sizeof(StatCounters));
statCountersCopy(t, c);
NCountHist++;
StatCounters *p2 = &CountHourHist[1];
StatCounters *c2 = &CountHist[N_COUNT_HIST - 1];
statCountersClean(CountHourHist + N_COUNT_HOUR_HIST - 1);
- xmemmove(p2, t2, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
+ memmove(p2, t2, (N_COUNT_HOUR_HIST - 1) * sizeof(StatCounters));
statCountersCopy(t2, c2);
NCountHourHist++;
}
{
assert(dest && orig);
/* this should take care of all the fields, but "special" ones */
- xmemcpy(dest, orig, sizeof(*dest));
+ memcpy(dest, orig, sizeof(*dest));
/* prepare space where to copy special entries */
statCountersInitSpecial(dest);
/* now handle special cases */
assert (location - aNode->nodeBuffer.offset == (int64_t)aNode->nodeBuffer.length);
size_t copyLen = min(amount, aNode->space());
- xmemcpy(aNode->nodeBuffer.data + aNode->nodeBuffer.length, source, copyLen);
+ memcpy(aNode->nodeBuffer.data + aNode->nodeBuffer.length, source, copyLen);
if (inmem_hi <= location)
inmem_hi = location + copyLen;
size_t copyLen = min(amount, aNode->nodeBuffer.length - copyOffset);
- xmemcpy(target, aNode->nodeBuffer.data + copyOffset, copyLen);
+ memcpy(target, aNode->nodeBuffer.data + copyOffset, copyLen);
return copyLen;
}
*/
size_t copy_sz = min(copyInto.length, body_sz);
debugs(90, 3, "storeClientReadHeader: copying " << copy_sz << " bytes of body");
- xmemmove(copyInto.data, copyInto.data + mem->swap_hdr_sz, copy_sz);
+ memmove(copyInto.data, copyInto.data + mem->swap_hdr_sz, copy_sz);
readBody(copyInto.data, copy_sz);
#endif
}
-/*
+/**
* Determine whether the given directory can handle this object
* size
*
* Note: if the object size is -1, then the only swapdirs that
- * will return true here are ones that have max_obj_size = -1,
+ * will return true here are ones that have min and max unset,
* ie any-sized-object swapdirs. This is a good thing.
*/
bool
SwapDir::objectSizeIsAcceptable(int64_t objsize) const
{
- /*
- * If the swapdir's max_obj_size is -1, then it definitely can
- */
-
- if (max_objsize == -1)
+ // If the swapdir has no range limits, then it definitely can
+ if (min_objsize <= 0 && max_objsize == -1)
return true;
/*
- * If the object size is -1, then if the storedir isn't -1 we
- * can't store it
+ * If the object size is -1 and the storedir has limits we
+ * can't store it there.
*/
- if ((objsize == -1) && (max_objsize != -1))
+ if (objsize == -1)
return false;
- /*
- * Else, make sure that the max object size is larger than objsize
- */
- return max_objsize > objsize;
+ // Else, make sure that the object size will fit.
+ return min_objsize <= objsize && max_objsize > objsize;
}
storeAppendPrintf(&output, "Store Directory Statistics:\n");
storeAppendPrintf(&output, "Store Entries : %lu\n",
(unsigned long int)StoreEntry::inUseCount());
- storeAppendPrintf(&output, "Maximum Swap Size : %8ld KB\n",
- (long int) maxSize());
+ storeAppendPrintf(&output, "Maximum Swap Size : %"PRIu64" KB\n",
+ maxSize());
storeAppendPrintf(&output, "Current Store Swap Size: %8lu KB\n",
store_swap_size);
- // XXX : below capacity display calculation breaks with int overflow on 64-bit systems
- storeAppendPrintf(&output, "Current Capacity : %d%% used, %d%% free\n",
- Math::intPercent((int) store_swap_size, (int) maxSize()),
- Math::intPercent((int) (maxSize() - store_swap_size), (int) maxSize()));
+ storeAppendPrintf(&output, "Current Capacity : %"PRId64"%% used, %"PRId64"%% free\n",
+ Math::int64Percent(store_swap_size, maxSize()),
+ Math::int64Percent((maxSize() - store_swap_size), maxSize()));
/* FIXME Here we should output memory statistics */
/* now the swapDir */
}
/* if needed, this could be taught to cache the result */
-size_t
+uint64_t
StoreController::maxSize() const
{
/* TODO: include memory cache ? */
return swapDir->maxSize();
}
-size_t
+uint64_t
StoreController::minSize() const
{
/* TODO: include memory cache ? */
StorePointer *tmp;
swap->n_allocated <<= 1;
tmp = static_cast<StorePointer *>(xcalloc(swap->n_allocated, sizeof(StorePointer)));
- xmemcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir *));
+ memcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir *));
xfree(swap->swapDirs);
swap->swapDirs = tmp;
}
}
StoreEntry *
-
-StoreController::get
-(const cache_key *key)
+StoreController::get(const cache_key *key)
{
- return swapDir->get
- (key);
+ return swapDir->get(key);
}
void
-
-StoreController::get
-(String const key, STOREGETCLIENT aCallback, void *aCallbackData)
+StoreController::get(String const key, STOREGETCLIENT aCallback, void *aCallbackData)
{
fatal("not implemented");
}
/* Lookup an object in the cache.
* return just a reference to object, don't start swapping in yet. */
StoreEntry *
-
-StoreHashIndex::get
-(const cache_key *key)
+StoreHashIndex::get(const cache_key *key)
{
PROF_start(storeGet);
debugs(20, 3, "storeGet: looking up " << storeKeyText(key));
}
void
-
-StoreHashIndex::get
-(String const key, STOREGETCLIENT aCallback, void *aCallbackData)
+StoreHashIndex::get(String const key, STOREGETCLIENT aCallback, void *aCallbackData)
{
fatal("not implemented");
}
}
}
-size_t
+uint64_t
StoreHashIndex::maxSize() const
{
- int i;
- size_t result = 0;
+ uint64_t result = 0;
- for (i = 0; i < Config.cacheSwap.n_configured; i++)
+ for (int i = 0; i < Config.cacheSwap.n_configured; i++)
result += store(i)->maxSize();
return result;
}
-size_t
+uint64_t
StoreHashIndex::minSize() const
{
- size_t result = 0;
+ uint64_t result = 0;
for (int i = 0; i < Config.cacheSwap.n_configured; i++)
result += store(i)->minSize();
storeKeyDup(const cache_key * key)
{
cache_key *dup = (cache_key *)memAllocate(MEM_MD5_DIGEST);
- xmemcpy(dup, key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(dup, key, SQUID_MD5_DIGEST_LENGTH);
return dup;
}
cache_key *
storeKeyCopy(cache_key * dst, const cache_key * src)
{
- xmemcpy(dst, src, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(dst, src, SQUID_MD5_DIGEST_LENGTH);
return dst;
}
#include "squid.h"
#include "HttpReply.h"
#include "log/File.h"
+#include "log/Tokens.h"
#include "MemObject.h"
#include "mgr/Registration.h"
#include "Store.h"
buf[j++] = (char) STORE_META_OK;
- xmemcpy(&buf[j], &buflen, sizeof(int));
+ memcpy(&buf[j], &buflen, sizeof(int));
j += sizeof(int);
for (t = tlv_list; t; t = t->next) {
buf[j++] = t->getType();
- xmemcpy(&buf[j], &t->length, sizeof(int));
+ memcpy(&buf[j], &t->length, sizeof(int));
j += sizeof(int);
- xmemcpy(&buf[j], t->value, t->length);
+ memcpy(&buf[j], t->value, t->length);
j += t->length;
}
static StoreIOState::STIOCB storeSwapOutFileClosed;
static StoreIOState::STFNCB storeSwapOutFileNotify;
+// wrapper to cross C/C++ ABI boundary. xfree is extern "C" for libraries.
+static void xfree_cppwrapper(void *x)
+{
+ xfree(x);
+}
+
/* start swapping object to disk */
static void
storeSwapOutStart(StoreEntry * e)
e->swap_dirn = mem->swapout.sio->swap_dirn;
/* write out the swap metadata */
- storeIOWrite(mem->swapout.sio, buf, mem->swap_hdr_sz, 0, xfree);
+ storeIOWrite(mem->swapout.sio, buf, mem->swap_hdr_sz, 0, xfree_cppwrapper);
}
static void
/* for ICP_END */
#include "icp_opcode.h"
+#if USE_SSL
+#include <openssl/ssl.h>
+#endif
+
#define PEER_MULTICAST_SIBLINGS 1
struct acl_name_list {
#if USE_HTTP_VIOLATIONS
time_t negativeTtl;
#endif
+ time_t maxStale;
time_t negativeDnsTtl;
time_t positiveDnsTtl;
time_t shutdownLifetime;
size_t maxRequestHeaderSize;
int64_t maxRequestBodySize;
int64_t maxChunkedRequestBodySize;
+ size_t maxRequestBufferSize;
size_t maxReplyHeaderSize;
acl_size_t *ReplyBodySize;
struct {
char *store;
char *swap;
-#if USE_USERAGENT_LOG
-
- char *useragent;
-#endif
-#if USE_REFERER_LOG
-
- char *referer;
-#endif
-#if WIP_FWD_LOG
-
- char *forward;
-#endif
-
- logformat *logformats;
-
customlog *accesslogs;
-
#if ICAP_CLIENT
customlog *icaplogs;
#endif
-
int rotateNumber;
} Log;
char *adminEmail;
int passive;
int epsv_all;
int epsv;
+ int eprt;
int sanitycheck;
int telnet;
} Ftp;
int max_age;
int s_maxage;
int max_stale;
+ int stale_if_error;
int min_fresh;
String other;
};
unsigned int ignore_auth:1;
#endif
} flags;
+ int max_stale;
};
/*
int zero_object_sz;
};
-class logformat_token;
-
-struct _logformat {
- char *name;
- logformat_token *format;
- logformat *next;
-};
-
class Logfile;
+class logformat;
+#include "log/Formats.h"
struct _customlog {
char *filename;
ACLList *aclList;
logformat *logFormat;
Logfile *logfile;
customlog *next;
- customlog_type type;
+ Log::Format::log_type type;
};
#endif /* SQUID_STRUCTS_H */
CacheEntry *e = (CacheEntry *)xcalloc(1, sizeof(CacheEntry));
assert(s);
/* e->s = *s; */
- xmemcpy(e->key_arr, s->key, SQUID_MD5_DIGEST_LENGTH);
+ memcpy(e->key_arr, s->key, SQUID_MD5_DIGEST_LENGTH);
e->key = &e->key_arr[0];
return e;
}
* strcmp(hier, "SSL_PARENT_MISS") &&
* strcmp(hier, "DEFAULT_PARENT");
*/
- xmemcpy(entry->key, storeKeyPublic(url, method_id), sizeof(entry->key));
+ memcpy(entry->key, storeKeyPublic(url, method_id), sizeof(entry->key));
/*fprintf(stdout, "%s:%d: %s %s %s %s\n",
* fname, count, method, storeKeyText(entry->key), url, hier); */
#include "squid.h"
#include "TestSwapDir.h"
-size_t
+uint64_t
TestSwapDir::maxSize() const
{
return 3;
bool statsCalled;
- virtual size_t maxSize() const;
+ virtual uint64_t maxSize() const;
virtual void stat(StoreEntry &) const; /* output stats to the provided store entry */
virtual void reconfigure(int, char*);
return *this;
}
-const int
+int
HelperChildConfig::needNew() const
{
/* during the startup and reconfigure use our special amount... */
Mgr::Action::Pointer
CacheManager::createNamedAction(char const* action)
{
- fatal ("Not implemented");
+ fatal("Not implemented");
return NULL;
}
return;
}
+CacheManager* CacheManager::instance=0;
+
CacheManager*
-CacheManager::GetInstance(void)
+CacheManager::GetInstance()
{
- static CacheManager *instance = 0;
- if (!instance)
- instance = new CacheManager();
+ fatal("Not implemented");
return instance;
}
#include "squid.h"
#include "comm.h"
+#include "comm/Loops.h"
#include "CommRead.h"
#include "fde.h"
}
void
-commSetSelect(int fd, unsigned int type, PF * handler, void *client_data,
- time_t timeout)
+Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
{
/* all test code runs synchronously at the moment */
}
void
-comm_quick_poll_required()
+Comm::QuickPollRequired()
{
/* for tests ... ignore */
}
--- /dev/null
+#include "config.h"
+#include "ipc/Forwarder.h"
+
+//Avoid linker errors about Ipc::Forwarder
+void foo_stub_ipc_forwarder()
+{
+ Ipc::Forwarder foo(NULL,1.0);
+}
fatal("storeAppendPrintf: Not implemented");
}
-extern "C" void
+void
storeAppendVPrintf(StoreEntry * e, const char *fmt, va_list vargs)
{
fatal("storeAppendVPrintf: Not implemented");
}
StoreEntry*
-
-TestStore::get
-(const cache_key*)
+TestStore::get(const cache_key*)
{
return NULL;
}
void
-
-TestStore::get
-(String, void (*)(StoreEntry*, void*), void*)
+TestStore::get(String, void (*)(StoreEntry*, void*), void*)
{}
void
TestStore::init()
{}
-size_t
+uint64_t
TestStore::maxSize() const
{
return 3;
}
-size_t
+uint64_t
TestStore::minSize() const
{
return 1;
void
testStore::testSetRoot()
{
- StorePointer aStore (new TestStore);
+ StorePointer aStore(new TestStore);
Store::Root(aStore);
CPPUNIT_ASSERT(&Store::Root() == aStore.getRaw());
void
testStore::testUnsetRoot()
{
- StorePointer aStore (new TestStore);
- StorePointer aStore2 (new TestStore);
+ StorePointer aStore(new TestStore);
+ StorePointer aStore2(new TestStore);
Store::Root(aStore);
Store::Root(aStore2);
CPPUNIT_ASSERT(&Store::Root() == aStore2.getRaw());
void
testStore::testStats()
{
- TestStorePointer aStore (new TestStore);
+ TestStorePointer aStore(new TestStore);
Store::Root(aStore.getRaw());
CPPUNIT_ASSERT(aStore->statsCalled == false);
Store::Stats(NullStoreEntry::getInstance());
void
testStore::testMaxSize()
{
- StorePointer aStore (new TestStore);
+ StorePointer aStore(new TestStore);
Store::Root(aStore.getRaw());
CPPUNIT_ASSERT(aStore->maxSize() == 3);
Store::Root(NULL);
virtual void maintain() {};
- virtual size_t maxSize() const;
+ virtual uint64_t maxSize() const;
- virtual size_t minSize() const;
+ virtual uint64_t minSize() const;
virtual void stat(StoreEntry &) const; /* output stats to the provided store entry */
{
getCurrentTime();
}
+
+const char *
+Time::FormatStrf(time_t t)
+{
+ struct tm *tm;
+ static char buf[128];
+ static time_t last_t = 0;
+
+ if (t != last_t) {
+ tm = localtime(&t);
+ strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
+ last_t = t;
+ }
+
+ return buf;
+}
+
+const char *
+Time::FormatHttpd(time_t t)
+{
+ static char buf[128];
+ static time_t last_t = 0;
+
+ if (t != last_t) {
+ struct tm *gmt = gmtime(&t);
+
+#if !USE_GMT
+ int gmt_min, gmt_hour, gmt_yday, day_offset;
+ size_t len;
+ struct tm *lt;
+ int min_offset;
+
+ /* localtime & gmtime may use the same static data */
+ gmt_min = gmt->tm_min;
+ gmt_hour = gmt->tm_hour;
+ gmt_yday = gmt->tm_yday;
+
+ lt = localtime(&t);
+
+ day_offset = lt->tm_yday - gmt_yday;
+ /* wrap round on end of year */
+ if (day_offset > 1)
+ day_offset = -1;
+ else if (day_offset < -1)
+ day_offset = 1;
+
+ min_offset = day_offset * 1440 + (lt->tm_hour - gmt_hour) * 60
+ + (lt->tm_min - gmt_min);
+
+ len = strftime(buf, 127 - 5, "%d/%b/%Y:%H:%M:%S ", lt);
+ snprintf(buf + len, 128 - len, "%+03d%02d",
+ (min_offset / 60) % 24,
+ min_offset % 60);
+#else /* USE_GMT */
+ buf[0] = '\0';
+ strftime(buf, 127, "%d/%b/%Y:%H:%M:%S -000", gmt);
+#endif /* USE_GMT */
+
+ last_t = t;
+ }
+
+ return buf;
+}
memset(r, '\0', sizeof(struct rusage));
#if HAVE_GETRUSAGE && defined(RUSAGE_SELF)
-#ifdef _SQUID_SOLARIS_
+#if _SQUID_SOLARIS_
/* Solaris 2.5 has getrusage() permission bug -- Arjan de Vet */
enter_suid();
#endif
getrusage(RUSAGE_SELF, r);
-#ifdef _SQUID_SOLARIS_
+#if _SQUID_SOLARIS_
leave_suid();
#endif
void
setSystemLimits(void)
{
-#if HAVE_SETRLIMIT && defined(RLIMIT_NOFILE) && !defined(_SQUID_CYGWIN_)
+#if HAVE_SETRLIMIT && defined(RLIMIT_NOFILE) && !_SQUID_CYGWIN_
/* limit system filedescriptors to our own limit */
struct rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
return;
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(fileno(fp), O_TEXT);
-
#endif
while (fgets(buf, 1024, fp)) { /* for each line */
size_t kb;
} kb_t;
-//UNUSED typedef struct _acl_time_data acl_time_data;
-//UNUSED typedef struct _acl_name_list acl_name_list;
-//UNUSED typedef struct _acl_deny_info_list acl_deny_info_list;
-//UNUSED typedef class AuthUser auth_user_t;
-
-
/// \ingroup AuthAPI
/// \deprecated Use AuthUserHashPointer instead.
typedef struct AuthUserHashPointer auth_user_hash_pointer;
class AuthConfig;
typedef Vector<AuthConfig *> authConfig;
-//UNUSED typedef struct _acl_snmp_comm acl_snmp_comm;
-//UNUSED typedef class ACLList acl_list;
-//UNUSED typedef struct _acl_address acl_address;
-//UNUSED typedef struct _acl_tos acl_tos;
-//UNUSED typedef struct _acl_size_t acl_size_t;
-//UNUSED class ACLChecklist;
-//UNUSED typedef struct _ushortlist ushortlist;
-//UNUSED typedef struct _relist relist;
-
struct http_port_list;
struct https_port_list;
-//UNUSED typedef struct _SquidConfig SquidConfig;
-//UNUSED typedef struct _SquidConfig2 SquidConfig2;
-
typedef struct _close_handler close_handler;
typedef struct _dread_ctrl dread_ctrl;
typedef struct _ETag ETag;
-//UNUSED class fde;
-
typedef struct _fileMap fileMap;
typedef struct _HttpHeaderFieldAttrs HttpHeaderFieldAttrs;
-//UNUSED class HttpHeaderFieldInfo;
-//UNUSED class HttpHeader;
-//UNUSED class HttpHdrCc;
-
typedef struct _TimeOrTag TimeOrTag;
-//UNUSED class HttpHeaderFieldStat;
-
typedef struct _HttpHeaderStat HttpHeaderStat;
typedef struct _HttpBody HttpBody;
-//UNUSED class HttpReply;
-
typedef struct _ConnCloseHelperData ConnCloseHelperData;
typedef struct _ipcache_addrs ipcache_addrs;
typedef struct _DigestFetchState DigestFetchState;
-//UNUSED class PeerDigest;
-
-//UNUSED typedef struct _peer peer;
-
typedef struct _net_db_name net_db_name;
typedef struct _net_db_peer net_db_peer;
typedef struct _iostats iostats;
-//UNUSED class MemBuf;
-
-//UNUSED class store_client;
-
-//UNUSED class SwapDir;
-
typedef struct _http_state_flags http_state_flags;
typedef struct _header_mangler header_mangler;
typedef struct _body_size body_size;
-//UNUSED class HttpRequest;
-
typedef struct _cachemgr_passwd cachemgr_passwd;
typedef struct _refresh_t refresh_t;
typedef struct _StatCounters StatCounters;
-/// \todo DROP: deprecated and no longer used.
typedef struct _storeSwapLogData storeSwapLogData;
typedef struct _StatHist StatHist;
typedef struct _link_list link_list;
-typedef struct _logformat logformat;
-
typedef struct _customlog customlog;
#if SQUID_SNMP
if ((t = strrchr(Host, '@'))) {
t++;
- xmemmove(Host, t, strlen(t) + 1);
+ memmove(Host, t, strlen(t) + 1);
}
}
old = list;
n <<= 2;
list = (url_entry *)xcalloc(n + 1, sizeof(*list));
- xmemcpy(list, old, i * sizeof(*list));
+ memcpy(list, old, i * sizeof(*list));
safe_free(old);
}
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
+#include "config.h"
+
+#if USE_WCCP
+
#include "squid.h"
#include "comm.h"
+#include "comm/Loops.h"
#include "event.h"
-#if USE_WCCP
-
#define WCCP_PORT 2048
#define WCCP_REVISION 0
#define WCCP_ACTIVE_CACHES 32
if (theWccpConnection < 0)
fatal("Cannot open WCCP Port");
- commSetSelect(theWccpConnection,
- COMM_SELECT_READ,
- wccpHandleUdp,
- NULL,
- 0);
+ Comm::SetSelect(theWccpConnection, COMM_SELECT_READ, wccpHandleUdp, NULL, 0);
debugs(80, 1, "Accepting WCCPv1 messages on " << Config.Wccp.address << ", FD " << theWccpConnection << ".");
debugs(80, 6, "wccpHandleUdp: Called.");
- commSetSelect(sock, COMM_SELECT_READ, wccpHandleUdp, NULL, 0);
+ Comm::SetSelect(sock, COMM_SELECT_READ, wccpHandleUdp, NULL, 0);
memset(&wccp_i_see_you, '\0', sizeof(wccp_i_see_you));
for (loop = 0; loop < number_caches; loop++) {
int i;
- xmemcpy(&caches[loop],
- &wccp_i_see_you.wccp_cache_entry[loop].ip_addr,
- sizeof(*caches));
+ memcpy(&caches[loop],
+ &wccp_i_see_you.wccp_cache_entry[loop].ip_addr,
+ sizeof(*caches));
for (i = 0; i < buckets_per_cache; i++) {
assert(bucket < WCCP_BUCKETS);
#if USE_WCCPv2
#include "comm.h"
+#include "comm/Loops.h"
#include "compat/strsep.h"
#include "event.h"
#include "ip/Address.h"
service_list_ptr->security_info = (struct wccp2_security_md5_t *) ptr;
if (service_list_ptr->wccp2_security_type == WCCP2_MD5_SECURITY) {
-
- xmemcpy(ptr, &wccp2_security_md5, sizeof(struct wccp2_security_md5_t));
-
+ memcpy(ptr, &wccp2_security_md5, sizeof(struct wccp2_security_md5_t));
ptr += sizeof(struct wccp2_security_md5_t);
} else {
/* assume NONE, and XXX I hate magic length numbers */
- xmemcpy(ptr, &wccp2_security_md5, 8);
+ memcpy(ptr, &wccp2_security_md5, 8);
ptr += 8;
}
assert(wccp2_here_i_am_header.length <= WCCP_RESPONSE_SIZE);
- xmemcpy(ptr, &service_list_ptr->info, sizeof(struct wccp2_service_info_t));
+ memcpy(ptr, &service_list_ptr->info, sizeof(struct wccp2_service_info_t));
service_list_ptr->service_info = (struct wccp2_service_info_t *) ptr;
wccp2_identity_info.cache_identity.weight = htons(Config.Wccp2.weight);
memset(&wccp2_identity_info.cache_identity.status, '\0', sizeof(wccp2_identity_info.cache_identity.status));
- xmemcpy(ptr, &wccp2_identity_info, sizeof(struct wccp2_identity_info_t));
+ memcpy(ptr, &wccp2_identity_info, sizeof(struct wccp2_identity_info_t));
service_list_ptr->wccp2_identity_info_ptr = ptr;
ptr += sizeof(struct wccp2_identity_info_t);
wccp2_mask_identity_info.cache_identity.weight = 0;
wccp2_mask_identity_info.cache_identity.status = 0;
- xmemcpy(ptr, &wccp2_mask_identity_info, sizeof(struct wccp2_mask_identity_info_t));
+ memcpy(ptr, &wccp2_mask_identity_info, sizeof(struct wccp2_mask_identity_info_t));
service_list_ptr->wccp2_identity_info_ptr = ptr;
ptr += sizeof(struct wccp2_mask_identity_info_t);
wccp2_cache_view_header.cache_view_version = htonl(1);
- xmemcpy(ptr, &wccp2_cache_view_header, sizeof(wccp2_cache_view_header));
+ memcpy(ptr, &wccp2_cache_view_header, sizeof(wccp2_cache_view_header));
ptr += sizeof(wccp2_cache_view_header);
service_list_ptr->num_routers = htonl(wccp2_numrouters);
- xmemcpy(ptr, &service_list_ptr->num_routers, sizeof(service_list_ptr->num_routers));
+ memcpy(ptr, &service_list_ptr->num_routers, sizeof(service_list_ptr->num_routers));
ptr += sizeof(service_list_ptr->num_routers);
wccp2_cache_view_info.num_caches = htonl(0);
- xmemcpy(ptr, &wccp2_cache_view_info.num_caches, sizeof(wccp2_cache_view_info.num_caches));
+ memcpy(ptr, &wccp2_cache_view_info.num_caches, sizeof(wccp2_cache_view_info.num_caches));
ptr += sizeof(wccp2_cache_view_info.num_caches);
wccp2_capability_info_header.capability_info_length = htons(3 * sizeof(wccp2_capability_element));
- xmemcpy(ptr, &wccp2_capability_info_header, sizeof(wccp2_capability_info_header));
+ memcpy(ptr, &wccp2_capability_info_header, sizeof(wccp2_capability_info_header));
ptr += sizeof(wccp2_capability_info_header);
wccp2_capability_element.capability_value = htonl(Config.Wccp2.forwarding_method);
- xmemcpy(ptr, &wccp2_capability_element, sizeof(wccp2_capability_element));
+ memcpy(ptr, &wccp2_capability_element, sizeof(wccp2_capability_element));
ptr += sizeof(wccp2_capability_element);
wccp2_capability_element.capability_value = htonl(Config.Wccp2.assignment_method);
- xmemcpy(ptr, &wccp2_capability_element, sizeof(wccp2_capability_element));
+ memcpy(ptr, &wccp2_capability_element, sizeof(wccp2_capability_element));
ptr += sizeof(wccp2_capability_element);
wccp2_capability_element.capability_value = htonl(Config.Wccp2.return_method);
- xmemcpy(ptr, &wccp2_capability_element, sizeof(wccp2_capability_element));
+ memcpy(ptr, &wccp2_capability_element, sizeof(wccp2_capability_element));
ptr += sizeof(wccp2_capability_element);
}
#endif
- commSetSelect(theWccp2Connection,
- COMM_SELECT_READ,
- wccp2HandleUdp,
- NULL,
- 0);
+ Comm::SetSelect(theWccp2Connection, COMM_SELECT_READ, wccp2HandleUdp, NULL, 0);
debugs(80, 1, "Accepting WCCPv2 messages on port " << WCCP_PORT << ", FD " << theWccp2Connection << ".");
debugs(80, 1, "Initialising all WCCPv2 lists");
debugs(80, 6, "wccp2HandleUdp: Called.");
- commSetSelect(sock, COMM_SELECT_READ, wccp2HandleUdp, NULL, 0);
+ Comm::SetSelect(sock, COMM_SELECT_READ, wccp2HandleUdp, NULL, 0);
/* FIXME INET6 : drop conversion boundary */
Ip::Address from_tmp;
offset += sizeof(struct assignment_key_t);
/* Number of routers */
- xmemcpy(&wccp_packet[offset], &service_list_ptr->num_routers, sizeof(service_list_ptr->num_routers));
+ memcpy(&wccp_packet[offset], &service_list_ptr->num_routers, sizeof(service_list_ptr->num_routers));
offset += sizeof(service_list_ptr->num_routers);
case WCCP2_ASSIGNMENT_METHOD_HASH:
/* Number of caches */
- xmemcpy(&wccp_packet[offset], &router_list_ptr->num_caches, sizeof(router_list_ptr->num_caches));
+ memcpy(&wccp_packet[offset], &router_list_ptr->num_caches, sizeof(router_list_ptr->num_caches));
offset += sizeof(router_list_ptr->num_caches);
if (num_caches) {
cache_address = (struct in_addr *) &wccp_packet[offset];
- xmemcpy(cache_address, &cache_list_ptr->cache_ip, sizeof(struct in_addr));
+ memcpy(cache_address, &cache_list_ptr->cache_ip, sizeof(struct in_addr));
total_weight += cache_list_ptr->weight << 12;
weight[cache] = cache_list_ptr->weight << 12;
case WCCP2_ASSIGNMENT_METHOD_MASK:
num_maskval = htonl(1);
- xmemcpy(&wccp_packet[offset], &num_maskval, sizeof(int));
+ memcpy(&wccp_packet[offset], &num_maskval, sizeof(int));
offset += sizeof(int);
mask_element = (struct wccp2_mask_element_t *) &wccp_packet[offset];
# do not build any of the install's ...
#
# eval is need to correctly handle quoted arguments
- eval "$base/../configure ${SQUID_CONFIGURE_FLAGS} ${configcache}" \
+ eval "$base/../configure ${DISTCHECK_CONFIGURE_FLAGS} ${configcache}" \
2>&1 && \
make ${pjobs} ${MAKETEST} 2>&1
MAKETEST="distcheck"
#
#
-# The options for this level can be easily generated semi-automatically from configure.in by:
-# grep -E "^AC_ARG_ENABLE" ./configure.in | grep -o -E "[0-9a-z\-]+[,]" | grep -o -E "[^,]+" >disable.opts
+# The options for this level can be easily generated semi-automatically from configure.ac by:
+# grep -E "^AC_ARG_ENABLE" ./configure.ac | grep -o -E "[0-9a-z\-]+[,]" | grep -o -E "[^,]+" >disable.opts
# followed by insertion of ' --disable-' and '\' strings
#
-# grep -E "^AC_ARG_WITH" ./configure.in | grep -o -E "[0-9a-z\-]+[,]" | grep -o -E "[^,]+" >without.opts
+# grep -E "^AC_ARG_WITH" ./configure.ac | grep -o -E "[0-9a-z\-]+[,]" | grep -o -E "[^,]+" >without.opts
# followed by insertion of ' --without-' and ' \' strings
#
# sometimes it's just too automatic.. Following options should be just stripped
MAKETEST="distcheck"
#
#
-# The options for this level can be easily generated semi-automatically from configure.in by:
-# grep -E "^AC_ARG_ENABLE" ./configure.in | grep -o -E "[0-9a-z\-]+[,]" | grep -o -E "[^,]+" >disable.opts
+# The options for this level can be easily generated semi-automatically from configure.ac by:
+# grep -E "^AC_ARG_ENABLE" ./configure.ac | grep -o -E "[0-9a-z\-]+[,]" | grep -o -E "[^,]+" >disable.opts
# followed by insertion of ' --enable-' and '\' strings
#
-# grep -E "^AC_ARG_WITH" ./configure.in | grep -o -E "[0-9a-z\-]+[,]" | grep -o -E "[^,]+" >without.opts
+# grep -E "^AC_ARG_WITH" ./configure.ac | grep -o -E "[0-9a-z\-]+[,]" | grep -o -E "[^,]+" >without.opts
# followed by insertion of ' --with-' and ' \' strings
#
# sometimes it's just too automatic..
# --enable-win32-service \
# --with-valgrind-debug \
#
+# --enable-cpu-profiling \ Requires CPU support.
+#
#
# NP: DISTCHECK_CONFIGURE_FLAGS is a magic automake macro for the
# distcheck target recursive tests beteen scripted runs.
--enable-mempools \
--enable-unlinkd \
--enable-stacktraces \
- --enable-cpu-profiling \
--enable-vary \
--enable-x-accelerator-vary \
--enable-ipv6 \
return -1;
}
total_bytes_read += len;
- xmemcpy(buf, inbuf, len);
+ memcpy(buf, inbuf, len);
if (len == 0) {
fprintf(stderr, "WARNING: %s, server closed socket after %d+%d bytes\n", r->url, r->hdr_offset, r->bytes_read);
/* XXX, If no data was received and it isn't the first request on this
/* Build headers */
if (r->hdr_length == 0) {
hlen = min(len, REPLY_HDR_SZ - r->hdr_offset - 1);
- xmemcpy(r->reply_hdrs + r->hdr_offset, buf, hlen);
+ memcpy(r->reply_hdrs + r->hdr_offset, buf, hlen);
r->hdr_offset += hlen;
r->reply_hdrs[r->hdr_offset] = '\0';
len -= hlen;
/* Save any remaining read data */
- xmemmove(buf, buf + hlen, len);
+ memmove(buf, buf + hlen, len);
}
/* Process headers */
if (r->hdr_length == 0 && (end = mime_headers_end(r->reply_hdrs)) != NULL) {
blen = r->hdr_offset - r->hdr_length;
assert(blen >= 0);
if (blen > 0) {
- xmemmove(buf + blen, buf, len);
- xmemcpy(buf, r->reply_hdrs + r->hdr_length, blen);
+ memmove(buf + blen, buf, len);
+ memcpy(buf, r->reply_hdrs + r->hdr_length, blen);
len += blen;
}
r->reply_hdrs[r->hdr_length] = '\0'; /* Null terminate headers */
} else if (r->content_length > -1) {
assert(r->bytes_read < r->content_length);
}
- xmemmove(buf, buf + bytes_used, len);
+ memmove(buf, buf + bytes_used, len);
}
}
return 0;
if [ ! -f "$t.o" -o $f -nt "$t.o" ]; then
echo >$t.cc <<EOF
/* This file is AUTOMATICALLY GENERATED. DO NOT ALTER IT */
+#include "config.h"
#include "${f}"
int main( int argc, char* argv[] ) { return 0; }
EOF
DISTCLEANFILES =
LDADD = \
- $(top_builddir)/src/tests/stub_debug.o \
- $(top_builddir)/src/time.o \
$(top_builddir)/src/ip/libip.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
include $(top_srcdir)/doc/manuals/Substitute.am
+## Several files need to be shared but we cannot depend on the other
+## directories to be built.
test_tools.cc: $(top_srcdir)/test-suite/test_tools.cc
cp $(top_srcdir)/test-suite/test_tools.cc .
+stub_debug.cc: $(top_srcdir)/src/tests/stub_debug.cc
+ cp $(top_srcdir)/src/tests/stub_debug.cc .
+
+time.cc: $(top_srcdir)/src/time.cc
+ cp $(top_srcdir)/src/time.cc .
+
# stock tools for unit tests - library independent versions of dlink_list
# etc.
# globals.cc is needed by test_tools.cc.
# Neither of these should be disted from here.
TESTSOURCES= test_tools.cc
-CLEANFILES += test_tools.cc
+CLEANFILES += test_tools.cc stub_debug.cc time.cc
## ##### helper-mux #####
bin_PROGRAMS = squidclient
squidclient_SOURCES = squidclient.cc \
- test_tools.cc
+ stub_debug.cc \
+ test_tools.cc \
+ time.cc
EXTRA_DIST += squidclient.1
man_MANS += squidclient.1
libexec_PROGRAMS = cachemgr$(CGIEXT)
cachemgr__CGIEXT__SOURCES = cachemgr.cc \
- test_tools.cc
+ stub_debug.cc \
+ test_tools.cc \
+ time.cc
cachemgr__CGIEXT__CXXFLAGS = -DDEFAULT_CACHEMGR_CONFIG=\"$(DEFAULT_CACHEMGR_CONFIG)\" $(AM_CXXFLAGS)
/** \endcond */
#endif
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
#include <io.h>
#endif
#if HAVE_STDIO_H
#include <gssapi/gssapi.h>
#elif HAVE_GSSAPI_H
#include <gssapi.h>
-#endif /* HAVE_GSSAPI_H */
-#if HAVE_GSSAPI_GSSAPI_EXT_H
-#include <gssapi/gssapi_ext.h>
-#endif /* HAVE_GSSAPI_GSSAPI_EXT_H */
+#endif /* HAVE_GSSAPI_GSSAPI_H/HAVE_GSSAPI_H */
+#if !HAVE_HEIMDAL_KERBEROS
#if HAVE_GSSAPI_GSSAPI_KRB5_H
#include <gssapi/gssapi_krb5.h>
-#endif /* HAVE_GSSAPI_GSSAPI_KRB5_H */
+#endif
#if HAVE_GSSAPI_GSSAPI_GENERIC_H
#include <gssapi/gssapi_generic.h>
-#endif /* HAVE_GSSAPI_GSSAPI_GENERIC_H */
+#endif
+#if HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#endif
+#endif
#ifndef gss_nt_service_name
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
static void usage(const char *progname);
static int Now(struct timeval *);
-static SIGHDLR catchSignal;
-static SIGHDLR pipe_handler;
+SIGHDLR catchSignal;
+SIGHDLR pipe_handler;
static void set_our_signal(void);
static ssize_t myread(int fd, void *buf, size_t len);
static ssize_t mywrite(int fd, void *buf, size_t len);
xstrerror());
exit(-1);
}
-#ifdef _SQUID_WIN32_
+#if _SQUID_WINDOWS_
setmode(put_fd, O_BINARY);
-
#endif
fstat(put_fd, &sb);
#endif
} /* ARGSUSED */
-static void
+void
catchSignal(int sig)
{
interrupted = 1;
fprintf(stderr, "Interrupted.\n");
}
-static void
+void
pipe_handler(int sig)
{
fprintf(stderr, "SIGPIPE received.\n");