Commit 6322f952 authored by Nils Goroll's avatar Nils Goroll

initial commit

parents
# Matches ALL Makefile and Makefile.in occurrences
Makefile
Makefile.in
# ...
.deps/
.libs/
*.o
*.lo
*.la
*~
*.sw[op]
*.trs
.dirstamp
# slink-ish configure call
CONFIGURE
# Various auto-tools artifacts
/aclocal.m4
/autom4te.cache/
/compile
/config.guess
/dcs_config.h
/dcs_config.h.in
/dcs_config.h.in~
/config.log
/config.status
/config.sub
/configure
/configure.lineno
/depcomp
/install-sh
/libtool
/ltmain.sh
/m4/libtool.m4
/m4/ltoptions.m4
/m4/ltsugar.m4
/m4/ltversion.m4
/m4/lt~obsolete.m4
/missing
/stamp-h1
/varnishapi.pc
/build-aux
TAGS
cscope.*out
#
# generated man
vmod_dcs.3
Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
All rights reserved.
Use only with permission
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src
dist_man_MANS = vmod_dcs.3
MAINTAINERCLEANFILES = $(dist_man_MANS)
doc_DATA = README.rst LICENSE
vmod_dcs.3: README.rst
if HAVE_RST2MAN
${RST2MAN} README.rst $@
else
@echo "========================================"
@echo "You need rst2man installed to make dist"
@echo "========================================"
@false
endif
dist_data_DATA = dcs_config.h
==============
DCS Classifier
==============
*TODO* fill in the skeleton
--------------------------------------------
Varnish Device Classification Service Module
--------------------------------------------
:Manual section: 3
:Authors: Nils Goroll
:Date: 2014-03-03
:Version: 0.1
SYNOPSIS
========
::
import dcs;
DESCRIPTION
===========
FUNCTIONS
=========
Example VCL::
backend foo { ... };
import dcs;
classify()
----------
Prototype
::
Returns
Description
Example
::
INSTALLATION
============
Installation requires the Varnish source tree (only the source matching the
binary installation).
1. `./autogen.sh` (for git-installation)
2. `./configure VARNISHSRC=/path/to/your/varnish/source/varnish-cache`
3. `make`
4. `make install` (may require root: sudo make install)
5. `make check` (Optional for regression tests)
VARNISHSRCDIR is the directory of the Varnish source tree for which to
compile your vmod. Both the VARNISHSRCDIR and VARNISHSRCDIR/include
will be added to the include search paths for your module.
Optionally you can also set the vmod install dir by adding VMODDIR=DIR
(defaults to the pkg-config discovered directory from your Varnish
installation).
ACKNOWLEDGEMENTS
================
HISTORY
=======
Version 0.1: Initial version, mostly feature-complete
BUGS
====
No bugs at all!
SEE ALSO
========
* varnishd(1)
* vcl(7)
COPYRIGHT
=========
See LICENSE for details.
* Copyright 2014 UPLEX - Nils Goroll Systemoptimierung
#!/bin/sh
warn() {
echo "WARNING: $@" 1>&2
}
case `uname -s` in
Darwin)
LIBTOOLIZE=glibtoolize
;;
FreeBSD)
LIBTOOLIZE=libtoolize
;;
Linux)
LIBTOOLIZE=libtoolize
;;
SunOS)
LIBTOOLIZE=libtoolize
;;
*)
warn "unrecognized platform:" `uname -s`
LIBTOOLIZE=libtoolize
esac
automake_version=`automake --version | tr ' ' '\n' | egrep '^[0-9]\.[0-9a-z.-]+'`
if [ -z "$automake_version" ] ; then
warn "unable to determine automake version"
else
case $automake_version in
0.*|1.[0-8]|1.[0-8][.-]*)
warn "automake ($automake_version) detected; 1.9 or newer recommended"
;;
*)
;;
esac
fi
set -ex
$LIBTOOLIZE --copy --force
aclocal -I m4
autoheader
automake --add-missing --copy --foreign
autoconf
AC_PREREQ(2.69)
AC_COPYRIGHT([Copyright 2014 UPLEX - Nils Goroll Systemoptimierung])
AC_INIT([dcs_classifier], [0.1])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR(src/gen_dcs_classifier.pl)
AM_CONFIG_HEADER(dcs_config.h)
AC_CANONICAL_SYSTEM
AC_LANG(C)
AM_INIT_AUTOMAKE([foreign])
AC_GNU_SOURCE
AC_PROG_CC
AC_PROG_CC_STDC
if test "x$ac_cv_prog_cc_c99" = xno; then
AC_MSG_ERROR([Could not find a C99 compatible compiler])
fi
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_PROG_MAKE_SET
# Check for rst utilities
AC_CHECK_PROGS(RST2MAN, [rst2man rst2man.py], "no")
if test "x$RST2MAN" = "xno"; then
AC_MSG_WARN([rst2man not found - not building man pages])
fi
AM_CONDITIONAL(HAVE_RST2MAN, [test "x$RST2MAN" != "xno"])
# Check for pkg-config
PKG_PROG_PKG_CONFIG
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([sys/stdlib.h])
############################################################
## DCS specifics
AC_ARG_VAR([DCS_KEY], [your DCS license key])
if test "x$DCS_KEY" = x; then
AC_MSG_ERROR([DCS_KEY is required])
fi
AC_ARG_VAR([DCS_ACCOUNT], [your netbiscuits account - optional, for online update only])
AC_ARG_VAR([DCS_DBFILE], [path to your DCS database file])
AC_CHECK_FILE([$DCS_DBFILE],
[],
[if test "x$DCS_ACCOUNT" = x; then
AC_MSG_ERROR([Need existing DCS_DBFILE if no DCS_ACCOUNT given])
fi
])
############################################################
## DEVELOPER flags etc
DEVELOPER_CFLAGS="-Werror -Wall -W -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wunused-parameter -Wcast-align -Wchar-subscripts -Wnested-externs -Wextra"
# These are not compliable yet
DEVELOPER_GCC_CFLAGS="-Wold-style-definition -Wredundant-decls "
#DEVELOPER_CFLAGS="${DEVELOPER_CFLAGS} ${DEVELOPER_GCC_CFLAGS}"
# These are compilable
DEVELOPER_CLANG_CFLAGS="-Wmissing-variable-declarations -Wno-string-plus-int"
# -Wno-empty-body
# --enable-developer-warnings
AC_ARG_ENABLE(developer-warnings,
AS_HELP_STRING([--enable-developer-warnings],[enable strict warnings (default is NO)]),
[],
[enable_developer_warnings=no])
#DEVELOPER_CFLAGS="${DEVELOPER_CFLAGS} ${DEVELOPER_CLANG_CFLAGS}"
if test "x$enable_developer_warnings" != "xno"; then
CFLAGS="${CFLAGS} ${DEVELOPER_CFLAGS}"
OCFLAGS="${OCFLAGS} ${DEVELOPER_CFLAGS}"
fi
# --enable-debugging-symbols
AC_ARG_ENABLE(debugging-symbols,
AS_HELP_STRING([--enable-debugging-symbols],[enable debugging symbols (default is NO)]),
CFLAGS="${CFLAGS} -O0 -g -fno-inline")
AC_SUBST(AM_LT_LDFLAGS)
############################################################
## VARNISH whether to install Varnish inline-c sources
AC_ARG_ENABLE(varnish2,
AS_HELP_STRING([--enable-varnish2],[install code for varnish2 inline-C (default is NO)]),
CFLAGS="${CFLAGS} -O0 -g -fno-inline")
AM_CONDITIONAL([INSTALL_VARNISH2], [test "x$enable_varnish2" != x])
############################################################
## VARNISH sources for vmod support
# Varnish source tree
AC_ARG_VAR([VARNISHSRC], [path to Varnish source tree for vmod])
AM_CONDITIONAL([BUILD_VMOD], [test "x$VARNISHSRC" != x])
if test "x$VARNISHSRC" = x; then
AC_MSG_WARN([No Varnish source - wont build the vmod])
else
AC_CHECK_PROGS(PYTHON, [python3 python3.1 python3.2 python2.7 python2.6 python2.5 python2 python], [AC_MSG_ERROR([Python is needed to build this vmod, please install python.])])
VARNISHSRC=`cd $VARNISHSRC && pwd`
AC_CHECK_FILE([$VARNISHSRC/include/varnishapi.h],
[],
[AC_MSG_FAILURE(["$VARNISHSRC" is not a Varnish source directory])]
)
# Check that varnishtest is built in the varnish source directory
AC_CHECK_FILE([$VARNISHSRC/bin/varnishtest/varnishtest],
[],
[AC_MSG_FAILURE([Can't find "$VARNISHSRC/bin/varnishtest/varnishtest". Please build your varnish source directory])]
)
# vmod installation dir
AC_ARG_VAR([VMODDIR], [vmod installation directory @<:@LIBDIR/varnish/vmods@:>@])
if test "x$VMODDIR" = x; then
VMODDIR=`pkg-config --variable=vmoddir varnishapi`
if test "x$VMODDIR" = x; then
AC_MSG_FAILURE([Can't determine vmod installation directory])
fi
fi
fi
############################################################
## FIN
AC_CONFIG_FILES([
Makefile
src/Makefile
src/gen/Makefile
])
AC_OUTPUT
# src / Makefile.am
AUTOMAKE_OPTIONS = subdir-objects
SUBDIRS = gen
bin_PROGRAMS = dcs dcs_test
dcs_match_SOURCES = \
$(top_srcdir)/src/gen/dcs_classifier.h \
dcs_match.h \
dcs_match.c
dcs_type_SOURCES = \
$(top_srcdir)/src/gen/dcs_classifier.h \
dcs_type.h \
dcs_type.c
dcs_test_CPPFLAGS = -Igen
dcs_test_SOURCES = \
$(top_srcdir)/src/gen/dcs_classifier.c \
$(dcs_match_SOURCES) \
$(dcs_type_SOURCES) \
dcs_test.c
dcs_CPPFLAGS = -Igen
dcs_SOURCES = \
$(top_srcdir)/src/gen/dcs_classifier.c \
$(dcs_match_SOURCES) \
$(dcs_type_SOURCES) \
dcs.c
EXTRA_DIST = gen_dcs_classifier.pl
# included c source
if INSTALL_VARNISH2
dcs_varnish2.c: dcs_varnish.c \
$(top_srcdir)/src/gen/dcs_classifier.c \
$(top_srcdir)/src/gen/dcs_classifier.h \
$(dcs_match_SOURCES) \
$(dcs_type_SOURCES)
dist_data_DATA = dcs_varnish2.c \
dcs_varnish.c \
$(top_srcdir)/src/gen/dcs_classifier.c \
$(top_srcdir)/src/gen/dcs_classifier.h \
dcs_match.h \
dcs_match.c \
dcs_type.h \
dcs_type.c
endif
## varnish 3 vmod
if BUILD_VMOD
vmoddir = $(VMODDIR)
vmod_LTLIBRARIES = libvmod_dcs.la
libvmod_dcs_la_CPPFLAGS = -Igen -I$(VARNISHSRC)/include -I$(VARNISHSRC)
libvmod_dcs_la_LDFLAGS = -module -export-dynamic -avoid-version
libvmod_dcs_la_SOURCES = \
vcc_if.c \
vcc_if.h \
vmod_dcs.c
vcc_if_INCLUDES = -I$(VARNISHSRC)/include -I$(VARNISHSRC)
vcc_dcs_INCLUDES = -I$(VARNISHSRC)/include -I$(VARNISHSRC)
vcc_if.c vcc_if.h: $(VARNISHSRC)/lib/libvmod_std/vmod.py $(top_srcdir)/src/vmod_dcs.vcc
@PYTHON@ $(VARNISHSRC)/lib/libvmod_std/vmod.py $(top_srcdir)/src/vmod_dcs.vcc
BUILT_SOURCES = \
vcc_if.c \
vcc_if.h
CLEANFILES = \
vcc_if.c \
vcc_if.h
VMOD_TESTS = tests/*.vtc
.PHONY: $(VMOD_TESTS)
tests/*.vtc:
$(VARNISHSRC)/bin/varnishtest/varnishtest -Dvarnishd=$(VARNISHSRC)/bin/varnishd/varnishd -Dvmod_topbuild=$(abs_top_builddir) $@
check: $(VMOD_TESTS)
EXTRA_DIST += \
vmod_dcs.vcc \
$(VMOD_TESTS)
endif
/*
* Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
* Use only with permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "dcs_config.h"
#include <stdio.h>
#include <ctype.h>
#include "dcs_match.h"
#include "dcs_type.h"
int
main (void) {
char *line = NULL;
int e, t;
size_t linesz;
while (getline(&line, &linesz, stdin) != -1) {
char *p = line;
for ( ; *p; ++p) *p = tolower(*p);
e = dcs_match(line);
t = dcs_match_type_id(e);
printf("--\n%sentry %d type %d - %s - %s\n", line,
e, t, dcs_type_mtd(t), dcs_type_name(t));
}
return 0;
}
/*
* Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
* Use only with permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "dcs_config.h"
#ifdef DEBUG_K_MATCH
#include <stdlib.h>
#endif
#include <errno.h>
#include "dcs_classifier.h"
#include "dcs_match.h"
#ifdef DEBUG_K_MATCH
#define p_entry(state, fmt, name) \
do { \
if (state.name ## _match_entry) { \
printf(fmt, #name, \
state.name ## _match_entry, \
dcs_type[dcs_entry[state.name ## _match_entry].type], \
dcs_entry[state.name ## _match_entry].key); \
} \
} while(0)
#define p_entry_if_changed(state, prev_match,fmt) \
do if (state.last_match_entry != prev_match) { \
p_entry(state, fmt, last); \
prev_match = state.last_match_entry; \
} while(0)
#else
#define p_entry(...) do { } while(0)
#define p_entry_if_changed(...) do { } while(0)
#endif
/*
* we deliberately return int instead of dcs_entry_id_t here in order to not
* require dcs_classifier.h for callers
*/
int /* dcs_entry_id_t */
dcs_match(const char *p) {
struct dcs_matchstate state;
#ifdef DEBUG_K_MATCH
dcs_entry_id_t prev_match = 0;
printf("\n--\n%s",p);
#endif
dcs_init_matchstate(&state);
while (*p) {
dcs_parse_subkey(&state, p);
p_entry_if_changed(state, prev_match, " %s match %d: %s - %s\n");
p++;
}
dcs_state_eval_candidates(&state);
p_entry_if_changed(state, prev_match, " new %s from candidates %d: %s - %s\n");
p_entry(state, " %s match %d: %s - %s\n", min);
p_entry(state, " %s match %d: %s - %s\n", first);
p_entry(state, " %s match %d: %s - %s\n", last);
return state.min_match_entry;
}
#define check_entry_id(entry_id, ret) \
do { \
if ((entry_id < 0) || (entry_id > (DCS_ENTRY_COUNT - 1))) { \
errno = EINVAL; \
return (ret); \
} \
} while(0)
int /* enum dcs_type */
dcs_match_type_id(int entry_id /* dcs_entry_id_t */) {
check_entry_id(entry_id, -1);
return dcs_entry[entry_id].type;
}
const char const *
dcs_match_key(int entry_id /* dcs_entry_id_t */) {
check_entry_id(entry_id, 0);
return dcs_entry[entry_id].key;
}
/*
* Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
* Use only with permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef DCS_MATCH_H
#define DCS_MATCH_H 1
int dcs_match(const char *p);
int dcs_match_type_id(int entry_id /* dcs_entry_id_t */);
const char const *dcs_match_key(int entry_id /* dcs_entry_id_t */);
#endif
/*
* Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
* Use only with permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "dcs_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include "gen/dcs_classifier.h" /* need DCS_* */
#include "dcs_match.h"
int
test (const char *fixup_remove_name, const char *fixup_reorder_name);
int
main (void) {
return test(NULL, NULL);
}
static void
test_p_diff (const char *label, int i, const char *testkey, int r) {
if (dcs_entry[i].type != dcs_entry[r].type) {
printf("%s\ti: %8d %s %s\ntype diff\tr: %8d %s %s\n",
label,
i, testkey, dcs_type[dcs_entry[i].type],
r, dcs_entry[r].key, dcs_type[dcs_entry[r].type]);
} else {
printf("%s\ti: %8d %s\n\t\tr: %8d %s\n",
label,
i, testkey,
r, dcs_entry[r].key);
}
}
int
test (const char *fixup_remove_name, const char *fixup_reorder_name) {
int i, r, errcount = 0;
FILE *f_remove, *f_reorder;
(void) fixup_remove_name;
(void) fixup_reorder_name;
(void) f_remove;
(void) f_reorder;
for (i = 0; i < DCS_ENTRY_COUNT; i++) {
if (dcs_matchstate_init.matchmask[i] == 0) {
r = dcs_match(dcs_entry[i].key);
if (i != r) {
test_p_diff("miss\t", i, dcs_entry[i].key, r);
errcount++;
}
} else {
#define KEYLIM 256
const char *poskey = dcs_entry[i].key;
const char *negkey = dcs_entry[i].key;
char p1[KEYLIM], p2[KEYLIM];
char n1[KEYLIM], n2[KEYLIM];
char *save;
if (poskey[0] == '!') {
poskey = strchr(poskey + 1, '*');
assert(poskey);
poskey++;
assert(*poskey);
negkey++;
}
if (strstr(poskey, "*!")) {
const char *pp, *np;
assert(strlen(poskey) < KEYLIM);
assert(strlen(negkey) < KEYLIM);
strcpy(p1, poskey);
strcpy(n1, negkey);
pp = strtok_r(p1, "*", &save);
*p2 = '\0';
poskey = p2;
while (pp) {
if (*pp != '!') {
strcat(p2, pp);
}
pp = strtok_r(NULL, "*", &save);
}
np = strtok_r(n1, "*", &save);
*n2 = '\0';
negkey = n2;
while (np) {
if (*np == '!')
np++;
strcat(n2, np);
np = strtok_r(NULL, "*", &save);
}
}
r = dcs_match(poskey);
if (i != r) {
test_p_diff("miss n-p", i, poskey, r);
errcount++;
}
r = dcs_match(negkey);
if (r == i) {
test_p_diff("miss n-n", i, negkey, r);
errcount++;
}
}
}
return errcount;
}
/*
* Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
* Use only with permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "dcs_config.h"
#include <errno.h>
#include "dcs_classifier.h"
#include "dcs_type.h"
#define check_type_id(type_id, ret) \
do { \
if ((type_id < 0) || (type_id > (DCS_TYPE_COUNT - 1))) { \
errno = EINVAL; \
return (ret); \
} \
} while(0)
const char *
dcs_type_name(int type_id /* enum dcs_type */) {
check_type_id(type_id, 0);
return dcs_type[type_id];
}
/*
* useful meta-classification to just three string constants:
*
*
*
*
*/
enum dcs_type_mtd {
T_MTD_MISSING = 0,
T_MTD_MOB,
T_MTD_TAB,
T_MTD_DSK
#define T_MTD_MAX T_MTD_DSK
};
const char * const dsc_type_mtd_str[T_MTD_MAX + 1] = {
[T_MTD_MISSING] = "dsk",
[T_MTD_MOB] = "mob",
[T_MTD_TAB] = "tab",
[T_MTD_DSK] = "dsk"
};
enum dcs_type dcs_type2mtd[DCS_TYPE_COUNT] = {
[NB_T_UNIDENTIFIED] = T_MTD_DSK,
[NB_T_BOT] = T_MTD_DSK,
[NB_T_CAMERA] = T_MTD_MOB,
[NB_T_CE_DEVICE] = T_MTD_MOB, // android 1.5; en-us; nimble
[NB_T_COMPUTER] = T_MTD_DSK, // macintosh*intel*mac os
[NB_T_DESKTOP_BROWSER] = T_MTD_DSK,
[NB_T_DEVTOOL] = T_MTD_DSK,
[NB_T_EREADER] = T_MTD_TAB,
[NB_T_MEDIAPLAYER] = T_MTD_MOB,
[NB_T_MOBILECONSOLE] = T_MTD_MOB,
[NB_T_MOBILE_BROWSER] = T_MTD_MOB,
[NB_T_MOBILE_PHONE] = T_MTD_MOB,
[NB_T_OPERATINGSYSTEM] = T_MTD_MOB, // ios 4.2
[NB_T_SETTOP_BOX_TV] = T_MTD_DSK,
[NB_T_TABLET] = T_MTD_TAB,
[NB_T_WEARABLE_COMPUTER] = T_MTD_MOB // android 4.0*glass
};
const char *
dcs_type_mtd(int type_id /* enum dcs_type */) {
check_type_id(type_id, 0);
return (dsc_type_mtd_str[dcs_type2mtd[type_id]]);
}
/*
* Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
* Use only with permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef DCS_TYPE_H
#define DCS_TYPE_H 1
const char * dcs_type_name(int type_id /* enum dcs_type */);
const char * dcs_type_mtd(int type_id /* enum dcs_type */);
#endif
/*
* Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
* Use only with permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* common code for varnish 2 (inline-C) and varnish 3 (vmod)
*
* this gets _INCLUDED_
*/
#include "dcs_classifier.c"
#include <ctype.h>
#include "dcs_match.c"
#include "dcs_type.c"
#define UA_LIMIT 1024
#define DCS_VARNISH2_NHDRS 4
const char * const hdrs[DCS_VARNISH2_NHDRS] = {
[0] = "\025X-OperaMini-Phone-UA:",
[1] = "\024X-Device-User-Agent:",
[2] = "\026X-Original-User-Agent:",
[3] = "\016X-Goog-Source:"
};
const char * const ua_prepend[DCS_VARNISH2_NHDRS] = {
[0] = " opera/ opera mini/ ",
[1] = NULL,
[2] = NULL,
[3] = NULL
};
#define appnd(w, space, r, l) \
l = strlen(r); \
strncpy(w, r, space); \
if (l > space) \
break; \
space -= l; \
w += l;
static int
dcs_varnish_classify(const struct sess *sp) {
const char *ua = VRT_GetHdr(sp, HDR_REQ, "\013User-Agent:");
const char *r;
char *w = NULL;
int i;
size_t l;
size_t space = UA_LIMIT;
char uabuf[space];
if ((! ua) || (! *ua))
return NB_T_UNIDENTIFIED;
if (VRT_GetHdr(sp, HDR_REQ, "\016x-wap-profile:"))
return NB_T_MOBILE_PHONE;
/* we need to copy to downcase the string for matching */
w = uabuf;
do {
appnd(w, space, ua, l);
} while(0);
ua = uabuf;
for (i = 0; i < DCS_VARNISH2_NHDRS; i++) {
r = VRT_GetHdr(sp, HDR_REQ, hdrs[i]);
if (r && *r) {
if (ua_prepend[i])
appnd(w, space, ua_prepend[i], l);
appnd(w, space, r, l);
}
}
uabuf[UA_LIMIT] = '\0';
assert(ua == uabuf);
assert(w > uabuf);
assert(w <= (uabuf + UA_LIMIT));
for (w = uabuf; *w; ++w) *w = tolower(*w);
return dcs_match(ua);
}
/*
* Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
* Use only with permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "dcs_config.h"
#include "dcs_varnish.c"
void
dcs_varnish2_classify_hdrs(const struct sess *sp) {
const int e = dcs_varnish_classify(sp);
const int t = dcs_match_type_id(e);
VRT_SetHdr(sp, HDR_REQ, "\020x-nb-classified:", dcs_type_name(t), vrt_magic_string_end);
VRT_SetHdr(sp, HDR_REQ, "\012x-variant:", dcs_type_mtd(t), vrt_magic_string_end);
}
# gen/Makefile.am
BUILT_SOURCES = dcs_classifier.c dcs_classifier.h
dcs_classifier.c dcs_classifier.h: ../gen_dcs_classifier.pl $(DCS_DBFILE)
../gen_dcs_classifier.pl $(DCS_DBFILE) $(DCS_KEY)
CLEANFILES = dcs_classifier.c dcs_classifier.h
This diff is collapsed.
# $Id$
varnishtest "Test dcs vmod"
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
import dcs from "${vmod_topbuild}/src/.libs/libvmod_dcs.so";
sub vcl_recv {
# this code will classify
#
# for best performance in production, only call classify
# once or use inline-C to save the return value of
# classify (int)
set req.http.x-nb-classified = dcs.type_name(dcs.classify());
set req.http.x-variant = dcs.type_mtd(dcs.classify());
error 200;
}
sub vcl_error {
set obj.http.x-nb-classified = req.http.x-nb-classified;
set obj.http.x-variant = req.http.x-variant;
synthetic {"classified ad here
"};
return (deliver);
}
} -start
client c1 {
# no User-Agent
txreq -url "/"
rxresp
expect resp.status == 200
expect resp.http.x-nb-classified == "unidentified"
expect resp.http.x-variant == "dsk"
} -run
client c1 {
txreq -hdr "user-agent: willgetignored" -hdr "x-wap-profile: anything"
rxresp
expect resp.status == 200
expect resp.http.x-nb-classified == "Mobile Phone"
expect resp.http.x-variant == "mob"
} -run
client c1 {
txreq -hdr "User-Agent: Opera/9.80 (Android; Opera Mini/19.0.1340/34.1309; U; de) Presto/2.8.119 Version/11.10" \
-hdr "X-OperaMini-Phone-UA: Mozilla/5.0 (Linux; U; Android 4.3; de-de; ME302C Build/JSS15Q) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"
rxresp
expect resp.status == 200
expect resp.http.x-nb-classified == "Mobile Phone"
expect resp.http.x-variant == "mob"
} -run
/*
* Copyright (c) 2014 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
* Use only with permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "dcs_config.h"
#include "vrt.h"
#include "vcc_if.h"
#include "dcs_varnish.c"
int
vmod_classify(struct sess *sp) {
return dcs_varnish_classify(sp);
}
const char *
vmod_entry_key(struct sess *sp, int e) {
(void) sp;
return dcs_match_key(e);
}
int
vmod_type_id(struct sess *sp, int e) {
(void) sp;
return dcs_match_type_id(e);
}
const char *
vmod_type_name(struct sess *sp, int e) {
const int t = dcs_match_type_id(e);
(void) sp;
return dcs_type_name(t > 0 ? t : 0);
}
const char *
vmod_type_mtd(struct sess *sp, int e) {
const int t = dcs_match_type_id(e);
(void) sp;
return dcs_type_mtd(t > 0 ? t : 0);
}
Module dcs
Function INT classify()
# all of these take the return value from classify()
Function STRING entry_key(INT)
Function INT type_id(INT)
Function STRING type_name(INT)
Function STRING type_mtd(INT)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment