Changelog for HylaFAX
+* convert CIDName/CIDNumber to CallID (14 Feb 2005)
+* add MaxBatchJobs config option (10 Feb 2005)
* improve the way that external gettys are run
* fix some problems when decoding pipe fails in ECM
* ignore "echos" of the dialed number after dialing
* NEW FEATURES *
-* hfaxd security fix for hosts.hfaxd entries without
- passwords (CAN-2004-1182)
-* support for gcc v3.3 and libtiff v3.7
-* fax batching support
+* faxgetty can now utilize more than two call identification tags
* numerous other enhancements and bugfixes (see CHANGES)
* KNOWN ISSUES *
* INCOMPATIBILITIES *
+* Some of the CallID changes in this release required some reordering of
+ the command-line parameters with which the DynamicConfig scripts were
+ called.
+* TIFFs received prior to upgrading to this release will display their
+ CIDName and CIDNumber information reversed (CallID2, CallID1) when
+ examined with faxinfo.
* libtiff-3.6.1 is fatally flawed when dealing with Group 3 images.
Don't use it as-is.
See: http://bugs.hylafax.org/bugzilla/show_bug.cgi?id=500
Class2DCCQueryCmd: "!(0-1),(0-5),(0-2),(0-2),(0-1),(0),(0),(0-7)"
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: AT+VCID=1
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
# Class2Cmd: AT+FCLASS=2.1;+FRY=4
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: AT+VCID=1
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
ModemFlowControl: rtscts # seems to work better than xonxoff
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: "AT#CID=1"
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
Class2APQueryCmd: none # not available
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: "AT#CID=1"
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
# unfortunately, HylaFAX can't currently receive in MMR
ModemAnswerCmd: AT+FCC=,,,,1;A
# Class2RTFCC: yes
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: "AT#CID=1"
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
# unfortunately, HylaFAX can't currently receive in MMR
ModemAnswerCmd: AT+FCC=,,,,1;A
Class1TMConnectDelay: 400 # counteract quick CONNECT response
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: AT+VCID=1
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
# Or with the MT5634ZBA-DID you'll probably need something like...
# ModemReadyCmds: AT*DS1*DD0*DF1*DN4 # enable DTMF-DID, wink-start, 4 digits
-# CIDNumber: "DTMF" # format of AT*DF1
-# CIDNumberAnswerLength: 4 # four DTMF-DID digits then ATA
+# CallIDPattern: "DTMF" # format of AT*DF1
+# CallIDAnswerLength: 4 # four DTMF-DID digits then ATA
Class1TMConnectDelay: 400 # counteract quick CONNECT response
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: AT+VCID=1
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
# Or with the MT5634ZBA-DID you'll probably need something like...
# ModemReadyCmds: AT*DS1*DD0*DF1*DN4 # enable DTMF-DID, wink-start, 4 digits
-# CIDNumber: "DTMF" # format of AT*DF1
-# CIDNumberAnswerLength: 4 # four DTMF-DID digits then ATA
+# CallIDPattern: "DTMF" # format of AT*DF1
+# CallIDAnswerLength: 4 # four DTMF-DID digits then ATA
Class2CQCmd: AT+FCQ=1
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: AT+VCID=1
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
# Or with the MT5634ZBA-DID you'll probably need something like...
# ModemReadyCmds: AT*DS1*DD0*DF1*DN4 # enable DTMF-DID, wink-start, 4 digits
-# CIDNumber: "DTMF" # format of AT*DF1
-# CIDNumberAnswerLength: 4 # four DTMF-DID digits then ATA
+# CallIDPattern: "DTMF" # format of AT*DF1
+# CallIDAnswerLength: 4 # four DTMF-DID digits then ATA
# Class2Cmd: AT+FCLASS=2.0;+FRY=4
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: AT+VCID=1
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
# Or with the MT5634ZBA-DID you'll probably need something like...
# ModemReadyCmds: AT*DS1*DD0*DF1*DN4 # enable DTMF-DID, wink-start, 4 digits
-# CIDNumber: "DTMF" # format of AT*DF1
-# CIDNumberAnswerLength: 4 # four DTMF-DID digits then ATA
+# CallIDPattern: "DTMF" # format of AT*DF1
+# CallIDAnswerLength: 4 # four DTMF-DID digits then ATA
# Class2Cmd: AT+FCLASS=2.1;+FRY=4
# If your line supports Caller-ID, you may want to uncomment this...
-# QualifyCID: etc/cid # you must create this file
# ModemResetCmds: AT+VCID=1
-# CIDNumber: "NMBR="
-# CIDName: "NAME="
+# CallIDPattern: "NMBR="
+# CallIDPattern: "NAME="
# Or with the MT5634ZBA-DID you'll probably need something like...
# ModemReadyCmds: AT*DS1*DD0*DF1*DN4 # enable DTMF-DID, wink-start, 4 digits
-# CIDNumber: "DTMF" # format of AT*DF1
-# CIDNumberAnswerLength: 4 # four DTMF-DID digits then ATA
+# CallIDPattern: "DTMF" # format of AT*DF1
+# CallIDAnswerLength: 4 # four DTMF-DID digits then ATA
# Caller ID configuration setup; add AT*ID1 to ModemResetCmds
# to enable functionality (when supported by the local Telco).
#
-#QualifyCID: etc/cid # CID access control list file
-#CIDNumber: "CALLER NUMBER: " # pattern string for phone number info
-#CIDName: "CALLER NAME: " # pattern string for identity info
+#CallIDPattern: "CALLER NUMBER: " # pattern string for phone number info
+#CallIDPattern: "CALLER NAME: " # pattern string for identity info
#
# Caller ID configuration setup for Supra.
#
#QualifyCID: etc/cid # CID access control list file
-#CIDNumber: "NMBR = " # pattern string for phone number info
-#CIDName: "NAME = " # pattern string for identity info
+#CallIDPattern: "NMBR = " # pattern string for phone number info
+#CallIDPattern: "NAME = " # pattern string for identity info
# Caller ID configuration setup for Supra.
#
#QualifyCID: etc/cid # CID access control list file
-#CIDNumber: "NMBR = " # pattern string for phone number info
-#CIDName: "NAME = " # pattern string for identity info
+#CallIDPattern: "NMBR = " # pattern string for phone number info
+#CallIDPattern: "NAME = " # pattern string for identity info
#
#ModemResetCmds: "AT#CID=10" # enable ANI/DNIS reporting
#RingsBeforeAnswer: 2 # collect info between two RINGs
-#QualifyCID: etc/cid # CID access control list file
-#CIDNumber: "NMBR = " # pattern string for calling number
-#CIDName: "NDID = " # pattern string for called number
+#CallIDPattern: "NMBR = " # pattern string for calling number
+#CallIDPattern: "NDID = " # pattern string for called number
#
# T.38 dial modifiers
#
# Caller ID configuration setup.
#
-#QualifyCID: etc/cid # CID access control list file
-#CIDNumber: "CALLER NUMBER: " # pattern string for phone number info
-#CIDName: "CALLER NAME: " # pattern string for identity info
+#CallIDPattern: "CALLER NUMBER: " # pattern string for phone number info
+#CallIDPattern: "CALLER NAME: " # pattern string for identity info
#
PagerSetupCmds: AT&K0&N15 # use V.22 at 1200 bps (PageNet)
#
#
# Caller ID configuration setup.
#
-#QualifyCID: etc/cid # CID access control list file
-#CIDNumber: "CALLER NUMBER: " # pattern string for phone number info
-#CIDName: "CALLER NAME: " # pattern string for identity info
+#CallIDPattern: "CALLER NUMBER: " # pattern string for phone number info
+#CallIDPattern: "CALLER NAME: " # pattern string for identity info
#
PagerSetupCmds: AT&K0&N15 # use V.22 at 1200 bps (PageNet)
#
# Caller ID configuration setup.
#
-#QualifyCID: etc/cid # CID access control list file
-#CIDNumber: "CALLER NUMBER: " # pattern string for phone number info
-#CIDName: "CALLER NAME: " # pattern string for identity info
+#CallIDPattern: "CALLER NUMBER: " # pattern string for phone number info
+#CallIDPattern: "CALLER NAME: " # pattern string for identity info
#
PagerSetupCmds: AT&K0&N15 # use V.22 at 1200 bps (PageNet)
#
#
# Caller ID configuration setup.
#
-#QualifyCID: etc/cid # CID access control list file
-#CIDNumber: "CALLER NUMBER: " # pattern string for phone number info
-#CIDName: "CALLER NAME: " # pattern string for identity info
+#CallIDPattern: "CALLER NUMBER: " # pattern string for phone number info
+#CallIDPattern: "CALLER NAME: " # pattern string for identity info
#
PagerSetupCmds: AT&K0&N15 # use V.22 at 1200 bps (PageNet)
#
MANPAGES=\
man/Makefile.in \
- man/cid.4f \
+ man/callid.4f \
man/hylafax-config.4f \
man/destctrls.4f \
man/dialrules.4f \
}
bool
-ClassModem::waitForRings(u_short rings, CallType& type, CallerID& cid)
+ClassModem::waitForRings(u_short rings, CallType& type, CallID& callid)
{
bool gotring = false;
u_int i = 0, count = 0;
if (count++ == 0) break; //discard initial DROFF code if present
incadence[i++] = -atoi(rbuf + conf.dringOff.length());
break;
- }
- else if (conf.dringOn.length() && strneq(conf.dringOn, rbuf, conf.dringOn.length())) {
+ } else if (conf.dringOn.length() && strneq(conf.dringOn, rbuf, conf.dringOn.length())) {
++count;
incadence[i++] = atoi(rbuf + conf.dringOn.length());
break;
- }
- else {
+ } else {
if (conf.ringExtended.length() && strneq(rbuf, conf.ringExtended, conf.ringExtended.length())) // extended RING
gotring = true;
- conf.parseCID(rbuf, cid);
+ conf.parseCallID(rbuf, callid);
/* DID modems may send DID data in lieu of RING */
- if ((cid.name.length() >= conf.cidNameAnswerLength &&
- conf.cidNameAnswerLength > 0) ||
- (cid.number.length() >= conf.cidNumberAnswerLength &&
- conf.cidNumberAnswerLength > 0))
- gotring = true;
+ for (int i = 0; i < conf.idConfig.length(); i++) {
+ if (conf.idConfig[i].answerlength && callid.length(i) >= conf.idConfig[i].answerlength)
+ gotring = true;
+ }
break;
}
/* fall thru... */
atCmd(conf.ringResponse, AT_NOTHING);
ATResponse r;
time_t ringstart = Sys::now();
- bool cidwasempty = cid.number.length() == 0 || cid.name.length() == 0;
+ bool callidwasempty = true;
+ for (int i = 0; callidwasempty && i < callid.size(); i++)
+ if (callid.length(i) )
+ callidwasempty = false;
do {
r = atResponse(rbuf, 3000);
- if (r == AT_OTHER && cidwasempty) {
+ if (r == AT_OTHER && callidwasempty) {
/*
* Perhaps a modem will repeat CID/DID info for us
* with AT+VRID if we missed it before.
*/
- conf.parseCID(rbuf, cid);
+ conf.parseCallID(rbuf, callid);
}
} while (r != AT_OK && (Sys::now()-ringstart < 3));
- if (conf.cidNumber == "SHIELDED_DTMF") { // retrieve DID, e.g. via voice DTMF
- ringstart = Sys::now();
- do {
- int c = server.getModemChar(5000);
- if (c == 0x10) c = server.getModemChar(5000);
- if (c == 0x23 || c == 0x2A || (c >= 0x30 && c <= 0x39)) {
- // a DTMF digit was received...
- protoTrace("MODEM HEARD DTMF: %c", c);
- cid.number.append(fxStr::format("%c", c));
- }
- } while (cid.number.length() < conf.cidNumberAnswerLength && (Sys::now()-ringstart < 10));
- u_char buf[2];
- buf[0] = DLE; buf[1] = ETX;
- if (!putModem(buf, 2, 3000))
- return (false);
+ for (int i = 0 ; i < conf.idConfig.length(); i++) {
+ if (conf.idConfig[i].pattern == "SHIELDED_DTMF") { // retrieve DID, e.g. via voice DTMF
+ ringstart = Sys::now();
+ do {
+ int c = server.getModemChar(5000);
+ if (c == 0x10) c = server.getModemChar(5000);
+ if (c == 0x23 || c == 0x2A || (c >= 0x30 && c <= 0x39)) {
+ // a DTMF digit was received...
+ protoTrace("MODEM HEARD DTMF: %c", c);
+ callid[i].append(fxStr::format("%c", c));
+ }
+ } while (callid.length(i) < conf.idConfig[i].answerlength && (Sys::now()-ringstart < 10));
+ u_char buf[2];
+ buf[0] = DLE; buf[1] = ETX;
+ if (!putModem(buf, 2, 3000))
+ return (false);
+ }
}
}
if (conf.dringOn.length()) { // Compare with all distinctive ring cadences
*/
#include <stdarg.h>
#include "Str.h"
+#include "CallID.h"
class ModemServer;
class ModemConfig;
CallType type; // resultant call type
} AnswerMsg;
-typedef struct {
- fxStr number; // caller's phone number
- fxStr name; // caller's identity
-} CallerID;
-
/*
* AT command escape codes. Command strings specified in the
* modem configuration file are parsed and embedded commands
* with recvAbort available to abort a receive
* at any time in this procedure.
*/
- virtual bool waitForRings(u_short rings, CallType&, CallerID&);
+ virtual bool waitForRings(u_short rings, CallType&, CallID&);
virtual CallType answerCall(AnswerType, fxStr& emsg, const char* dialnumber = NULL);
virtual void answerCallCmd(CallType);
};
* Record an activity in the transfer log file.
*/
bool
-FaxAcctInfo::record(const char* cmd) const
+FaxAcctInfo::record(const char* cmd)
{
bool ok = false;
int fd = Sys::open(FAX_XFERLOG, O_RDWR|O_CREAT|O_APPEND, 0644);
record.fput("\t%s", fmtTime(duration)); // $12 = duration
record.fput("\t%s", fmtTime(conntime)); // $13 = conntime
record.fput("\t\"%s\"", status); // $14 = status
- record.fput("\t\"%s\"", cidname); // $15 = CIDName
- record.fput("\t\"%s\"", cidnumber); // $16 = CIDNumber
- record.fput("\t\"%s\"", owner); // $17 = owner
+ record.fput("\t\"%s\"", callid.size() > CallID::NAME ? (const char*) callid[1] : ""); // $15 = CallID2/CIDName
+ record.fput("\t\"%s\"", callid.size() > CallID::NUMBER ? (const char*) callid[0] : ""); // $16 = CallID1/CIDNumber
+ fxStr callid_formatted = "";
+ for (int i = 2; i < callid.size(); i++) {
+ if (i > 2) callid_formatted.append("::");
+ callid_formatted.append(callid[i]);
+ }
+ record.fput("\t\"%s\"", (const char*) callid_formatted); // $17 = CallID3 -> CallIDn
+ record.fput("\t\"%s\"", owner); // $18 = owner
record.put('\n');
flock(fd, LOCK_EX);
ok = (Sys::write(fd, record, record.getLength()) == (ssize_t)record.getLength());
#define _FaxAcctInfo_
#include "Types.h"
+#include "CallID.h"
#include <time.h>
struct FaxAcctInfo {
u_int npages; // pages successfully sent/rcvd
u_int params; // encoded transfer parameters
const char* status; // status info (optional)
- const char* cidname; // caller id name
- const char* cidnumber; // caller id number
+ CallID callid; // call identification
const char* owner; // job owner (uid)
- bool record(const char* cmd) const;
+ bool record(const char* cmd);
};
#endif /* _FaxAcctInfo_ */
recvPages = 0; // count of received pages
fileStart = Sys::now(); // count initial negotiation on failure
if (modem->pollBegin(canonicalizePhoneNumber(FAXNumber), sep, pwd, emsg)) {
- const CallerID cid; // null
pollOK = recvDocuments(tif, info, docs, emsg);
if (!pollOK)
traceProtocol("POLL FAX: %s", (const char*) emsg);
* result of a poll request.
*/
void
-FaxServer::notifyPollRecvd(FaxRequest&, const FaxRecvInfo&)
+FaxServer::notifyPollRecvd(FaxRequest&, FaxRecvInfo&)
{
}
*/
bool
-FaxServer::recvFax(const CallerID& cid, fxStr& emsg)
+FaxServer::recvFax(const CallID& callid, fxStr& emsg)
{
traceProtocol("RECV FAX: begin");
* after recvBegin can cause part of the first page to
* be lost.)
*/
- info.cidname = cid.name;
- info.cidnumber = cid.number;
+ info.callid = callid;
TIFF* tif = setupForRecv(info, docs, emsg);
if (tif) {
recvPages = 0; // total count of received pages
* cause timing problems).
*/
for (u_int i = 0, n = docs.length(); i < n; i++) {
- const FaxRecvInfo& ri = docs[i];
+ FaxRecvInfo& ri = docs[i];
if (ri.npages == 0)
Sys::unlink(ri.qfile);
else
FaxServer::recvFaxPhaseD(TIFF* tif, FaxRecvInfo& info, u_int& ppm, fxStr& emsg)
{
fxStr id = info.sender;
- if (info.cidname.length() || info.cidnumber.length()) id.append("\n" | info.cidname);
- if (info.cidnumber.length()) id.append("\n" | info.cidnumber);
-
+ for (int i = 0; i < info.callid.size(); i++) {
+ id.append('\n');
+ id.append(info.callid[i]);
+ }
do {
if (++recvPages > maxRecvPages) {
emsg = "Maximum receive page count exceeded, job terminated";
}
void
-FaxServer::notifyRecvBegun(const FaxRecvInfo&)
+FaxServer::notifyRecvBegun(FaxRecvInfo&)
{
}
* Handle notification that a page has been received.
*/
void
-FaxServer::notifyPageRecvd(TIFF*, const FaxRecvInfo& ri, int)
+FaxServer::notifyPageRecvd(TIFF*, FaxRecvInfo& ri, int)
{
traceServer("RECV FAX (%s): from %s, page %u in %s, %s, %s, %s, %s"
, (const char*) ri.commid
* Handle notification that a document has been received.
*/
void
-FaxServer::notifyDocumentRecvd(const FaxRecvInfo& ri)
+FaxServer::notifyDocumentRecvd(FaxRecvInfo& ri)
{
traceServer("RECV FAX (%s): %s from %s, route to %s, %u pages in %s"
, (const char*) ri.commid
* Handle final actions associated with a document being received.
*/
void
-FaxServer::notifyRecvDone(const FaxRecvInfo& ri)
+FaxServer::notifyRecvDone(FaxRecvInfo& ri)
{
if (ri.reason != "")
traceServer("RECV FAX (%s): session with %s terminated abnormally: %s"
fax.status = (pollFaxPhaseB(freq.addr, freq.item, docs, fax.notice) ?
send_done : send_retry);
for (u_int j = 0; j < docs.length(); j++) {
- const FaxRecvInfo& ri = docs[j];
+ FaxRecvInfo& ri = docs[j];
if (ri.npages > 0) {
Sys::chmod(ri.qfile, recvFileMode);
notifyPollRecvd(fax, ri);
void setLocalIdentifier(const fxStr& lid);
void sendFax(FaxRequest&, FaxMachineInfo&, FaxAcctInfo&, u_int&);
- bool recvFax(const CallerID& cid, fxStr& emsg);
+ bool recvFax(const CallID& callid, fxStr& emsg);
time_t getFileTransferTime() const;
time_t getPageTransferTime() const;
virtual void notifyConnected(const FaxRequest&);
virtual void notifyPageSent(FaxRequest&, const char*);
virtual void notifyDocumentSent(FaxRequest&, u_int index);
- virtual void notifyPollRecvd(FaxRequest&, const FaxRecvInfo&);
+ virtual void notifyPollRecvd(FaxRequest&, FaxRecvInfo&);
virtual void notifyPollDone(FaxRequest&, u_int index);
- virtual void notifyRecvBegun(const FaxRecvInfo&);
- virtual void notifyPageRecvd(TIFF* tif, const FaxRecvInfo&, int ppm);
- virtual void notifyDocumentRecvd(const FaxRecvInfo& req);
- virtual void notifyRecvDone(const FaxRecvInfo& req);
+ virtual void notifyRecvBegun(FaxRecvInfo&);
+ virtual void notifyPageRecvd(TIFF* tif, FaxRecvInfo&, int ppm);
+ virtual void notifyDocumentRecvd(FaxRecvInfo& req);
+ virtual void notifyRecvDone(FaxRecvInfo& req);
public:
virtual ~FaxServer();
{ "ringfax", &ModemConfig::ringFax },
{ "ringvoice", &ModemConfig::ringVoice },
{ "ringextended", &ModemConfig::ringExtended },
-{ "cidname", &ModemConfig::cidName },
-{ "cidnumber", &ModemConfig::cidNumber },
{ "dringon", &ModemConfig::dringOn },
{ "dringoff", &ModemConfig::dringOff },
};
{ "faxt1timer", &ModemConfig::t1Timer, TIMER_T1 },
{ "faxt2timer", &ModemConfig::t2Timer, TIMER_T2 },
{ "faxt4timer", &ModemConfig::t4Timer, TIMER_T4 },
-{ "cidnumberanswerlength", &ModemConfig::cidNumberAnswerLength, 0 },
-{ "cidnameanswerlength", &ModemConfig::cidNameAnswerLength, 0 },
{ "modemdialresponsetimeout", &ModemConfig::dialResponseTimeout, 3*60*1000},
{ "modemanswerresponsetimeout", &ModemConfig::answerResponseTimeout, 3*60*1000},
{ "modempagestarttimeout", &ModemConfig::pageStartTimeout, 3*60*1000},
saveUnconfirmedPages = true; // keep unconfirmed pages
softRTFCC = true; // real-time fax comp. conv. (software)
noAnswerVoice = false; // answer voice calls
+
+ idConfig.resize(0);
+ callidIndex = (u_int) -1;
}
void
}
void
-ModemConfig::parseCID(const char* rbuf, CallerID& cid) const
+ModemConfig::parseCallID(const char* rbuf, CallID& callid) const
{
- if (cidName.length() && strneq(rbuf, cidName, cidName.length()))
- cid.name = cid.name | rbuf+cidName.length();
- if (cidNumber.length() && strneq(rbuf, cidNumber, cidNumber.length()))
- cid.number = cid.number | rbuf+cidNumber.length();
+ for (size_t i = 0; i < idConfig.length(); i++) {
+ fxAssert(i < callid.size(), "Miss matched Call ID Size with parsing");
+ const fxStr& pat = idConfig[i].pattern;
+ if (pat.length() && strneq(rbuf, pat, pat.length()))
+ callid[i].append(rbuf+pat.length());
+ }
}
void
saveUnconfirmedPages = getBoolean(value);
else if (streq(tag, "distinctiverings"))
parseDR(value);
- else
+ else if (streq(tag, "callidpattern") || streq(tag, "callidanswerlength") ) {
+ if (tag[6] == 'p') callidIndex++; // only increment on instances of "Pattern"
+ if (idConfig.length() < callidIndex+1 && callidIndex != (u_int) -1)
+ idConfig.resize(callidIndex+1);
+ if (tag[6] == 'p') {
+ idConfig[callidIndex].pattern = value;
+ configTrace("CallID[%d].pattern = \"%s\"", callidIndex,
+ (const char*)idConfig[callidIndex].pattern);
+ } else {
+ if (callidIndex != (u_int) -1) {
+ idConfig[callidIndex].answerlength = atoi(value);
+ configTrace("CallID[%d].answerlength = %d", callidIndex,
+ idConfig[callidIndex].answerlength);
+ } else
+ configError("No index for Call ID Answer Length");
+ }
+ } else if (streq(tag, "cidnumber")) {
+ if (idConfig.length() < CallID::NUMBER+1)
+ idConfig.resize(CallID::NUMBER+1);
+ idConfig[CallID::NUMBER].pattern = value;
+ } else if (streq(tag, "cidname")) {
+ if (idConfig.length() < CallID::NAME+1)
+ idConfig.resize(CallID::NAME+1);
+ idConfig[CallID::NAME].pattern = value;
+ } else if (streq(tag, "cidnumberanswerlength")) {
+ if (idConfig.length() < CallID::NUMBER+1)
+ idConfig.resize(CallID::NUMBER+1);
+ idConfig[CallID::NUMBER].answerlength = getNumber(value);
+ } else if (streq(tag, "cidnameanswerlength")) {
+ if (idConfig.length() < CallID::NAME+1)
+ idConfig.resize(CallID::NAME+1);
+ idConfig[CallID::NAME].answerlength = getNumber(value);
+ } else
return (false);
return (true);
}
#undef N
+
+fxIMPLEMENT_ObjArray(IDConfArray, id_config);
#include "FaxConfig.h"
#include "FaxModem.h"
+#include "Array.h"
+
+class id_config
+{
+ public:
+ fxStr pattern;
+ int answerlength;
+
+ int compare (const id_config* n) const
+ {
+ return ::compare(pattern, n->pattern);
+ }
+
+};
+
+fxDECLARE_ObjArray(IDConfArray, id_config);
+
struct ModemConfig : public FaxConfig {
private:
BaudRate getRate(const char*);
virtual void configError(const char* fmt, ...) = 0;
virtual void configTrace(const char* fmt, ...) = 0;
fxStr parseATCmd(const char*);
+
+ u_int callidIndex; // call id index
public:
fxStr type; // modem type
fxStr resetCmds; // extra modem reset commands for start of initialization
fxStr dringOn; // pattern for distinctive ring silence interval
fxStr dringOff; // pattern for distinctive ring ring interval
bool noAnswerVoice; // leave voice calls unanswered
- // caller id
- fxStr cidName; // pattern for name info
- fxStr cidNumber; // pattern for number info
- u_int cidNameAnswerLength; // answer when CID received
- u_int cidNumberAnswerLength; // answer when CID received
+ // call identification
+ IDConfArray idConfig; // pattern for ID info
// protocol timers
u_int t1Timer; // T.30 T1 timer (ms)
u_int t2Timer; // T.30 T2 timer (ms)
virtual ~ModemConfig();
- void parseCID(const char*, CallerID&) const;
+ void parseCallID(const char*, CallID&) const;
const fxStr& getFlowCmd(FlowControl) const;
void parseDR(const char*);
void processDRString(char*, const u_int);
bool ModemServer::serverBusy() const
{ return state != RUNNING; }
-bool ModemServer::modemWaitForRings(u_short rings, CallType& type, CallerID& cid)
- { return modem->waitForRings(rings, type, cid); }
+bool ModemServer::modemWaitForRings(u_short rings, CallType& type, CallID& callid)
+ { return modem->waitForRings(rings, type, callid); }
CallType ModemServer::modemAnswerCall(AnswerType atype, fxStr& emsg, const char* dialnumber)
{ return modem->answerCall(atype, emsg, dialnumber); }
void ModemServer::modemAnswerCallCmd(CallType ctype)
bool setInputBuffering(bool on);
bool modemStopOutput();
// modem driver interfaces
- bool modemWaitForRings(u_short rings, CallType&, CallerID&);
+ bool modemWaitForRings(u_short rings, CallType&, CallID&);
CallType modemAnswerCall(AnswerType, fxStr&, const char* dialnumber = NULL);
void modemAnswerCallCmd(CallType);
void modemFlushInput();
changeState(LISTENING);
sendModemStatus("B");
ringsHeard = 0;
- received_cid.name = "";
- received_cid.number = "";
listenForRing();
} else if (state != SENDING && state != ANSWERING && state != RECEIVING) {
/*
do {
CallType ctype = ClassModem::CALLTYPE_UNKNOWN;
- CallerID cid;
+ CallID callid(idConfig.length());
again = false;
- if (modemWaitForRings(ringsHeard, ctype, cid)) {
- if (cid.number != "" || cid.name != "") {
- received_cid = cid; // CNID is only sent once. Store it
- // for answering after later RINGs.
- traceServer("ANSWER: CID NUMBER \"%s\" NAME \"%s\"",
- (const char*) received_cid.number, (const char*) received_cid.name);
- faxApp::sendModemStatus(getModemDeviceID(), "C\"%s\"%s\"",
- (const char*) received_cid.number, (const char*) received_cid.name);
+ if (modemWaitForRings(ringsHeard, ctype, callid)) {
+ if (! callid.isEmpty()) {
+ received_callid = callid; // CNID is only sent once. Store it
+ // for answering after later RINGs.
+ fxStr send;
+ for (int i = 0; i < received_callid.size(); i++) {
+ if (i) send.append(',');
+ send.append("\"" | received_callid[i] | "\"");
+ traceServer("ANSWER: Call ID %d \"%s\"", i+1, received_callid.id(i));
+ }
+ faxApp::sendModemStatus(getModemDeviceID(), "C%s", (const char*) send);
}
++ringsHeard;
if (dringOn.length() && ctype == ClassModem::CALLTYPE_UNKNOWN) --ringsHeard;
// distinctive ring failed to identify - get another ring
/* DID modems may only signal a call with DID data - no RING */
- if (ringsBeforeAnswer && (ringsHeard >= ringsBeforeAnswer) ||
- (cid.name.length() >= cidNameAnswerLength &&
- cidNameAnswerLength > 0) ||
- (cid.number.length() >= cidNumberAnswerLength &&
- cidNumberAnswerLength > 0))
- answerPhone(ClassModem::ANSTYPE_ANY, ctype, received_cid);
+ bool done = false;
+ for (int i = 0; i < callid.size(); i++) {
+ if (idConfig[i].answerlength > 0 && callid[i].length() >= idConfig[i].answerlength) {
+ done = true;
+ break;
+ }
+ }
+ if (done || ringsBeforeAnswer && (ringsHeard >= ringsBeforeAnswer))
+ answerPhone(ClassModem::ANSTYPE_ANY, ctype, received_callid);
else if (isModemInput())
again = true;
else
void
faxGettyApp::answerPhoneCmd(AnswerType atype, const char* dialnumber)
{
- CallerID cid;
CallType ctype = ClassModem::CALLTYPE_UNKNOWN;
if (state == LISTENING) {
/*
* cancel any timeout and answer the call.
*/
Dispatcher::instance().stopTimer(&answerHandler);
- answerPhone(atype, ctype, received_cid, dialnumber);
+ answerPhone(atype, ctype, received_callid, dialnumber);
} else if (lockModem()) {
/*
* The modem is ours, notifier the queuer and answer.
*/
sendModemStatus("B");
- answerPhone(atype, ctype, received_cid, dialnumber);
+ answerPhone(atype, ctype, received_callid, dialnumber);
} else if (state != ANSWERING && state != RECEIVING) {
/*
* The modem is in use to call out, or some other process
* user (sending an "ANSWER" command through the FIFO).
*/
void
-faxGettyApp::answerPhone(AnswerType atype, CallType ctype, const CallerID& cid, const char* dialnumber)
+faxGettyApp::answerPhone(AnswerType atype, CallType ctype, const CallID& callid, const char* dialnumber)
{
changeState(ANSWERING);
beginSession(FAXNumber);
ai.start = Sys::now();
ai.device = getModemDeviceID();
ai.dest = getModemNumber();
- ai.cidname = cid.name;
- ai.cidnumber = cid.number;
+ ai.callid = callid;
ai.npages = 0;
ai.params = 0;
ai.csi = "";
bool callResolved;
bool advanceRotary = true;
fxStr emsg;
- if (!isCIDOk(cid.number)) { // check Caller ID if present
+ if (!isCIDOk(callid.size() > CallID::NUMBER ? callid.id(CallID::NUMBER) : "")) { // check Caller ID if present
/*
* Call was rejected based on Caller ID information.
*/
advanceRotary = false;
} else {
if (dynamicConfig.length()) {
- fxStr cmd(dynamicConfig | quote | cid.name | enquote |
- quote | cid.number | enquote | quote | getModemDevice() | enquote);
+ fxStr cmd(dynamicConfig | quote | getModemDevice() | enquote);
+ for (int i = 0; i < callid.size(); i++)
+ cmd.append(quote | callid.id(i) | enquote);
fxStr localid = "";
int pipefd[2], idlength, status;
char line[1024];
// NB: answer based on ctype, not atype
if (!(noAnswerVoice && ctype == ClassModem::CALLTYPE_VOICE))
ctype = modemAnswerCall(ctype, emsg, dialnumber);
- callResolved = processCall(ctype, emsg, cid);
+ callResolved = processCall(ctype, emsg, callid);
}
} else if (atype == ClassModem::ANSTYPE_ANY) {
/*
*/
int r = answerRotor;
do {
- callResolved = answerCall(answerRotary[r], ctype, emsg, cid, dialnumber);
+ callResolved = answerCall(answerRotary[r], ctype, emsg, callid, dialnumber);
r = (r+1) % answerRotorSize;
} while (!callResolved && adaptiveAnswer && r != answerRotor);
} else {
* any existing call type information such as
* distinctive ring.
*/
- callResolved = answerCall(atype, ctype, emsg, cid, dialnumber);
+ callResolved = answerCall(atype, ctype, emsg, callid, dialnumber);
}
}
/*
modemHangup();
discardModem(true);
}
+
+ for (int i = 0; i < received_callid.size(); i++)
+ received_callid[i].resize(0);
+
bool isSetup;
if (isModemLocked() || lockModem()) {
isSetup = setupModem();
* the modem layer arrives at as the call type.
*/
bool
-faxGettyApp::answerCall(AnswerType atype, CallType& ctype, fxStr& emsg, const CallerID& cid, const char* dialnumber)
+faxGettyApp::answerCall(AnswerType atype, CallType& ctype, fxStr& emsg, const CallID& callid, const char* dialnumber)
{
bool callResolved;
if (atype == ClassModem::ANSTYPE_EXTERN) {
* then we take action based on the returned call type.
*/
ctype = runGetty("EXTERN GETTY", OSnewEGetty,
- egettyArgs, emsg, lockExternCalls, cid, true);
+ egettyArgs, emsg, lockExternCalls, callid, true);
if (ctype == ClassModem::CALLTYPE_DONE) // NB: call completed
return (true);
if (ctype != ClassModem::CALLTYPE_ERROR)
emsg = "External getty use is not permitted";
} else
ctype = modemAnswerCall(atype, emsg, dialnumber);
- callResolved = processCall(ctype, emsg, cid);
+ callResolved = processCall(ctype, emsg, callid);
return (callResolved);
}
* to recondition the modem for incoming calls (if configured).
*/
bool
-faxGettyApp::processCall(CallType ctype, fxStr& emsg, const CallerID& cid)
+faxGettyApp::processCall(CallType ctype, fxStr& emsg, const CallID& callid)
{
bool callHandled = false;
);
changeState(RECEIVING);
sendRecvStatus(getModemDeviceID(), "B");
- callHandled = recvFax(cid, emsg);
+ callHandled = recvFax(callid, emsg);
sendRecvStatus(getModemDeviceID(), "E");
break;
case ClassModem::CALLTYPE_DATA:
traceServer("ANSWER: DATA CONNECTION");
if (gettyArgs != "") {
sendModemStatus("d");
- runGetty("GETTY", OSnewGetty, gettyArgs, emsg, lockDataCalls, cid);
+ runGetty("GETTY", OSnewGetty, gettyArgs, emsg, lockDataCalls, callid);
sendModemStatus("e");
} else
traceServer("ANSWER: Data connections are not permitted");
traceServer("ANSWER: VOICE CONNECTION");
if (vgettyArgs != "") {
sendModemStatus("v");
- runGetty("VGETTY", OSnewVGetty, vgettyArgs, emsg, lockVoiceCalls, cid);
+ runGetty("VGETTY", OSnewVGetty, vgettyArgs, emsg, lockVoiceCalls, callid);
sendModemStatus("w");
} else
traceServer("ANSWER: Voice connections are not permitted");
const char* args,
fxStr& emsg,
bool keepLock,
- const CallerID& cid,
+ const CallID& callid,
bool keepModem
)
{
emsg = fxStr::format("%s: could not create", what);
return (ClassModem::CALLTYPE_ERROR);
}
- getty->setupArgv(args, cid.name, cid.number);
+ getty->setupArgv(args,
+ callid.size() > CallID::NUMBER ? callid.id(CallID::NUMBER) : "",
+ callid.size() > CallID::NAME ? callid.id(CallID::NAME) : "");
/*
* The getty process should not inherit the lock file.
* Remove it here before the fork so that our state is
}
void
-faxGettyApp::notifyRecvBegun(const FaxRecvInfo& ri)
+faxGettyApp::notifyRecvBegun(FaxRecvInfo& ri)
{
(void) sendRecvStatus(getModemDeviceID(), "S%s", (const char*) ri.encode());
* Handle notification that a page has been received.
*/
void
-faxGettyApp::notifyPageRecvd(TIFF* tif, const FaxRecvInfo& ri, int ppm)
+faxGettyApp::notifyPageRecvd(TIFF* tif, FaxRecvInfo& ri, int ppm)
{
(void) sendRecvStatus(getModemDeviceID(), "P%s", (const char*) ri.encode());
* Handle notification that a document has been received.
*/
void
-faxGettyApp::notifyDocumentRecvd(const FaxRecvInfo& ri)
+faxGettyApp::notifyDocumentRecvd(FaxRecvInfo& ri)
{
(void) sendRecvStatus(getModemDeviceID(), "D%s", (const char*) ri.encode());
ai.status = ri.reason;
ai.jobid = "";
ai.jobtag = "";
- ai.cidname = ri.cidname;
- ai.cidnumber = ri.cidnumber;
+ ai.callid = ri.callid;
ai.owner = "";
if (!ai.record("RECV"))
logError("Error writing RECV accounting record, dest=%s",
* Handle notification that a document has been received.
*/
void
-faxGettyApp::notifyRecvDone(const FaxRecvInfo& ri)
+faxGettyApp::notifyRecvDone(FaxRecvInfo& ri)
{
FaxServer::notifyRecvDone(ri);
+ fxStr callid_formatted;
+ for (int i = 0; i < ri.callid.size(); i++) {
+ callid_formatted.append(quote | ri.callid.id(i) | enquote);
+ }
// hand to delivery/notification command
fxStr cmd(faxRcvdCmd
| quote | ri.qfile | enquote
| quote | getModemDeviceID() | enquote
| quote | getCommID() | enquote
| quote | ri.reason | enquote
- | quote | ri.cidnumber | enquote
- | quote | ri.cidname | enquote
- );
+ | callid_formatted);
traceServer("RECV FAX: %s", (const char*) cmd);
setProcessPriority(BASE); // lower priority
runCmd(cmd, true, this);
time_t lastCIDModTime; // last mod time of CID patterns file
REArray* cidPats; // recv cid patterns
fxBoolArray* acceptCID; // accept/reject matched cid
- CallerID received_cid; // non-null received CNID
+ CallID received_callid; // non-null received CNID
fxStr gettyArgs; // getty arguments
fxStr vgettyArgs; // voice getty arguments
fxStr egettyArgs; // extern getty arguments
void discardModem(bool dropDTR);
// inbound call handling
bool isCIDOk(const fxStr& cid);
- bool processCall(CallType ctype, fxStr& emsg, const CallerID& cid);
+ bool processCall(CallType ctype, fxStr& emsg, const CallID& callid);
CallType runGetty(const char* what,
Getty* (*newgetty)(const fxStr&, const fxStr&),
const char* args, fxStr &emsg,
- bool keepLock, const CallerID& cid,
+ bool keepLock, const CallID& callid,
bool keepModem = false);
void setRingsBeforeAnswer(int rings);
void listenBegin();
void listenForRing();
void answerPhoneCmd(AnswerType, const char* dialnumber = NULL);
- void answerPhone(AnswerType, CallType, const CallerID& cid, const char* dialnumber = NULL);
+ void answerPhone(AnswerType, CallType, const CallID& callid, const char* dialnumber = NULL);
void answerCleanup();
- bool answerCall(AnswerType atype, CallType& ctype, fxStr& emsg, const CallerID& cid, const char* dialnumber = NULL);
+ bool answerCall(AnswerType atype, CallType& ctype, fxStr& emsg, const CallID& callid, const char* dialnumber = NULL);
friend void AnswerTimeoutHandler::timerExpired(long, long);
// miscellaneous stuff
// notification interfaces used by FaxServer
void notifyModemReady();
void notifyModemWedged();
- void notifyRecvBegun(const FaxRecvInfo&);
- void notifyPageRecvd(TIFF* tif, const FaxRecvInfo&, int ppm);
- void notifyDocumentRecvd(const FaxRecvInfo&);
- void notifyRecvDone(const FaxRecvInfo&);
+ void notifyRecvBegun(FaxRecvInfo&);
+ void notifyPageRecvd(TIFF* tif, FaxRecvInfo&, int ppm);
+ void notifyDocumentRecvd(FaxRecvInfo&);
+ void notifyRecvDone(FaxRecvInfo&);
public:
faxGettyApp(const fxStr& device, const fxStr& devID);
~faxGettyApp();
ai.jobtag = req->jobtag;
ai.user = req->mailaddr;
ai.csi = info.getCSI();
- ai.cidname = "";
- ai.cidnumber = "";
+ CallID empty_callid;
+ ai.callid = empty_callid;
ai.owner = req->owner;
if (req->status == send_done)
ai.status = "";
* result of a poll request.
*/
void
-faxSendApp::notifyPollRecvd(FaxRequest& req, const FaxRecvInfo& ri)
+faxSendApp::notifyPollRecvd(FaxRequest& req, FaxRecvInfo& ri)
{
(void) sendJobStatus(req.jobid, "p%s", (const char*) ri.encode());
ai.status = ri.reason;
ai.jobid = req.jobid;
ai.jobtag = req.jobtag;
- ai.cidname = "";
- ai.cidnumber = "";
+ CallID empty_callid;
+ ai.callid = empty_callid;
if (!ai.record("POLL"))
logError("Error writing POLL accounting record, dest=%s",
(const char*) ai.dest);
void notifyConnected(const FaxRequest&);
void notifyPageSent(FaxRequest& req, const char* filename);
void notifyDocumentSent(FaxRequest&, u_int fileIndex);
- void notifyPollRecvd(FaxRequest&, const FaxRecvInfo&);
+ void notifyPollRecvd(FaxRequest&, FaxRecvInfo&);
void notifyPollDone(FaxRequest&, u_int pollIndex);
public:
faxSendApp(const fxStr& device, const fxStr& devID);
ai.dest = req->external;
ai.csi = "";
ai.params = 0;
- ai.cidname = "";
- ai.cidnumber = "";
+ CallID empty_callid;
+ ai.callid = empty_callid;
ai.owner = req->owner;
if (req->status == send_done)
ai.status = "";
#endif
char* cp;
ri.sender = "";
- ri.cidname = "";
- ri.cidnumber = "";
+ CallID empty_callid;
+ ri.callid = empty_callid;
if (TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &cp)) {
while (cp[0] != '\0' && cp[0] != '\n') { // sender
ri.sender.append(cp[0]);
cp++;
}
- if (cp[0] == '\n') {
- cp++;
- while (cp[0] != '\0' && cp[0] != '\n') { // cidname
- ri.cidname.append(cp[0]);
- cp++;
- }
- }
- if (cp[0] == '\n') {
+ sanitize(ri.sender);
+ u_int i = 0;
+ while (cp[0] == '\n') {
cp++;
- while (cp[0] != '\0' && cp[0] != '\n') { // cidnumber
- ri.cidnumber.append(cp[0]);
+ ri.callid.resize(i);
+ while (cp[0] != '\0' && cp[0] != '\n') {
+ ri.callid[i].append(cp[0]);
cp++;
}
+ sanitize(ri.callid[i]);
+ i++;
}
- sanitize(ri.sender);
- sanitize(ri.cidname);
- sanitize(ri.cidnumber);
} else
ri.sender = "<unknown>";
#ifdef TIFFTAG_FAXSUBADDRESS
fprintf(fd, fspec, fmtTime(ri.time));
break;
case 'i':
- fprintf(fd, fspec, (const char*) ri.cidname);
+ fprintf(fd, fspec, ri.callid.size() > CallID::NAME ? (const char*) ri.callid.id(CallID::NAME) : "");
break;
case 'j':
- fprintf(fd, fspec, (const char*) ri.cidnumber);
+ fprintf(fd, fspec, ri.callid.size() > CallID::NUMBER ? (const char*) ri.callid.id(CallID::NUMBER) : "");
break;
case 'l':
fprintf(fd, fspec, ri.params.pageLength());
sman.apps/wedged.1m \
sman.apps/xferfaxstats.1m
MANSFILE=sman.files/hylafax-server.4f \
- sman.files/cid.4f \
+ sman.files/callid.4f \
sman.files/hylafax-config.4f \
sman.files/destctrls.4f \
sman.files/dialrules.4f \
sman.apps/wedged.1m:: ${SRCDIR}/wedged.1m; ${MANCVT}
sman.apps/xferfaxstats.1m:: ${SRCDIR}/xferfaxstats.1m; ${MANCVT}
sman.files/hylafax-server.4f:: ${SRCDIR}/hylafax-server.4f; ${MANCVT}
-sman.files/cid.4f:: ${SRCDIR}/cid.4f; ${MANCVT}
+sman.files/callid.4f:: ${SRCDIR}/callid.4f; ${MANCVT}
sman.files/hylafax-config.4f:: ${SRCDIR}/hylafax-config.4f; ${MANCVT}
sman.files/destctrls.4f:: ${SRCDIR}/destctrls.4f; ${MANCVT}
sman.files/doneq.4f:: ${SRCDIR}/doneq.4f; ${MANCVT}
.\"
.if n .po 0
.ds Fx \fIHyla\s-1FAX\s+1\fP
-.TH CID ${MANNUM4_5} "May 28, 2001"
+.TH CallID ${MANNUM4_5} "May 28, 2001"
.SH NAME
-cid \- Caller-ID and DNIS access control list
+callid \- Call identification access control list
.SH DESCRIPTION
The \*(Fx configuration parameter
.B QualifyCID
.B QualifyCID
is non-null, then only the calls identified by
strings matching
-.B CIDNumber
+.B CIDNumber (CallID1)
in the file
-(typically \fBetc/cid\fP) will be answered.
+(typically \fBetc/callid\fP) will be answered.
.PP
Patterns are specified one per line and must conform to the
regular expressions syntax specified by
should be
.IR accepted .
The order of patterns in a
-.SM CID
+.SM CallID
file is important.
When a call is to be answered, the
.I faxgetty
Finally, note that regular expressions can be used to specify
many numbers with one pattern.
.SH NOTES
-In the case of Caller-ID, the caller's identity, and in the case
-of DNIS, the called number,
-is recognized by using the
-.B CIDNumber
+The
+.B CIDNumber (CallID1)
configuration parameter described in
-.IR hylafax-config (${MANNUM4_5}).
+.IR hylafax-config (${MANNUM4_5})
+is used to store call identification information.
This parameter must be present in the per-modem configuration
-file for Caller-ID or DNIS screening or routing to function properly.
+file for call identification screening to function properly.
If
.B QualifyCID
is defined, but no
-.B CIDNumber
+.B CIDNumber (CallID1)
is specified, then no match will occur and all
incoming calls will be ignored.
.PP
-Caller-ID data is only sent once by the telco, and the timing of
-its arrival varies upon the telco and the type of line. If
+Call identification data is only sent once by the telco or PBX, and the timing of
+its arrival varies upon the telco or PBX and the type of line. If
\*(Fx is configured to answer via
.B RingsBeforeAnswer
-prior to the arrival of the caller-ID data, then all
-.B CIDNumber
-and
-.B CIDName
+prior to the arrival of the data, then all
+.B CallID
values will be null. For example, on US analog lines, caller-ID
data is usually sent between RINGs 1 and 2. In this situation,
.B RingsBeforeAnswer
.I devid
.I commid
.I error-msg
-.I cidnumber
-.I cidname
+[
+.I callid-1
+[
+.I callid-2
+[
+.I ...
+[
+.I callid-n
+] ] ] ]
.SH DESCRIPTION
.B bin/faxrcvd
is the command script invoked by the facsimile server whenever
an error message that is non-null if an error was encountered
during the receive operation.
.TP
-.B cidnumber
-the value of
-.B CIDNumber
-when using
-.B QualifyCID
-.TP
-.B cidname
-the value of
-.B CIDName
-when using
-.B QualifyCID
+.B callid
+the value of various identification indicators from the call
.SH NOTES
This script can route facsimile directly to the intended receipient.
To do this create a shell script
The facsimile will be sent as a MIME-encoded PostScript document
as default.
.TP
+.I CALLIDn
+is equivalent to the nth call identification parameter
+.TP
.I CIDNAME
is equivalent to
-.B CIDName
+.B CALLID2
above.
.TP
.I CIDNUMBER
is equivalent to
-.B CIDNumber
+.B CALLID1
above.
.TP
.I DEVICE
AnswerRotary string \s-1Any\s+1 alternatives for answering calls
AnswerBias integer \- bias to apply to successful rotary answer
AreaCode\(S2 string \- local area code
-CIDName string \- Caller \s-1ID\s+1 or DNIS name pattern string
-CIDNameAnswerLength integer \s-10\s+1 answer call when CIDName received
-CIDNumber string \- Caller \s-1ID\s+1 or DNIS number pattern string
-CIDNumberAnswerLength integer \s-10\s+1 answer call when CIDNumber received
+CallIDAnswerLength integer \- answer call when CallIDPattern received
+CallIDPattern strint \- call identification pattern string
+CIDName string \- equivalent to CallIDPattern (2)
+CIDNameAnswerLength integer \s-10\s+1 equivalent to CallIDAnswerLength (2)
+CIDNumber string \- equivalent to CallIDPattern (1)
+CIDNumberAnswerLength integer \s-10\s+1 equivalent to CallIDAnswerLength (1)
ClocalAsRoot boolean \s-1No\s+1 set \s-1CLOCAL\s+1 using root \s-1UID\s+1
ContCoverCmd\(S1 string \s-1bin/mkcover\s+1 continuation cover page generation script
ContCoverPage\(S1 string \- continuation cover page template filename
.B DialStringRules
below.)
.TP
-.B CIDName
-A string that identifies the caller's identity in any Caller-ID
-status messages or the called identity in any DNIS messages.
+.B CallIDPattern
+A string that identifies the caller's identity in any call
+identification messages provided by the modem (such as Caller*ID or DNIS/DID).
The specified string is compared against any
unrecognized status messages received from the modem before
.B ModemAnswerCmd
is sent to the modem.
If there is a match, then the remainder
-of the message is returned as the ``caller name''.
+of the message is returned as
+.B CallIDn
+where n corresponds to the n'th instance that this
+.B CallIDPattern
+is from the top in the modem configuration file.
For example, for the ZyXEL U-1496 this parameter would be set to
-``\s-1CALLER NAME:\s+1 '' (note the trailing space).
-If more than one message matches, then the message remainders are
-concatenated.
-See also
-.B CIDNumber
-and
-.BR QualifyCID .
-.TP
-.B CIDNameAnswerLength
-An integer indicating the minimum number of characters in
-.B CIDName
-to be received when
-.B ModemAnswerCmd
-is sent to the modem irrespective of any
-.B RingsBeforeAnswer
-value greater than zero. This allows the answering of calls
-which deliver CID/DID data but not RINGs.
-A value of zero for
-.B CidNameAnswerLength
-disables this feature.
-.TP
-.B CIDNumber
-A string that identifies the caller's phone number in any Caller-ID
-status messages or the called number in any DNIS messages.
-The specified string is compared against any
-unrecognized status messages received from the modem before
-.B ModemAnswerCmd
-is sent to the modem.
-If there is a match, then the remainder
-of the message is returned as the phone number of the caller.
-For example, for the ZyXEL U-1496 this parameter would be set to
-``\s-1CALLER NUMBER:\s+1 ''.
-If more than one message matches, then the message remainders are
+.nf
+\s-1CallIDPattern: ``CALLER NAME: ''\s+1 (note the trailing space).
+.fi
+If more than one message matches between instances of "RING" messages, then the message remainders are
concatenated.
-See also
-.B CIDName
-and
-.BR QualifyCID .
The special
-.B CIDNumber
+.B CallID
value of "SHIELDED_DTMF" is used in conjunction with
.B ModemRingResponse
and
-.B CIDNumberAnswerLength.
+.B CallIDAnswerLength.
After executing
.B ModemRingResponse,
HylaFAX will expect
DTMF data (usually DLE-shielded) for
-.B CIDNumber
+.B CallIDn
until
-.B CIDNumberAnswerLength
+.B CallIDAnswerLength
is reached. Note that if the modem is in voice mode to hear these
DTMF digits, then it must be returned to fax mode in the
.B ModemAnswerCmd.
For example, the following settings will cause HylaFAX to enter
voice mode and go off-hook when a RING is detected. It will then
expect four DTMF digits (presumably for routing), and then it will
-return to fax mode and answer the call.
+pause for 100 ms before returning to fax mode and answering the call.
.nf
ModemRingResponse: AT+FCLASS=8;H1
- CIDNumber: SHIELDED_DTMF
- CIDNumberAnswerLength: 4
- ModemAnswerCmd: AT+FCLASS=1;A
+ CallIDPattern: SHIELDED_DTMF
+ CallIDAnswerLength: 4
+ ModemAnswerCmd: <delay:100>AT+FCLASS=1;A
+
.fi
-.TP
-.B CIDNumberAnswerLength
-An integer indicating the minimum number of characters in
-.B CIDNumber
+Multiple entries of
+.B CallIDPattern
+are used together in one modem configuration file in order to capture multiple
+.B CallID
+responses. For example, the following settings would capture "NDID" responses
+from the modem as CallID1, "NMBR" responses from the modem as CallID2, "NAME"
+responses as CallID3, and it would trigger
+.B ModemAnswerCmd
+whenever CallID1 or CallID2 were longer than 7 or 10 characters, respectively.
+.nf
+
+ CallIDPattern: "NDID="
+ CallIDAnswerLength: 7
+ CallIDPattern: "NMBR="
+ CallIDAnswerLength: 10
+ CallIDPattern: "NAME="
+
+.fi
+Note that this example is only given as an example, and probably would cause unexpected
+results. Because pattern-matching ends when
+.B ModemAnswerCmd
+is sent to the modem, if "NDID", "NMBR", and "NAME" responses came from the modem in
+that order, and the "NDID" response was at least 7 characters long, then
+.B ModemAnswerCmd
+would be sent to the modem immediately following the "NDID" response, and the "NMBR" and
+"NAME" responses would be ignored. Generally only one
+.B CallIDAnswerLength
+item should be in a modem configuration file.
+.TP
+.B CallIDAnswerLength
+An integer indicating the minimum number of characters in a
+.B CallID
+matching the previous
+.B CallIDPattern
to be received when
.B ModemAnswerCmd
is sent to the modem irrespective of any
.B RingsBeforeAnswer
value greater than zero. This allows the answering of calls
which deliver CID/DID data but not RINGs.
+For example,
+.nf
+\s-1CallIDAnswerLength: ``7''\s+1
+.fi
+would cause the call to be answered
+when
+.B CallID2
+reached a length of seven digits.
A value of zero for
-.B CidNumberAnswerLength
+.B CallIDAnswerLength
disables this feature.
.TP
.B ClocalAsRoot
The pathname of the optional shell script, e.g. ``etc/localid'', that
makes dynamic configuration changes, i.e., to
.B LocalIdentifier,
-based on CIDName, CIDNumber, and device ID. The script is passed those
-three values as the first, second, and third parameters ($1, $2, $3),
-respectively when answering an incoming call. The script can then
+based on and device ID and call identification. The script is passed those
+values as the parameters ($1 = device id, $2 = CallID1, $3 = CallID2, $4 = CallID3, ...),
+when answering an incoming call. The script can then
perform local processing as desired to send on standard output the
configuration items to change in a ``parameter:value'' format, i.e.
``LocalIdentifier: +1.800.555.1212''. If there are multiple parameters
.IR ps2fax (${MANNUM1_8}).
.TP
.B QualifyCID
-A string that specifies whether or not \fICaller-ID information\fP
-and/or \fIDNIS information\fP
+A string that specifies whether or not \fIcall identification information\fP
should be checked against an access control list before accepting
an inbound call.
If
.B QualifyCID
-is non-null and there is Caller-ID or DNIS service,
-then only calls with data matching numbers identified
+is non-null and there is call identification service,
+then only calls with
+.B CallID1
+data matching identifications
in the file specified by this string (typically \fBetc/cid\fP)
will be accepted; see
.IR cid (${MANNUM4_5}).
If
.B QualifyCID
is not specified in the configuration file, or the value is
-null, then all incoming calls will be answered.
-Note that Caller-ID screening and DNIS routing are only available when this
+null, then all incoming calls will be answerable.
+Note that call identification screening is only available when this
service is enabled on the phone line and the modem is capable of
-presenting Caller-ID status or DNIS data information to the host.
+presenting that information to the host.
The
-.B CIDNumber
-and
-.B CIDName
+.B CallIDPattern
parameters must also be setup to reflect the manner in which
-the modem returns Caller-ID status or DNIS data information to the host.
+the modem returns call identification information to the host.
.TP
.B QualifyPWD
A string that specifies whether or not the identity of
is a command script that prints a summary of the \*(Fx
accounting statistics for received facsimile.
The statistics can be sorted using one of several keys:
-the caller's \s-1CSI\s+1 (default), CIDName, CIDNumber,
+the caller's \s-1CSI\s+1 (default), CIDName (CallID2), CIDNumber (CallID1),
the communication speed, or
the communication data format.
Statistics are read from the file
d man @MANDIR@/man4 ? ? ?
f man @MANDIR@/man4/pagesizes.@MANNUM4_5@=../man/cman.files/pagesizes.4f 0444 @SYSUID@ @SYSGID@
f man @MANDIR@/man4/typerules.@MANNUM4_5@=../man/cman.files/typerules.4f 0444 @SYSUID@ @SYSGID@
-f man @MANDIR@/man4/cid.@MANNUM4_5@=../man/sman.files/cid.4f 0444 @SYSUID@ @SYSGID@
+f man @MANDIR@/man4/cid.@MANNUM4_5@=../man/sman.files/callid.4f 0444 @SYSUID@ @SYSGID@
f man @MANDIR@/man4/hylafax-config.@MANNUM4_5@=../man/sman.files/hylafax-config.4f 0444 @SYSUID@ @SYSGID@
f man @MANDIR@/man4/destctrls.@MANNUM4_5@=../man/sman.files/destctrls.4f 0444 @SYSUID@ @SYSGID@
f man @MANDIR@/man4/dialrules.@MANNUM4_5@=../man/sman.files/dialrules.4f 0444 @SYSUID@ @SYSGID@
--- /dev/null
+/* $Id$ */
+/*
+ * Copyright (c) 2004 iFAX Solutions, Inc.
+ * HylaFAX is a trademark of Silicon Graphics
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+#include "CallID.h"
+
+CallID::CallID (int howmany)
+ : _id(howmany)
+{
+}
+
+CallID::~CallID (void)
+{
+}
+
+/*
+ * We need to manyally copy the array, becasue fxArray implementation doesn't
+ * do deep copy on the array, and we get double frees/corruption
+ */
+void CallID::operator= (const CallID& a)
+{
+ _id.resize(a._id.length());
+ for (int i = 0; i < _id.length(); i++)
+ _id[i] = a._id[i];
+}
+
+void CallID::resize(int i)
+{
+ _id.resize(i);
+}
+
+size_t CallID::makeString(fxStr& output)
+{
+ output.resize(0);
+ for (size_t i = 0; i < _id.length(); i++)
+ {
+ if (i)
+ output.append('\n');
+ output.append(_id[i]);
+ }
+ return _id.length();
+}
+
+
+const char* CallID::id (int i) const
+{
+ fxAssert(i<_id.length(), "Invalid Str[] index");
+ return _id[i];
+}
+
+int CallID::length (int i) const
+{
+ fxAssert(i<_id.length(), "Invalid Str[] index");
+ return _id[i].length();
+}
+
+
+fxStr& CallID::operator [](int i)
+{
+ fxAssert(i<_id.length(), "Invalid Str[] index");
+ return _id[i];
+}
+
+bool CallID::isEmpty (void) const
+{
+ for (int i = 0; i < _id.length(); i++)
+ {
+ if (_id[i].length() != 0)
+ return false;
+ }
+ return true;
+}
+size_t CallID::size (void) const
+{
+ return _id.length();
+}
+
+
--- /dev/null
+/* $Id$ */
+/*
+ * Copyright (c) 2004 iFAX Solutions Inc.
+ * HylaFAX is a trademark of Silicon Graphics
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+#ifndef _CallID_
+#define _CallID_
+
+#include "StrArray.h"
+
+class CallID : public fxObj {
+public:
+ fxStrArray _id; // file containing data
+
+ CallID (int howmany = 0);
+ ~CallID (void);
+
+ void operator= (const CallID&);
+ void resize(int i);
+
+ size_t makeString(fxStr&);
+
+ fxStr& operator [](int i);
+ const char* id (int i) const;
+ int length (int i) const;
+
+ bool isEmpty (void) const;
+
+ size_t size(void) const;
+
+ static const int NUMBER=0;
+ static const int NAME=1;
+
+};
+
+#endif /* _CallID_ */
, subaddr(other.subaddr)
, params(other.params)
, reason(other.reason)
- , cidname(other.cidname)
- , cidnumber(other.cidnumber)
+ , callid(other.callid)
{
npages = other.npages;
time = other.time;
FaxRecvInfo::~FaxRecvInfo() {}
fxStr
-FaxRecvInfo::encode() const
+FaxRecvInfo::encode()
{
- return fxStr::format("%x,%x,%x,%s,%s,\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\""
+ fxStr callid_formatted;
+ for (int i = 0; i < callid.size(); i++) {
+ if (i) callid_formatted.append("\",\"");
+ callid_formatted.append(callid[i]);
+ }
+ return fxStr::format("%x,%x,%x,%s,%s,\"%s\",\"%s\",\"%s\",\"%s\",\"%s\""
, time
, npages
, params.encode()
, (const char*) passwd
, (const char*) subaddr
, (const char*) reason
- , (const char*) cidname
- , (const char*) cidnumber
+ , (const char*) callid_formatted
);
}
cp = strchr(cp+1, '"');
if (cp == NULL || cp[1] != ',' || cp[2] != '"')
return (false);
- reason = cp+3; // +1 for "/+1 for ,/+1 for "
+ subaddr = cp+3; // +1 for "/+1 for ,/+1 for "
subaddr.resize(subaddr.next(0,'"'));
cp = strchr(cp+1, '"');
if (cp == NULL || cp[1] != ',' || cp[2] != '"')
cp = strchr(cp+1, '"');
if (cp == NULL || cp[1] != ',' || cp[2] != '"')
return (false);
- reason = cp+3; // +1 for "/+1 for ,/+1 for "
- cidname.resize(cidname.next(0,'"'));
- cp = strchr(cp+1, '"');
- if (cp == NULL || cp[1] != ',' || cp[2] != '"')
- return (false);
- reason = cp+3; // +1 for "/+1 for ,/+1 for "
- cidnumber.resize(cidnumber.next(0,'"'));
+ u_int i = 0;
+ while (cp+2 != '\0') {
+ callid[i] = cp+3; // +1 for "/+1 for ,/+1 for "
+ if (*cp == '\"') break;
+ callid[i].resize(callid[i].next(0,'"'));
+ i++;
+ }
return (true);
}
*/
#include "Str.h"
#include "Class2Params.h"
+#include "CallID.h"
class FaxRecvInfo : public fxObj {
public:
u_int time; // time on the phone
Class2Params params; // transfer parameters
fxStr reason; // reason for failure (if not null)
- fxStr cidname; // caller id name
- fxStr cidnumber; // caller id number
+ CallID callid; // call identification
FaxRecvInfo();
FaxRecvInfo(const FaxRecvInfo& other);
~FaxRecvInfo();
- fxStr encode() const;
+ fxStr encode();
bool decode(const char*);
};
#endif /* _FaxRecvInfo_ */
FaxRecvInfo.c++ \
FaxSendInfo.c++ \
JobExt.c++ \
+ CallID.c++ \
ModemExt.c++ \
SendFaxJob.c++ \
SendFaxClient.c++ \
#include "PageSize.h"
#include "Class2Params.h"
+#include "CallID.h"
#include "port.h"
}
#endif
fxStr sender = "";
- fxStr cidname = "";
- fxStr cidnumber = "";
+ CallID callid;
char* cp;
if (TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &cp)) {
while (cp[0] != '\0' && cp[0] != '\n') { // sender
sender.append(cp[0]);
cp++;
}
- if (cp[0] == '\n') {
- cp++;
- while (cp[0] != '\0' && cp[0] != '\n') { // cidname
- cidname.append(cp[0]);
- cp++;
- }
- }
- if (cp[0] == '\n') {
+ sanitize(sender);
+ u_int i = 0;
+ while (cp[0] == '\n') {
cp++;
- while (cp[0] != '\0' && cp[0] != '\n') { // cidnumber
- cidnumber.append(cp[0]);
+ callid.resize(i+1);
+ while (cp[0] != '\0' && cp[0] != '\n') {
+ callid[i].append(cp[0]);
cp++;
}
+ sanitize(callid[i]);
+ i++;
}
- sanitize(sender);
- sanitize(cidname);
- sanitize(cidnumber);
} else
sender = "<unknown>";
printf("%11s %s\n", "Sender:", (const char*) sender);
printf("%11s %s\n", "SignalRate:", params.bitRateName());
printf("%11s %s\n", "DataFormat:", params.dataFormatName());
printf("%11s %s\n", "ErrCorrect:", params.ec == EC_DISABLE ? "No" : "Yes");
- if (cidname != "")
- printf("%11s %s\n", "CIDName:", (const char*) cidname);
- if (cidnumber != "")
- printf("%11s %s\n", "CIDNumber:", (const char*) cidnumber);
+ for (u_int i = 0; i < callid.size(); i++) {
+ // formatting will mess up if i gets bigger than one digit
+ printf("%9s%u: %s\n", "CallID", i+1, (const char*) callid.id(i));
+ }
return (0);
}
# faxrcvd file devID commID error-msg
#
if [ $# -lt 4 ]; then
- echo "Usage: $0 file devID commID error-msg CIDNumber CIDName "
+ echo "Usage: $0 file devID commID error-msg [ callID-1 [ callID-2 [ ... [ callID-n ] ] ] ]"
exit 1
fi
HOSTNAME=`hostname` # XXX no good way to find FQDN
PORT=4559 # XXX no good way to lookup service
-FILE="$1"
-DEVICE="$2"
-COMMID="$3"
-MSG="$4"
-CIDNUMBER="$5"
-CIDNAME="$6"
+FILE="$1"; shift;
+DEVICE="$1"; shift;
+COMMID="$1"; shift;
+MSG="$1"; shift;
+COUNT=1
+while [ "$1" != "" ]; do
+ eval CALLID$COUNT="$1"
+ shift
+ COUNT=`expr $COUNT + 1`
+done
+CIDNUMBER="$CALLID1"
+CIDNAME="$CALLID2"
FILENAME=`echo $FILE | $SED -e 's/\.tif//' -e 's/recvq\///'`
SENDER="`$INFO $FILE | $AWK -F: '/Sender/ { print $2 }' 2>$ERRORSTO | $SED 's/^.//'`"
$2 == "RECV" && NF == 14 { acct($9, $11, $13, getBR($10), getDF($10), $14); }
$2 == "RECV" && NF == 16 { acct($9, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
$2 == "RECV" && NF == 17 { acct($9, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
+ $2 == "RECV" && NF == 18 { acct($9, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
'
;;
-cidname)
AWKRULES='
$2 == "RECV" && NF == 16 { acct($15, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
$2 == "RECV" && NF == 17 { acct($15, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
+ $2 == "RECV" && NF == 18 { acct($15, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
'
;;
-cidnumber)
AWKRULES='
$2 == "RECV" && NF == 16 { acct($16, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
$2 == "RECV" && NF == 17 { acct($16, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
+ $2 == "RECV" && NF == 18 { acct($16, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
'
;;
-dest*)
$2 == "RECV" && NF == 14 { acct($8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "RECV" && NF == 16 { acct($8, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
$2 == "RECV" && NF == 17 { acct($8, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
+ $2 == "RECV" && NF == 18 { acct($8, $11, $13, getBR($10), getDF($10), $14, $15, $16); }
'
;;
-speed|-rate)
$2 == "RECV" && NF == 14 { acct(getBR($10), $11, $13, getBR($10), getDF($10), $14); }
$2 == "RECV" && NF == 16 { acct(getBR($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
$2 == "RECV" && NF == 17 { acct(getBR($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
+ $2 == "RECV" && NF == 18 { acct(getBR($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
'
;;
-format)
$2 == "RECV" && NF == 14 { acct(getDF($10), $11, $13, getBR($10), getDF($10), $14); }
$2 == "RECV" && NF == 16 { acct(getDF($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
$2 == "RECV" && NF == 17 { acct(getDF($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
+ $2 == "RECV" && NF == 18 { acct(getDF($10), $11, $13, getBR($10), getDF($10), $14, $15, $16); }
'
;;
esac
$2 == "SEND" && NF == 14 { acct($7, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 16 { acct($7, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 17 { acct($7 " (" $17 ")", $8, $11, $13, getBR($10), getDF($10), $14); }
+ $2 == "SEND" && NF == 18 { acct($7 " (" $18 ")", $8, $11, $13, getBR($10), getDF($10), $14); }
'
KEYTITLE="Sender"
;;
$2 == "SEND" && NF == 14 { acct($9, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 16 { acct($9, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 17 { acct($9, $8, $11, $13, getBR($10), getDF($10), $14); }
+ $2 == "SEND" && NF == 18 { acct($9, $8, $11, $13, getBR($10), getDF($10), $14); }
'
KEYTITLE="CSI"
MAPNAMES=no
$2 == "SEND" && NF == 14 { acct($8, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 16 { acct($8, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 17 { acct($8, $8, $11, $13, getBR($10), getDF($10), $14); }
+ $2 == "SEND" && NF == 18 { acct($8, $8, $11, $13, getBR($10), getDF($10), $14); }
'
KEYTITLE="Destination"
MAPNAMES=no
$2 == "SEND" && NF == 14 { acct(getBR($10), $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 16 { acct(getBR($10), $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 17 { acct(getBR($10), $8, $11, $13, getBR($10), getDF($10), $14); }
+ $2 == "SEND" && NF == 18 { acct(getBR($10), $8, $11, $13, getBR($10), getDF($10), $14); }
'
KEYTITLE="Speed"
MAPNAMES=no
$2 == "SEND" && NF == 14 { acct(getDF($10), $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 16 { acct(getDF($10), $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 17 { acct(getDF($10), $8, $11, $13, getBR($10), getDF($10), $14); }
+ $2 == "SEND" && NF == 18 { acct(getDF($10), $8, $11, $13, getBR($10), getDF($10), $14); }
'
KEYTITLE="Format"
MAPNAMES=no
$2 == "SEND" && NF == 14 { acct($6, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 16 { acct($6, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 17 { acct($6, $8, $11, $13, getBR($10), getDF($10), $14); }
+ $2 == "SEND" && NF == 18 { acct($6, $8, $11, $13, getBR($10), getDF($10), $14); }
'
KEYTITLE="JobTag"
MAPNAMES=no
$2 == "SEND" && NF == 14 { acct($4, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 16 { acct($4, $8, $11, $13, getBR($10), getDF($10), $14); }
$2 == "SEND" && NF == 17 { acct($4, $8, $11, $13, getBR($10), getDF($10), $14); }
+ $2 == "SEND" && NF == 18 { acct($4, $8, $11, $13, getBR($10), getDF($10), $14); }
'
KEYTITLE="Device"
MAPNAMES=no