Abstract in English

Updated July 2006: This text now describes centaurifax 1.0, a version that repairs a number of minor problems (including the use of netcat -q 10). The user authentication has been changed, a manual page was added and the software now comes as an installable package. It was tested on Debian Etch. Click here to see the down-load page.

Having a digital ISDN telephone connection lets you easily integrate Fax and Answering Machine functionality into your Linux server. SuSE (and Debian) distribute a package called Capisuite for this purpose. You will also need a supported ISDN card (an AVM Fritz card is inexpensive and works).

This text tries to give some advise of how to use Capisuite in a small business environment. A solution (shell script) to provide a simple networked FAX service for KDE is included. Although the remaining text is in german, the examples are commented in english:

To allow for more flexibility I suggest not to use real user-ids to configure Capisuite but special user ids like voice0, voice1, voice2, fax0 and fax1. Your mail system should then be used to map these special users to real users.

Zusammenfassung auf Deutsch

Aktualisiert im Juli 2006: Der Text beschreibt jetzt centaurifax 1.0, eine Version die eine Reihe kleinerer Probleme behebt (nunmehr unter Verwendung von netcat -q 10). Die Benutzerauthentifizierung wurde geändert, eine Manual Seite hinzugefügt und die Software kommt jetzt als installierbares Paket. Getestet wurde unter Debian Etch. Hier der Verweis zur Download Seite.

Wer über einen ISDN Telefonanschluss verfügt kann leicht Anrufbeantworter und FAX Funktionen in einen Linux Server einbinden. SuSE (und auch Debian) liefern zu diesem Zweck ein Paket namens Capisuite. Dazu wird noch eine unterstützte ISDN Karte benötigt (eine AVM Fritz Karte ist preisgünstig und funktioniert).

Dieser Text möchte einige praktische Ratschläge zur Benutzung von Capisuite in einem Kleinbetrieb geben. Insbesondere wird eine Lösung (Shell-Skript) für einen einfachen FAX Netzwerkdienst mit KDE vorgestellt.

Um eine grössere Flexibilität bei Einrichtung und Betrieb zu erhalten, wird Capisuite so konfiguriert dass anstelle von personenbezogenen Benutzerkonten folgende abstrakte Konten benutzt werden: voice0, voice1, voice2, fax0 und fax1. Die Verteilung der von Capisuite erzeugten E-Mails an die realen Personen wird durch Mappen der E-Mail Adressen im Mail Server besorgt (siehe /etc/aliases).

 

Die Konfiguration

Im Folgenden werden die Konfigurationsdateien kurz vorgestellt. Die Originaldateien enthalten wesentlich mehr Kommentare als die hier enthaltenen, gekürzten Versionen. An dieser Stelle wurden dafür praktische Hinweise eingefügt.

Nicht weiter eingegangen wird auf ein Problem mit der AVM Fritz Karte - den binären Treiber von AVM. Immerhin hat SuSE den Treiber in die Distributionen 9.x eingebunden und zumindest bis Kernel 2.6.16 (der aktuelle Stand zu diesem Zeitpunkt) kann der Treiber noch verwendet werden (siehe unten).

/etc/capisuite.conf

Neben einigen Hilfsprogrammen ist der wesentliche Teil von Capisuite mittels Python Skripts realisiert. Das erlaubt auch einfache Änderungen ohne Neukompilierung. Zum Beispiel sind die WAV Dateien, die normalerweise vom Anrufbeantworter per E-Mail verschickt werden, recht gross. Unter Linux sind OGG Dateien eventuell praktischer. Zur Umstellung werden in der Datei /usr/lib/python2.3/site-packages/cs_helpers.py einfach nur alle Vorkommnisse von "wav" nach "ogg" geändert.

Probleme: (1) die vorhandenen Skripts funktionieren nicht wenn die Telefonnummern "*" oder "#" enthalten - der Anrufbeantworter stürzt dann ab und Faxe werden nicht transportiert. (2) Leider werden die Protokoll- und Fehlermeldungen nicht ins syslog geschrieben.

# You will most likely not need to modify the original file of your installation. In
# the text below the original comments were removed and some extra info was added...

# the incoming script decides what to do with incoming calls
incoming_script="/usr/lib/capisuite/incoming.py"

# the idle script handles fax output
idle_script="/usr/lib/capisuite/idle.py"
idle_script_interval="30"

# You may eventually modify /usr/lib/python2.3/site-packages/cs_helpers.py to create
# smaller OGG files instead of WAV files for voice messages - just change wav to ogg

# log only some important messages (e.g. connection start/end)
log_level="1"
log_file="/var/log/capisuite.log"
log_error="/var/log/capisuite.error"

# use this for a simple home or small office ISDN connection...
DDI_length="0"
DDI_base_length="0"
DDI_stop_numbers=""

/etc/cronjob.conf

Aufräumen ist für die Praxis recht wichtig um Datenvermüllung zu verhindern - also nicht vergessen! Capisuite startet regelmässig einen Cronjob der das besorgen kann. Eventuell die Zeiten an die eigenen Vorstellungen anpassen...

# The configuration for the cron job in /etc/cron.daily/capisuite
# tells Capisuite to delete all spool files after 10 days ...
MAX_DAYS_RCVD=10
MAX_DAY_DONE=10
MAX_DAYS_FAILED=10

Achtung Debian Benutzer: Der cronjob wird nicht automatisch installiert. Die Datei findet sich im Dokumentationsverzeichnis unter examples.

/etc/answering_machine.conf

Hier ist zum ersten Mal richtig was zu konfigurieren. Zunächst wird die hoffentlich vorhandene Telefonanlage dazu gebracht externe MSN-Nummern an interne MSNs je nach Funktion umzuleiten.

Im Beispiel sind dies 21 für private Anrufe, 22 für geschäftliche Anrufe und 28 für Fernabfrage und Anrufweiterschaltung. Auf den internen Nummern 21 und 22 liegen in diesem Beispiel auch echte Telefone, 28 hat kein zugeordnetes Telefon. Ausserhalb der Bürozeiten werden von einem der Telefone alle Anrufe für 22 auf 28 umgeleitet.

Somit erhält ein geschäftlicher Anrufer zu Geschäftszeiten nach 40 Sekunden und ausserhalb der Geschäftszeiten sofort den Anrufbeantworter. Private Anrufer müssen es 60 Sekunden lang klingeln lassen um in den Genuss des Anrufbeantworters zu kommen. Vorschlag für ein erstklassiges Bürotelefon: Bang&Olufsen Beocom 3 ISDN.

Die hier benutzten abstrakten Konten voice0, voice1, voice2 und später fax0, fax1 können beim Anlegen ohne Passwort erstellt werden (sind also gesperrte Konten) weil sie nur intern benutzt werden. In der Datei /etc/aliases werden E-Mails an die abstrakten Konten einfach auf "echte" Benutzerkonten umgeleitet. Dazu bitte die Manual Page man:aliases lesen!

# These are some global defaults - see comments in the original file
[GLOBAL]
audio_dir="/usr/share/capisuite/"
voice_user_dir="/var/spool/capisuite/users/"
user_audio_files="0"
voice_delay="60"
announcement="announcement.la"
record_length="300"
record_silence_timeout="8"

# The telefone exchange is configured to deviler private calls to MSN 21 !
# The user voice0 is used for private messages (configure mail to deliver)
[voice0]
pin="1234"
voice_numbers="21"
voice_delay="60"
voice_action="MailAndSave"
fax_action="MailAndSave"

# Business calls get delivered to MSN 22 and user voice1 is used ...
[voice1]
pin="1234"
voice_numbers="22"
voice_delay="40"
voice_action="MailAndSave"
fax_action="MailAndSave"

# MSN 28 is for special purposes (remote access for example)
[voice2]
pin="1234"
voice_numbers="28"
voice_delay="1"
voice_action="MailAndSave"
fax_action="MailAndSave"

/etc/fax.conf

Auch beim FAX muss zunächst die Telefonanlage konfiguriert werden. Ein analoges Fax-Gerät wird z.B. auf der internen Nummer 17 betrieben, aber nach 15 Sekunden leitet die Anlage den Anruf auf MSN 27 um. Das passiert wenn das analoge FAX nicht betriebsbereit (oder besetzt) ist. Zudem wird die 27 direkt von einigen externen MSNs erreicht (für FAX Spam).

Neben den Einträgen in /etc/aliases (siehe oben) ist zu Beachten, dass die echten Benutzer, sofern sie das Recht erhalten sollen Faxe zu versenden, mit Konfigurationseinträgen versehen werden. Siehe Beispiel...

# These are some global defaults - see comments in the original file
[GLOBAL]
spool_dir="/var/spool/capisuite/"
fax_user_dir="/var/spool/capisuite/users/"
send_tries="5"
send_delays="60,60,60,300,300,3600,3600,18000,36000"
send_controller="1"
### this MSN may be interpreted by your telephone exchange...
outgoing_MSN="27"
outgoing_timeout="60"
dial_prefix=""
### put your number and name here...
fax_stationID="+49 9999 9999999"
fax_headline="Your Name"

# This is the default for incomming faxes, also ok for sending
[fax0]
fax_numbers="27"
fax_action="MailAndSave"

# Not assigned for incomming faxes but can be used for sending
[fax1]
fax_numbers=""
fax_action="MailAndSave"

# Real users must be listed here to allow them sending faxes
[user1]
fax_numbers=""
fax_action="MailAndSave"
[user2]
fax_numbers=""
fax_action="MailAndSave"

Jetzt kann die Konfiguration getestet werden. Nur für das Versenden von Faxen im Netzwerk reicht das mitgelieferte Programm capisuitefax zunächst nicht aus. Zur KDE-Integration und zum Arbeiten im Netzwerk siehe folgendes Kapitel.

Faxen im Netzwerk mit KDE

Network Fax Service: Das centaurifax Skript

Hier werden einfach zwei Teile gemischt, die aber von Leuten die KDE nicht benutzen sicher leicht wieder zu trennen sind: (1) Der KDE Fax Dialog KdePrintFax, der als Pseudodrucker aufgerufen wird (2) das Skript centaurifax um die Fax Daten zum Server zu schicken und den Status zurückzugeben.

KdePrintFax

Wer zur Druckausgabe "Fax versenden" auswählt ruft das genannte Programm auf. In dessen Dialog kann man nun den Empfänger eintragen. Leider wird Capisuite nicht direkt unterstützt. Um das Nachzureichen wird beim ersten Aufruf über das Menü "Einstellungen" der KdePrintFax Konfigurationsdialog aufgerufen. Nach den üblichen Eingaben von Name und Faxnummer wählen wir "System" als Unterseite. In der Combobox für "Fax System" wählen wir "Hylafax" (bzw. unter KDE 3.5.x "Other"). Und jetzt der Trick - im Feld "Kommando" tragen wir ein: /usr/local/bin/centaurifax alpha key %name %number %subject %files. Dabei ist key durch ein Schlüsselwort zu ersetzen das auf der Serverseite konfiguriert werden kann um den Benutzer zu authentifizieren. Im Fall von "Hylafax" bleibt das Feld "Fax Server" leer!

Die centaurifax Skriptdateien (hier zur Download Seite) werden installiert oder manuell nach /usr/local/bin kopiert und ausführbar gemacht (chmod 755 centaurifax*). Wenn KdePrintFax einmal korrekt konfiguriert ist, kann dessen Konfiguration (.kde/share/config/kdeprintfaxrc) allen KDE Benutzern zur Verfügung gestellt werden indem man es nach /opt/kde3/share/config kopiert und lesbar macht: chmod 644 kdeprintfaxrc.

Ein sehr einfacher Weg für Anwender um unter KDE 3.5.x centaurifax zu konfigurieren führt über den folgenden Aufruf aus einem Kommandofenster:

#Simple Client Setup, see "man centaurifax" for details.
# Replace 'myhost' with your hostname and 'mykey' with the actual
# authorization key for this user ...

centaurifax --setup  myhost mykey

xinetd konfigurieren

Als letzter Schritt wird centaurifax noch auf dem Server eingerichtet. (1) zuerst die Scriptdateien nach /usr/local/bin kopieren oder das Paket installieren und dann (2) in /etc/xinet.d/centaurifax einen neuen Eintrag anlegen, damit centaurifax auf dem Server gestartet wird wenn ein Client ein Fax senden will. Bitte auch (3) die berechtigten Benutzer in der oben beschriebenen fax.conf Datei anlegen!

Hylafax selber wird hier nicht benutzt und sollte auch nicht installiert sein! Die Programme centaurifax und capisuitefax treten anstelle von Hylafax. Gegebenenfalls muss noch das Progrämmchen netcat installiert werden - die Manual Page man:netcat ausprobieren um zu sehen ob es schon installiert ist.

Ein sehr einfacher Weg für Administratoren um centaurifax auf dem Server zu konfigurieren führt über den folgenden Aufruf aus einem Kommandofenster:

#Simple Server Setup, see "man centaurifax" for details.
# Please replace "one two" by a list of local authorization keys

centaurifax --setup --server --keys "one two" --int 00 --nat 0 --country 49

Eine xinetd Konfiguration würde dann z.B. so aussehen:

# file: /etc/xinet.d/centaurifax
# Centaurifax is a proxy/stub for capisuitefax. (c) Dr. J. Pfennig 2004-2006
# We use the hylafax tcp port (4559) to call the server!

service centaurifax
{
     disable         = no
     type            = unlisted
     socket_type     = stream
     protocol        = tcp
     port            = 4559
     wait            = no
     user            = root
     server          = /usr/local/share/centauritools/centaurifax
     server_args     = --server --keys "one two" --international 00 --national 0 --country 49
}

Die Beispielkonfiguration normalisiert Telefonvorwahlen (hier am Beispiel der deutschen Telekom). So wird u.A. die Vorwahl 004969 (wie sie z.B. das KDE Addressbuch liefern könnte) umgesetzt nach 069 (so wie es neuerdings im Netz der deutschen Telekom nötig ist).

Nach dem Restart von xinetd sollte es möglich sein von entsprechend konfigurierten Clients Faxe zu verschicken. Bei richtiger Konfiguration landen Bestätigungen oder Fehlermeldungen in der E-Mail des Absenders. Der restliche Text ist technischer Natur und beschreibt die Funktionsweise des Skripts bzw. wie der fritzcapi Kerneltreiber kompiliert wird.

Beschreibung der Funktionsweise von centaurifax

Wichtigste Teile sind das Programm netcat, das die Datenübertragung bewerkstelligt, xinetd auf dem Server um die Daten zu Empfangen und das von centaurifax implementierte Protokoll. Die eigentliche Faxfunktion bleibt dem capisuitefax Programm (aus Capisuite) überlassen.

Das Protokoll schaltet den Fax Daten einen Header von acht Textzeilen vor. Diese beginnen jeweils mit dem Schlüsselwort: KEY1, USER, NAME, DIAL, SUBJ, RES1, RES2 und RES3. Das Feld KEY1 (z.B. als Passwort oder Projektnummer) wird nur bei entsprechender Servereinstellung abgeprüft, darf aber nicht leer sein. Das Skript ist in mehrere Dateien aufgeteilt, wobei der Hauptteil (centaurifax) die alleinige Schnittstelle zur Benutzung bildet. Wenn auf der Serverseite das Programm capisuitefax einen Fehler meldet, wird der Fehlertext an KdePrintFax zurückgegeben und kann dort über das Protokollfenster angesehen werden.

Quellentext: centaurifax

#!/bin/bash

# Centaurifax is a proxy/stub to integrate capisuitefax with KDE.
# Copyright Dr. J. Pfennig 2004-2006. Published under BSD license.

# Who are we?
CF_NAME="${0##*/}"
CF_BASE="$(readlink -f $0)"

# We use the hylafax tcp port (4559) to call the server!
CF_PORT=4559

# parse the call line ...
declare CF_SVR CF_SET CF_KEY CF_INT CF_NAT CF_COU CF_REG

while [ -n "$1" ] ; do
   case "$1" in
   --set*)  CF_SET=1; shift ;;
   --ser*)  CF_SVR=1; shift ;;
   --cli*)  CF_SVR=0; shift ;;
   --key*)  CF_KEY="$2"; shift ; shift ;;
   --int*)  CF_INT="$2"; shift ; shift ;;
   --nat*)  CF_NAT="$2"; shift ; shift ;;
   --cou*)  CF_COU="$2"; shift ; shift ;;
   --reg*)  CF_REG="$2"; shift ; shift ;;
   --hel*)  CF_SVR= ; break ;;
   -*)      echo "$CF_NAME: unknow option '$1', try '--help'" ; exit 1 ;;
   *)       [ -z "$CF_SVR" ] && CF_SVR=0 ; break ;;
   esac
done

# call a worker ...
[ -n "$CF_SET" ] && . ${CF_BASE%/*}/centaurifax_setup
[ -z "$CF_SVR" ] && . ${CF_BASE%/*}/centaurifax_usage
# are we server or client?
[ "$CF_SVR" = 1 ] && . ${CF_BASE%/*}/centaurifax_server ||
                     . ${CF_BASE%/*}/centaurifax_client

# end

Quellentext: centaurifax_client

# This file gets called from centaurifax. If implements a proxy to
# call capisuite fax on a server ...

if [ "$#" != 6 ] ; then
    echo "usage:  $CF_NAME [--client] host[:port] key name dial subject postscriptfile"
    exit 1
fi

if [ ! -r "$6" ] ; then
    echo "$CF_NAME: Cannot read file: $6"
    exit 4
fi

PORT="${1#*:}" ; [ "$PORT" = "$1" ] && PORT="$CF_PORT"
HOST="${1%:*}" ; shift

RESULT=`(
    echo KEY1 "$1"; shift
    echo USER "$USER"
    echo NAME "$1"; shift
    echo DIAL "$1"; shift
    echo SUBJ "$1"; shift
    echo RES1
    echo RES2
    echo RES3
    cat $1 ) | netcat -q 10 -v $HOST $PORT`
if [ "$?" = 0 ] ; then
    echo "$RESULT"
    [ "`echo "$RESULT" | grep -o "STATUS: [0-9]*"`" = "STATUS: 0" ] && exit 0
    exit 3
fi
echo "$CF_NAME: Failed to submit job to $HOST:$PORT"
exit 2

Quellentext: centaurifax_server

# This file gets called from centaurifax. It should be launched using xinetd
# using a script that can be generated using "centaurifax --setup --server"

cd /tmp
umask 077
[ -d centaurifax ] || mkdir centaurifax
cd centaurifax
trap "rm -f $$_0[01]" 0
csplit --quiet --prefix $$_ - 9

while read arg val; do

    case "$arg" in
        KEY1)
            for i in ${CF_KEY//,/ } ; do
                [ "$i" = "$val" ] || continue
                KEY1="$val"; break
            done
            ;;
        USER)
            UNAM="$val"
            ;;
        NAME)
            NAME="${val:-(anonymous)}"
            ;;
        DIAL)
            DIAL=$(tr -d " ()-" <<<"$val")
            [ -n "$CF_INT" ] && DIAL=" ${DIAL/+/$CF_INT}"
            [ -n "$CF_NAT" ] && DIAL="${DIAL/ $CF_INT$CF_COU/ $CF_NAT}"
            [ -n "$CF_REG" ] && DIAL="${DIAL/ $CF_NAT$CF_REG/ }"
            ;;
        SUBJ)
            SUBJ="${val:-(none)}"
            ;;
        RES?)
            ;;
        *)
            echo "$CF_NAME: invalid request (unknown key: $arg)"
            exit 3

    esac
done < $$_00

if [ -z "$KEY1" -a -n "$CF_KEY" ] ; then
    sleep 5
    echo "$CF_NAME: invalid request (key missing or invalid: KEY1)"
    exit 3
fi
if [ -z "$UNAM" ] ; then
    echo "$CF_NAME: invalid request (value required: USER)"
    exit 3
fi

if [ -z "$DIAL" ] ; then
    echo "$CF_NAME: invalid request (value required: DIAL)"
    exit 3
fi


IFS=$'\t\n'
sep=$'\t'
capisuitefax${sep}-u${sep}$UNAM${sep}-A${sep}$NAME${sep}-S${sep}$SUBJ${sep}-d${sep}${DIAL/ /}${sep}$$_01
unset IFS
echo    STATUS: $?
unset IFS

Die Skripte ist einfach genug um Spielraum für weitere Ideen zu lassen. Viel Spass damit!

Den fritzcapi Treiber für 2.6.16 Kernel übersetzen

Die Quellentexte können aus dem SuSE 9.1 Paket oder von der AVM Web-Seite bezogen werden. Ab Kernel 2.6.16 ist eine kleine Änderung nötig. Verzweigen Sie dafür zum Verzeichnis Ihres Hardwaretyps (z.B. fritz.pci/src) und kommentieren Sie die Funktion atomic_xchg aus (Zeile 74-81):

# Do this only for Kernel 2.6.16 (or later) ...
/* begin comment
static inline unsigned long atomic_xchg (
        volatile atomic_t *     v,
        unsigned                value
) {
        return __xchg (value, &v->counter, sizeof (unsigned));
}
end comment */ /* atomic_xchg */

Möglicherweise sind die SuSE Makefiles für Debian anzupassen. Hier ein Beispiel (für fritz.pci):

# Main Make in the fritzcapi source root ...
# BEWARE: DO NOT COPY THIS - Makefiles rely on tab characters!
KERNELRELEASE = $(shell uname -r)
KERNEL_SOURCE := /lib/modules/$(KERNELRELEASE)/build

TARGETS := fritz.pci

all: modules

modules:
        set -e; for i in $(TARGETS); do \
                $(MAKE) KDIR=$(KERNEL_SOURCE) -C $$i/src ;\
        done

modules_install: install

install:
        set -e; for i in $(TARGETS); do \
                $(MAKE) KDIR=$(KERNEL_SOURCE) -C $$i/src install ;\
        done

clean:
        set -e; for i in $(TARGETS); do \
                $(MAKE) KDIR=$(KERNEL_SOURCE) -C $$i/src clean ;\
        done

Achtung Debian Benutzer: Das Sub Make z.B im Verzeichnis fritz.pci/src braucht eine kleine Änderung. Das SuSE Maketarget modules_add gibt es bei Debian nicht, man ändere es ggf. in modules_install! Zumindest unter Debian reichen dann die folgenden Zeilen um den Treiber zu kompilieren:

pushd fritzcapi/fritz.pci/src
make KDIR=/usr/src/linux
make KDIR=/usr/src/linux install
make KDIR=/usr/src/linux clean
popd