Fixed version issue of chan_lcr
[lcr.git] / route.c
1 /*****************************************************************************\ 
2 **                                                                           **
3 ** PBX4Linux                                                                 **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** match processing of routing configuration                                 **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14
15 struct route_ruleset    *ruleset_first;         /* first entry */
16 struct route_ruleset    *ruleset_main;          /* pointer to main ruleset */
17
18 struct cond_defs cond_defs[] = {
19         { "extern",     MATCH_EXTERN,   COND_TYPE_NULL,
20           "extern", "Matches if call is from external port (no extension)."},
21         { "intern",     MATCH_INTERN,COND_TYPE_NULL,
22           "intern", "Matches if call is from an extension."},
23         { "port",       MATCH_PORT,     COND_TYPE_INTEGER,
24           "port=<number>[-<number>][,...]", "Matches if call is received from given port(s). NOT INTERFACE!"},
25         { "interface",  MATCH_INTERFACE,COND_TYPE_STRING,
26           "interface=<interface>[,...]", "Matches if call is received from given interface(s). NOT PORTS!"},
27         { "callerid",   MATCH_CALLERID, COND_TYPE_STRING,
28           "callerid=<digits>[-<digits>][,...]", "Matches if caller ID matches or begins with the given (range(s) of) prefixes(s)."},
29         { "callerid2",  MATCH_CALLERID2,COND_TYPE_STRING,
30           "callerid2=<digits>[-<digits>][,...]", "Matches the second caller ID (network provided)."},
31         { "extension",  MATCH_EXTENSION,COND_TYPE_STRING,
32           "extension=<digits>[-<digits>][,...]", "Matches if caller calls from given (range(s) of) extension(s)."},
33         { "dialing",    MATCH_DIALING,  COND_TYPE_STRING,
34           "dialing=<digits>[-<digits>][,...]", "Matches if caller has dialed the given (range(s) of) digits at least."},
35         { "enblock",    MATCH_ENBLOCK,  COND_TYPE_NULL,
36           "enblock", "Matches if caller dialed en block. (Dial the number before pick up.)"},
37         { "overlap",    MATCH_OVERLAP,  COND_TYPE_NULL,
38           "overlap", "Matches if caller dialed digit by digit. (Dial the number after pick up.)"},
39         { "anonymous",  MATCH_ANONYMOUS,COND_TYPE_NULL,
40           "anonymous", "Matches if caller uses restricted caller ID or if not available."},
41         { "visible",    MATCH_VISIBLE,  COND_TYPE_NULL,
42           "visible", "Matches if caller ID is presented and if available."},
43         { "unknown",    MATCH_UNKNOWN,  COND_TYPE_NULL,
44           "unknown", "Matches if no ID is available from caller."},
45         { "available",  MATCH_AVAILABLE,COND_TYPE_NULL,
46           "available", "Matches if ID is available from caller."},
47         { "fake",       MATCH_FAKE,     COND_TYPE_NULL,
48           "fake", "Matches if caller ID is not screened and may be faked by caller."},
49         { "real",       MATCH_REAL,     COND_TYPE_NULL,
50           "real", "Matches if caller ID is screend and so it is the real caller's ID."},
51         { "redirected", MATCH_REDIRECTED,COND_TYPE_NULL,
52           "redirected", "Matches if caller has been redirected."},
53         { "direct",     MATCH_DIRECT    ,COND_TYPE_NULL,
54           "direct", "Matches if caller did not come from an redirection."},
55         { "redirid",    MATCH_REDIRID   ,COND_TYPE_STRING,
56           "redirid=<digits>[-<digits>][,...]", "Matches if the caller has been redirected by the given (range(s) of) ID(s) or prefix(es))"},
57         { "time",       MATCH_TIME,     COND_TYPE_TIME,
58           "time=<minutes>[-<minutes>][,...]", "Matches if the caller calls within the given (range(s) of) time(s). (e.g. 0700-1900)"},
59         { "mday",       MATCH_MDAY,     COND_TYPE_MDAY,
60           "mday=<day>[-<day>][,...]", "Matches if the caller calls within the given (range(s) of) day(s) of the month. (1..31)"},
61         { "month",      MATCH_MONTH,    COND_TYPE_MONTH,
62           "month=<month>[-<month>][,...]", "Matches if the caller calls within the given (range(s) of) month(s). (1=January..12=December)"},
63         { "year",       MATCH_YEAR,     COND_TYPE_YEAR,
64           "year=<year>[-<year>][,...]", "Matches if the caller calls within the given (range(s) of) year(s). (1970..2106)"},
65         { "wday",       MATCH_WDAY,     COND_TYPE_WDAY,
66           "wday=<day>[-<day>][,...]", "Matches if the caller calls within the given (range(s) of) weekday(s). (1=Monday..7=Sunday)"},
67         { "capability", MATCH_CAPABILITY, COND_TYPE_CAPABILITY,
68           "capability=speech|audio|video|digital-restricted|digital-unrestricted|digital-unrestricted-tones[,...]", "Matches the given bearer capability(s)."},
69         { "infolayer1", MATCH_INFOLAYER1, COND_TYPE_INTEGER,
70           "infolayer1=<value>[,...]", "Matches the given information layer 1. (2=u-Law, 3=a-law, see info layer 1 in bearer capability.)"},
71         { "hlc",        MATCH_HLC,      COND_TYPE_HLC,
72           "hlc=telephony|faxg2g3|faxg4|teletex1|teletex2|teletex3|videotex1|videotex2|telex|mhs|osi|maintenance|management|audiovisual[,...]", "Matches the high layer capability(s)."},
73         { "file",       MATCH_FILE,     COND_TYPE_STRING,
74           "file=<path>[,...]", "Mathes is the given file exists and if the first character is '1'."},
75         { "execute",    MATCH_EXECUTE,  COND_TYPE_STRING,
76           "execute=<command>[,...]","Matches if the return value of the given command is greater 0."},
77         { "default",    MATCH_DEFAULT,  COND_TYPE_NULL,
78           "default","Matches if no further dialing could match."},
79         { "timeout",    MATCH_TIMEOUT,  COND_TYPE_INTEGER,
80           "timeout=<seconds>","Matches if the ruleset was entered AFTER given seconds."},
81         { "free",       MATCH_FREE,     COND_TYPE_IFATTR,
82           "free=<interface>:<channel>","Matches if the given minimum of channels are free."},
83         { "notfree",    MATCH_NOTFREE,  COND_TYPE_IFATTR,
84           "notfree=<interface>:<channel>","Matches if NOT the given minimum of channels are free."},
85         { "blocked",    MATCH_DOWN,     COND_TYPE_STRING,
86           "blocked=<interfaces>[,...]","Matches if all of the given interfaces are blocked."},
87         { "idle",       MATCH_UP,       COND_TYPE_STRING,
88           "idle=<interface>[,...]","Matches if any of the given interfaces is idle."},
89         { "busy",       MATCH_BUSY,     COND_TYPE_STRING,
90           "busy=<extension>[,...]","Matches if any of the given extension is busy."},
91         { "notbusy",    MATCH_IDLE,     COND_TYPE_STRING,
92           "notbusy=<extension>[,...]","Matches if any of the given extension is not busy."},
93         { "remote",     MATCH_REMOTE,   COND_TYPE_STRING,
94           "remote=<application name>","Matches if remote application is running."},
95         { "notremote",  MATCH_NOTREMOTE,COND_TYPE_STRING,
96           "notremote=<application name>","Matches if remote application is not running."},
97         { NULL, 0, 0, NULL}
98 };
99
100 struct param_defs param_defs[] = {
101         { PARAM_PROCEEDING,
102           "proceeding", PARAM_TYPE_NULL,
103           "proceeding", "Will set the call into 'proceeding' state to prevent dial timeout."},
104         { PARAM_ALERTING,
105           "alerting",   PARAM_TYPE_NULL,
106           "alerting", "Will set the call into 'altering' state."},
107         { PARAM_CONNECT,
108           "connect",    PARAM_TYPE_NULL,
109           "connect", "Will complete the call before processing the action. Audio path for external calls will be established."},
110         { PARAM_EXTENSION,
111           "extension",  PARAM_TYPE_STRING,
112           "extension=<digits>", "Give extension name (digits) to relate this action to."},
113         { PARAM_EXTENSIONS,
114           "extensions", PARAM_TYPE_STRING,
115           "extensions=<extension>[,<extension>[,...]]", "One or more extensions may be given."},
116         { PARAM_PREFIX,
117           "prefix",     PARAM_TYPE_STRING,
118           "prefix=<digits>", "Add prefix in front of the dialed number."},
119         { PARAM_CAPA,
120           "capability", PARAM_TYPE_CAPABILITY,
121           "capability=speech|audio|video|digital-restricted|digital-unrestricted|digital-unrestricted-tones", "Alter the service type of the call."},
122         { PARAM_BMODE,
123           "bmode",      PARAM_TYPE_BMODE,
124           "bmode=transparent|hdlc", "Alter the bchannel mode of the call. Use hdlc for data calls."},
125         { PARAM_INFO1,
126           "infolayer1", PARAM_TYPE_INTEGER,
127           "infolayer1=<value>", "Alter the layer 1 information of a call. Use 3 for ALAW or 2 for uLAW."},
128         { PARAM_HLC,
129           "hlc",        PARAM_TYPE_HLC,
130           "hlc=telephony|faxg2g3|faxg4|teletex1|teletex2|teletex3|videotex1|videotex2|telex|mhs|osi|maintenance|management|audiovisual", "Alter the HLC identification."},
131         { PARAM_EXTHLC,
132           "exthlc",     PARAM_TYPE_HLC,
133           "exthlc=<value>", "Alter extended HLC value, see hlc. (Mainenance only, don't use it.)"},
134         { PARAM_PRESENT,
135           "present",    PARAM_TYPE_YESNO,
136           "present=yes|no", "Allow or restrict caller ID regardless what the caller wants."},
137         { PARAM_DIVERSION,
138           "diversion",  PARAM_TYPE_DIVERSION,
139           "diversion=cfu|cfnr|cfb|cfp", "Set diversion type."},
140         { PARAM_DEST,
141           "dest",       PARAM_TYPE_DESTIN,
142           "dest=<string>", "Destination number to divert to. Use 'vbox' to divert to vbox. (cfu,cfnr,cfb only)"},
143         { PARAM_SELECT,
144           "select",     PARAM_TYPE_NULL,
145           "select", "Lets the caller select the history of calls using keys '1'/'3' or '*'/'#'."},
146         { PARAM_DELAY,
147           "delay",      PARAM_TYPE_INTEGER,
148           "delay=<seconds>", "Number of seconds to delay."},
149         { PARAM_LIMIT,
150           "limit",      PARAM_TYPE_INTEGER,
151           "limit=<retries>", "Number of maximum retries."},
152         { PARAM_HOST,
153           "host",       PARAM_TYPE_STRING,
154           "host=<string>", "Name of remote VoIP host."},
155         { PARAM_PORT,
156           "port",       PARAM_TYPE_STRING,
157           "port=<value>", "Alternate port to use if 'host' is given."},
158         { PARAM_INTERFACES,
159           "interfaces", PARAM_TYPE_STRING,
160           "interfaces=<interface>[,<interface>[,...]]", "Give one or a list of Interfaces to select a free channel from."},
161         { PARAM_ADDRESS,
162           "address",    PARAM_TYPE_STRING,
163           "address=<string>", "Complete VoIP address. ( [user@]host[:port] )"},
164         { PARAM_SAMPLE,
165           "sample",     PARAM_TYPE_STRING,
166           "sample=<file prefix>", "Filename of sample (current tone's dir) or full path to sample. ('.wav'/'.wave'/'.isdn' is added automatically."},
167         { PARAM_ANNOUNCEMENT,
168           "announcement",PARAM_TYPE_STRING,
169           "announcement=<file prefix>", "Filename of announcement (inside vbox recording dir) or full path to sample. ('.wav'/'.wave'/'.isdn' is added automatically."},
170         { PARAM_RULESET,
171           "ruleset",    PARAM_TYPE_STRING,
172           "ruleset=<name>", "Ruleset to go to."},
173         { PARAM_CAUSE,
174           "cause",      PARAM_TYPE_INTEGER,
175           "cause=<cause value>", "Cause value when disconnecting. (21=reject 1=unassigned 63=service not available)"},
176         { PARAM_LOCATION,
177           "location",   PARAM_TYPE_INTEGER,
178           "location=<location value>", "Location of cause value when disconnecting. (0=user 1=private network sering local user)"},
179         { PARAM_DISPLAY,
180           "display",    PARAM_TYPE_STRING,
181           "display=<text>", "Message to display on the caller's telephone. (internal only)"},
182         { PARAM_PORTS,
183           "ports",      PARAM_TYPE_INTEGER,
184           "ports=<port>[,<port>[,...]]", "ISDN port[s] to use."},
185         { PARAM_TPRESET,
186           "tpreset",    PARAM_TYPE_INTEGER,
187           "tpreset=<seconds>", "Preset of countdown timer."},
188         { PARAM_FILE,
189           "file",       PARAM_TYPE_STRING,
190           "file=<full path>", "Full path to file name."},
191         { PARAM_CONTENT,
192           "content",    PARAM_TYPE_STRING,
193           "content=<string>", "Content to write into file."},
194         { PARAM_APPEND,
195           "append",     PARAM_TYPE_NULL,
196           "append", "Will append to given file, rather than overwriting it."},
197         { PARAM_EXECUTE,
198           "execute",    PARAM_TYPE_STRING,
199           "execute=<full path>", "Full path to script/command name. (Dialed digits are the argument 1.)"},
200         { PARAM_PARAM,
201           "param",      PARAM_TYPE_STRING,
202           "param=<string>", "Optionally this parameter can be inserted as argument 1, others are shifted."},
203         { PARAM_TYPE,
204           "type",       PARAM_TYPE_TYPE,
205           "type=unknown|subscriber|national|international", "Type of number to dial, default is 'unknown'."},
206         { PARAM_COMPLETE,
207           "complete",   PARAM_TYPE_NULL,
208           "complete", "Indicates complete number as given by prefix. Proceeding of long distance calls may be faster."},
209         { PARAM_CALLERID,
210           "callerid",   PARAM_TYPE_STRING,
211           "callerid=<digits>", "Change caller ID to given string."},
212         { PARAM_CALLERIDTYPE,
213           "calleridtype",PARAM_TYPE_CALLERIDTYPE,
214           "calleridtype=[unknown|subscriber|national|international]", "Type of caller ID. For normal MSN use 'unknown'"},
215         { PARAM_CALLTO,
216           "callto",     PARAM_TYPE_STRING,
217           "callto=<digits>", "Where to call back. By default the caller ID is used."},
218         { PARAM_ROOM,
219           "room",       PARAM_TYPE_INTEGER,
220           "room=<digits>", "Conference room number, must be greater 0, as in real life."},
221         { PARAM_JINGLE,
222           "jingle",     PARAM_TYPE_NULL,
223           "jingle", "Conference members will hear a jingle if a member joins."},
224         { PARAM_TIMEOUT,
225           "timeout",    PARAM_TYPE_INTEGER,
226           "timeout=<seconds>", "Timeout before continue with next action."},
227         { PARAM_NOPASSWORD,
228           "nopassword", PARAM_TYPE_NULL,
229           "nopassword", "Don't ask for password. Be sure to authenticate right via real caller ID."},
230         { PARAM_STRIP,
231           "strip",      PARAM_TYPE_NULL,
232           "strip", "Remove digits that were required to match this rule."},
233         { PARAM_APPLICATION,
234           "application",PARAM_TYPE_STRING,
235           "application=<name>", "Name of remote application to make call to."},
236         { PARAM_CONTEXT,
237           "context",    PARAM_TYPE_STRING,
238           "context=<context>", "Give context parameter to the remote application."},
239         { PARAM_EXTEN,
240           "exten",      PARAM_TYPE_STRING,
241           "exten=<extension>", "Give exten parameter to the remote application. (overrides dialed number)"},
242         { PARAM_ON,
243           "on", PARAM_TYPE_STRING,
244           "on=[init|hangup]", "Defines if the action is executed on call init or on hangup."},
245         { PARAM_KEYPAD,
246           "keypad",     PARAM_TYPE_NULL,
247           "keypad", "Use 'keypad facility' for dialing, instead of 'called number'."},
248         { 0, NULL, 0, NULL, NULL}
249 };
250
251 struct action_defs action_defs[] = {
252         { ACTION_EXTERNAL,
253           "extern",     &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_external, &EndpointAppPBX::action_hangup_call,
254           PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_KEYPAD | PARAM_CONTEXT | PARAM_TIMEOUT,
255           "Call is routed to extern number as dialed."},
256         { ACTION_INTERNAL,
257           "intern",     &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_internal, &EndpointAppPBX::action_hangup_call,
258           PARAM_CONNECT | PARAM_EXTENSION | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_TIMEOUT,
259           "Call is routed to intern extension as given by the dialed number or specified by option."},
260         { ACTION_OUTDIAL,
261           "outdial",    &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_external, &EndpointAppPBX::action_hangup_call,
262           PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_KEYPAD | PARAM_TIMEOUT,
263           "Same as 'extern'"},
264         { ACTION_VBOX_RECORD,
265           "vbox-record",&EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_vbox_record, &EndpointAppPBX::action_hangup_call,
266           PARAM_CONNECT | PARAM_EXTENSION | PARAM_ANNOUNCEMENT | PARAM_TIMEOUT,
267           "Caller is routed to the voice box of given extension."},
268         { ACTION_PARTYLINE,
269           "partyline",&EndpointAppPBX::action_init_partyline, NULL, &EndpointAppPBX::action_hangup_call,
270           PARAM_ROOM | PARAM_JINGLE,
271           "Caller is participating the conference with the given room number."},
272         { ACTION_LOGIN,
273           "login",      NULL, &EndpointAppPBX::action_dialing_login, NULL,
274           PARAM_CONNECT | PARAM_EXTENSION | PARAM_NOPASSWORD,
275           "Log into the given extension. Password required."},
276         { ACTION_CALLERID,
277           "callerid",   &EndpointAppPBX::action_init_change_callerid, &EndpointAppPBX::action_dialing_callerid, NULL,
278           PARAM_CONNECT | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_PRESENT,
279           "Caller changes the caller ID for all calls."},
280         { ACTION_CALLERIDNEXT,
281           "calleridnext",&EndpointAppPBX::action_init_change_callerid, &EndpointAppPBX::action_dialing_calleridnext, NULL,
282           PARAM_CONNECT | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_PRESENT,
283           "Caller changes the caller ID for the next call."},
284         { ACTION_FORWARD,
285           "forward",    &EndpointAppPBX::action_init_change_forward, &EndpointAppPBX::action_dialing_forward, NULL,
286           PARAM_CONNECT | PARAM_DIVERSION | PARAM_DEST | PARAM_DELAY,
287           "Caller changes the diversion of given type to the given destination or voice box."},
288         { ACTION_REDIAL,
289           "redial",     &EndpointAppPBX::action_init_redial_reply, &EndpointAppPBX::action_dialing_redial, NULL,
290           PARAM_CONNECT | PARAM_SELECT,
291           "Caller redials. (last outgoing call(s))"},
292         { ACTION_REPLY,
293           "reply",      &EndpointAppPBX::action_init_redial_reply, &EndpointAppPBX::action_dialing_reply, NULL,
294           PARAM_CONNECT | PARAM_SELECT,
295           "Caller replies. (last incoming call(s))"},
296         { ACTION_POWERDIAL,
297           "powerdial",  NULL, &EndpointAppPBX::action_dialing_powerdial, NULL,
298           PARAM_CONNECT | PARAM_DELAY | PARAM_LIMIT | PARAM_TIMEOUT,
299           "Caller redials using powerdialing."},
300         { ACTION_CALLBACK,
301           "callback",   NULL, &EndpointAppPBX::action_dialing_callback, &EndpointAppPBX::action_hangup_callback,
302           PARAM_PROCEEDING | PARAM_ALERTING | PARAM_CONNECT | PARAM_EXTENSION | PARAM_DELAY | PARAM_CALLTO | PARAM_PREFIX,
303           "Caller will use the callback service. After disconnecting, the callback is triggered."},
304         { ACTION_ABBREV,
305           "abbrev",     NULL, &EndpointAppPBX::action_dialing_abbrev, NULL,
306           PARAM_CONNECT,
307           "Caller dials abbreviation."},
308         { ACTION_TEST,
309           "test",       NULL, &EndpointAppPBX::action_dialing_test, NULL,
310           PARAM_CONNECT | PARAM_PREFIX | PARAM_TIMEOUT,
311           "Caller dials test mode."},
312         { ACTION_PLAY,
313           "play",       &EndpointAppPBX::action_init_play, NULL, NULL,
314           PARAM_PROCEEDING | PARAM_ALERTING | PARAM_CONNECT | PARAM_SAMPLE | PARAM_TIMEOUT,
315           "Plays the given sample."},
316         { ACTION_VBOX_PLAY,
317           "vbox-play",  &EndpointAppPBX::action_init_vbox_play, &EndpointAppPBX::action_dialing_vbox_play, NULL,
318           PARAM_EXTENSION,
319           "Caller listens to her voice box or to given extension."},
320         { ACTION_CALCULATOR,
321           "calculator", NULL, &EndpointAppPBX::action_dialing_calculator, NULL,
322           PARAM_CONNECT,
323           "Caller calls the calculator."},
324         { ACTION_TIMER,
325           "timer",      NULL, &EndpointAppPBX::action_dialing_timer, NULL,
326           PARAM_CONNECT | PARAM_TPRESET | PARAM_TIMEOUT,
327           NULL},
328 //        "Caller calls the timer."},
329         { ACTION_GOTO,
330           "goto",       NULL, &EndpointAppPBX::action_dialing_goto, NULL,
331           PARAM_PROCEEDING | PARAM_ALERTING | PARAM_CONNECT | PARAM_RULESET | PARAM_STRIP | PARAM_SAMPLE,
332           "Jump to given ruleset and optionally play sample. Dialed digits are not flushed."},
333         { ACTION_MENU,
334           "menu",       NULL, &EndpointAppPBX::action_dialing_menu, NULL,
335           PARAM_CONNECT | PARAM_RULESET | PARAM_SAMPLE,
336           "Same as 'goto', but flushes all digits dialed so far."},
337         { ACTION_DISCONNECT,
338           "disconnect", NULL, &EndpointAppPBX::action_dialing_disconnect, NULL,
339           PARAM_CONNECT | PARAM_CAUSE | PARAM_LOCATION | PARAM_SAMPLE | PARAM_DISPLAY,
340           "Caller gets disconnected optionally with given cause and given sample and given display text."},
341         { ACTION_RELEASE,
342           "release",    NULL, &EndpointAppPBX::action_dialing_release, NULL,
343           PARAM_CONNECT | PARAM_CAUSE | PARAM_LOCATION | PARAM_DISPLAY,
344           "Same as 'disconnect', but using RELEASE message on ISDN."},
345         { ACTION_DEFLECT,
346           "deflect",    NULL, &EndpointAppPBX::action_dialing_deflect, NULL,
347           PARAM_DEST,
348           NULL},
349 //        "External call is deflected to the given destination within the telephone network."},
350         { ACTION_SETFORWARD,
351           "setforward", NULL, &EndpointAppPBX::action_dialing_setforward, NULL,
352           PARAM_CONNECT | PARAM_DIVERSION | PARAM_DEST | PARAM_PORT,
353           NULL},
354 //        "The call forward is set within the telephone network of the external line."},
355         { ACTION_EXECUTE,
356           "execute",    &EndpointAppPBX::action_init_execute, NULL, &EndpointAppPBX::action_hangup_execute,
357           PARAM_CONNECT | PARAM_EXECUTE | PARAM_PARAM | PARAM_ON | PARAM_TIMEOUT,
358           "Executes the given script file. The file must terminate quickly, because it will halt the PBX."},
359         { ACTION_FILE,
360           "file",       NULL, NULL, &EndpointAppPBX::action_hangup_file,
361           PARAM_CONNECT | PARAM_FILE | PARAM_CONTENT | PARAM_APPEND,
362           "Writes givent content to given file. If content is not given, the dialed digits are written."},
363         { ACTION_PICK,
364           "pick",       &EndpointAppPBX::action_init_pick, NULL, NULL,
365           PARAM_EXTENSIONS,
366           "Pick up a call that is ringing on any phone. Extensions may be given to limit the picking ability."},
367         { ACTION_PASSWORD,
368           "password",   NULL, &EndpointAppPBX::action_dialing_password, NULL,
369           0,
370           NULL},
371         { ACTION_PASSWORD_WRITE,
372           "password_wr",NULL, &EndpointAppPBX::action_dialing_password_wr, NULL,
373           0,
374           NULL},
375         { ACTION_NOTHING,
376           "nothing",    NULL, NULL, NULL,
377           PARAM_PROCEEDING | PARAM_ALERTING | PARAM_CONNECT | PARAM_TIMEOUT,
378           "does nothing. Usefull to wait for calls to be released completely, by giving timeout value."},
379         { ACTION_EFI,
380           "efi",        &EndpointAppPBX::action_init_efi, NULL, NULL,
381           PARAM_PROCEEDING | PARAM_ALERTING | PARAM_CONNECT,
382           "Elektronische Fernsprecher Identifikation - announces caller ID."},
383         { -1,
384           NULL, NULL, NULL, NULL, 0, NULL}
385 };
386
387
388 /* display documentation of rules */
389
390 void doc_rules(const char *name)
391 {
392         int i, j;
393
394         if (name) {
395                 i = 0;
396                 while(action_defs[i].name) {
397                         if (!strcasecmp(action_defs[i].name, name))
398                                 break;
399                         i++;
400                 }
401                 if (!action_defs[i].name) {
402                         fprintf(stderr, "Given action '%s' unknown.\n", name);
403                         return;
404                 }
405                 name = action_defs[i].name;
406         }
407
408         printf("Syntax overview:\n");
409         printf("----------------\n\n");
410         printf("[ruleset]\n");
411         printf("<condition> ...   : <action> [parameter ...]   [timeout=X : <action> ...]\n");
412         printf("...\n");
413         printf("Please refer to the documentation for description on rule format.\n\n");
414
415         if (!name) {
416                 printf("Available conditions to match:\n");
417                 printf("------------------------------\n\n");
418                 i = 0;
419                 while(cond_defs[i].name) {
420                         printf("Usage: %s\n", cond_defs[i].doc);
421                         printf("%s\n\n", cond_defs[i].help);
422                         i++;
423                 }
424
425                 printf("Available actions with their parameters:\n");
426                 printf("----------------------------------------\n\n");
427         } else {
428                 printf("Detailes parameter description of action:\n");
429                 printf("-----------------------------------------\n\n");
430         }
431         i = 0;
432         while(action_defs[i].name) {
433                 if (name && !!strcmp(action_defs[i].name,name)) { /* not selected */
434                         i++;
435                         continue;
436                 }
437                 if (!action_defs[i].help) { /* not internal actions */
438                         i++;
439                         continue;
440                 }
441                 printf("Usage: %s", action_defs[i].name);
442                 j = 0;
443                 while(j < 64) {
444                         if ((1LL<<j) & action_defs[i].params)
445                                 printf(" [%s]", param_defs[j].doc);
446                         j++;
447                 }
448                 printf("\n%s\n\n", action_defs[i].help);
449                 if (name) { /* only show parameter help for specific action */
450                         j = 0;
451                         while(j < 64) {
452                                 if ((1LL<<j) & action_defs[i].params)
453                                         printf("%s:\n\t%s\n", param_defs[j].doc, param_defs[j].help);
454                                 j++;
455                         }
456                         printf("\n");
457                 }
458                 i++;
459         }
460 }
461
462 void ruleset_free(struct route_ruleset *ruleset_start)
463 {
464         struct route_ruleset *ruleset;
465         struct route_rule *rule;
466         struct route_cond *cond;
467         struct route_action *action;
468         struct route_param *param;
469
470         while(ruleset_start) {
471                 ruleset = ruleset_start;
472                 ruleset_start = ruleset->next;
473                 while(ruleset->rule_first) {
474                         rule = ruleset->rule_first;
475                         ruleset->rule_first = rule->next;
476                         while(rule->cond_first) {
477                                 cond = rule->cond_first;
478                                 if (cond->string_value) {
479                                         FREE(cond->string_value, 0);
480                                         rmemuse--;
481                                 }
482                                 if (cond->string_value_to) {
483                                         FREE(cond->string_value_to, 0);
484                                         rmemuse--;
485                                 }
486                                 rule->cond_first = cond->next;
487                                 FREE(cond, sizeof(struct route_cond));
488                                 rmemuse--;
489                         }
490                         while(rule->action_first) {
491                                 action = rule->action_first;
492                                 rule->action_first = action->next;
493                                 while(action->param_first) {
494                                         param = action->param_first;
495                                         action->param_first = param->next;
496                                         if (param->string_value) {
497                                                 FREE(param->string_value, 0);
498                                                 rmemuse--;
499                                         }
500                                         FREE(param, sizeof(struct route_param));
501                                         rmemuse--;
502                                 }
503                                 FREE(action, sizeof(struct route_action));
504                                 rmemuse--;
505                         }
506                         FREE(rule, sizeof(struct route_rule));
507                         rmemuse--;
508                 }
509                 FREE(ruleset, sizeof(struct route_ruleset));
510                 rmemuse--;
511         }
512 }
513
514 void ruleset_debug(struct route_ruleset *ruleset_start)
515 {
516         struct route_ruleset    *ruleset;
517         struct route_rule       *rule;
518         struct route_cond       *cond;
519         struct route_action     *action;
520         struct route_param      *param;
521         int                     first;
522
523         ruleset = ruleset_start;
524         while(ruleset) {
525                 printf("Ruleset: '%s'\n", ruleset->name);
526                 rule = ruleset->rule_first;
527                 while(rule) {
528                         /* CONDITION */
529                         first = 1;
530                         cond = rule->cond_first;
531                         while(cond) {
532                                 if (first)
533                                         printf("    Condition:");
534                                 else
535                                         printf("    and       ");
536                                 first = 0;
537                                 printf(" %s", cond_defs[cond->index].name);
538                                 if (cond->value_type != VALUE_TYPE_NULL)
539                                         printf(" = ");
540                                 next_cond_value:
541                                 switch(cond->value_type) {
542                                         case VALUE_TYPE_NULL:
543                                         break;
544
545                                         case VALUE_TYPE_INTEGER:
546                                         printf("%d", cond->integer_value);
547                                         break;
548
549                                         case VALUE_TYPE_INTEGER_RANGE:
550                                         printf("%d-%d", cond->integer_value, cond->integer_value_to);
551                                         break;
552
553                                         case VALUE_TYPE_STRING:
554                                         printf("'%s'", cond->string_value);
555                                         break;
556
557                                         case VALUE_TYPE_STRING_RANGE:
558                                         printf("'%s'-'%s'", cond->string_value, cond->string_value_to);
559                                         break;
560
561                                         default:
562                                         printf("Software error: VALUE_TYPE_* %d not known in function '%s' line=%d", cond->value_type, __FUNCTION__, __LINE__);
563                                 }
564                                 if (cond->value_extension && cond->next) {
565                                         cond = cond->next;
566                                         printf(" or ");
567                                         goto next_cond_value;
568                                 }
569
570                                 cond = cond->next;
571                                 printf("\n");
572                         }
573
574                         /* ACTION */
575                         action = rule->action_first;
576                         while(action) {
577                                 printf("    Action: %s\n", action_defs[action->index].name);
578                                 /* PARAM */
579                                 first = 1;
580                                 param = action->param_first;
581                                 while(param) {
582                                         if (first)
583                                                 printf("    Param:");
584                                         else
585                                                 printf("          ");
586                                         first = 0;
587                                         printf(" %s", param_defs[param->index].name);
588                                         if (param->value_type != VALUE_TYPE_NULL)
589                                                 printf(" = ");
590                                         switch(param->value_type) {
591                                                 case VALUE_TYPE_NULL:
592                                                 break;
593
594                                                 case VALUE_TYPE_INTEGER:
595                                                 if (param_defs[param->index].type == PARAM_TYPE_CALLERIDTYPE) {
596                                                         switch(param->integer_value) {
597                                                                 case INFO_NTYPE_UNKNOWN:
598                                                                 printf("unknown");
599                                                                 break;
600                                                                 case INFO_NTYPE_SUBSCRIBER:
601                                                                 printf("subscriber");
602                                                                 break;
603                                                                 case INFO_NTYPE_NATIONAL:
604                                                                 printf("national");
605                                                                 break;
606                                                                 case INFO_NTYPE_INTERNATIONAL:
607                                                                 printf("international");
608                                                                 break;
609                                                                 default:
610                                                                 printf("unknown(%d)", param->integer_value);
611                                                         }
612                                                         break;
613                                                 }
614                                                 if (param_defs[param->index].type == PARAM_TYPE_CAPABILITY) {
615                                                         switch(param->integer_value) {
616                                                                 case INFO_BC_SPEECH:
617                                                                 printf("speech");
618                                                                 break;
619                                                                 case INFO_BC_AUDIO:
620                                                                 printf("audio");
621                                                                 break;
622                                                                 case INFO_BC_VIDEO:
623                                                                 printf("video");
624                                                                 break;
625                                                                 case INFO_BC_DATARESTRICTED:
626                                                                 printf("digital-restricted");
627                                                                 break;
628                                                                 case INFO_BC_DATAUNRESTRICTED:
629                                                                 printf("digital-unrestricted");
630                                                                 break;
631                                                                 case INFO_BC_DATAUNRESTRICTED_TONES:
632                                                                 printf("digital-unrestricted-tones");
633                                                                 break;
634                                                                 default:
635                                                                 printf("unknown(%d)", param->integer_value);
636                                                         }
637                                                         break;
638                                                 }
639                                                 if (param_defs[param->index].type == PARAM_TYPE_DIVERSION) {
640                                                         switch(param->integer_value) {
641                                                                 case INFO_DIVERSION_CFU:
642                                                                 printf("cfu");
643                                                                 break;
644                                                                 case INFO_DIVERSION_CFNR:
645                                                                 printf("cfnr");
646                                                                 break;
647                                                                 case INFO_DIVERSION_CFB:
648                                                                 printf("cfb");
649                                                                 break;
650                                                                 case INFO_DIVERSION_CFP:
651                                                                 printf("cfp");
652                                                                 break;
653                                                                 default:
654                                                                 printf("unknown(%d)", param->integer_value);
655                                                         }
656                                                         break;
657                                                 }
658                                                 if (param_defs[param->index].type == PARAM_TYPE_TYPE) {
659                                                         switch(param->integer_value) {
660                                                                 case INFO_NTYPE_UNKNOWN:
661                                                                 printf("unknown");
662                                                                 break;
663                                                                 case INFO_NTYPE_SUBSCRIBER:
664                                                                 printf("subscriber");
665                                                                 break;
666                                                                 case INFO_NTYPE_NATIONAL:
667                                                                 printf("national");
668                                                                 break;
669                                                                 case INFO_NTYPE_INTERNATIONAL:
670                                                                 printf("international");
671                                                                 break;
672                                                                 default:
673                                                                 printf("unknown(%d)", param->integer_value);
674                                                         }
675                                                         break;
676                                                 }
677                                                 if (param_defs[param->index].type == PARAM_TYPE_YESNO) {
678                                                         switch(param->integer_value) {
679                                                                 case 1:
680                                                                 printf("yes");
681                                                                 break;
682                                                                 case 0:
683                                                                 printf("no");
684                                                                 break;
685                                                                 default:
686                                                                 printf("unknown(%d)", param->integer_value);
687                                                         }
688                                                         break;
689                                                 }
690                                                 if (param_defs[param->index].type == PARAM_TYPE_NULL) {
691                                                         break;
692                                                 }
693                                                 printf("%d", param->integer_value);
694                                                 break;
695
696                                                 case VALUE_TYPE_STRING:
697                                                 printf("'%s'", param->string_value);
698                                                 break;
699
700                                                 default:
701                                                 printf("Software error: VALUE_TYPE_* %d not known in function '%s' line=%d", param->value_type, __FUNCTION__, __LINE__);
702                                         }
703                                         param = param->next;
704                                         printf("\n");
705                                 }
706                                 /* TIMEOUT */
707                                 if (action->timeout)
708                                         printf("    Timeout: %d\n", action->timeout);
709                                 action = action->next;
710                         }
711                         printf("\n");
712                         rule = rule->next;
713                 }
714                 printf("\n");
715                 ruleset = ruleset->next;
716         }
717 }
718
719
720 /*
721  * parse ruleset
722  */
723 static char *read_string(char *p, char *key, int key_size, const char *special)
724 {
725         key[0] = 0;
726
727         if (*p == '\"') {
728                 p++;
729                 /* quote */
730                 while(*p) {
731                         if (*p == '\"') {
732                                 p++;
733                                 *key = '\0';
734                                 return(p);
735                         }
736                         if (*p == '\\') {
737                                 p++;
738                                 if (*p == '\0') {
739                                         break;
740                                 }
741                         }
742                         if (--key_size == 0) {
743                                 UPRINT(key, "\001String too long.");
744                                 return(p);
745                         }
746                         *key++ = *p++;
747                 }
748                 UPRINT(key, "\001Unexpected end of line inside quotes.");
749                 return(p);
750         }
751
752         /* no quote */
753         while(*p) {
754                 if (strchr(special, *p)) {
755                         *key = '\0';
756                         return(p);
757                 }
758                 if (*p == '\\') {
759                         p++;
760                         if (*p == '\0') {
761                                 UPRINT(key, "\001Unexpected end of line.");
762                                 return(p);
763                         }
764                 }
765                 if (--key_size == 0) {
766                         UPRINT(key, "\001String too long.");
767                         return(p);
768                 }
769                 *key++ = *p++;
770         }
771         *key = '\0';
772         return(p);
773 }
774 char ruleset_error[256];
775 struct route_ruleset *ruleset_parse(void)
776 {
777 //      char                    from[128];
778 //      char                    to[128];
779         int                     i;
780         unsigned long long      j;
781 //      int                     a,
782 //                              b;
783         #define                 MAXNESTING 8
784         FILE                    *fp[MAXNESTING];
785         char                    filename[MAXNESTING][256];
786         int                     line[MAXNESTING];
787         int                     nesting = -1;
788         char                    buffer[1024],
789                                 key[1024],
790                                 key_to[1024],
791                                 pointer[1024+1],
792                                 *p;
793         int                     expecting = 1; /* 1 = expecting ruleset */
794         int                     index,
795                                 value_type,
796                                 integer,
797                                 integer_to; /* condition index, .. */
798         struct route_ruleset    *ruleset_start = NULL, *ruleset;
799         struct route_ruleset    **ruleset_pointer = &ruleset_start;
800         struct route_rule       *rule;
801         struct route_rule       **rule_pointer = NULL;
802         struct route_cond       *cond;
803         struct route_cond       **cond_pointer = NULL;
804         struct route_action     *action;
805         struct route_action     **action_pointer = NULL;
806         struct route_param      *param;
807         struct route_param      **param_pointer = NULL;
808         char                    failure[256];
809         unsigned long long      allowed_params;
810
811         /* check the integrity of IDs for ACTION_* and PARAM_* */
812         i = 0;
813         while(action_defs[i].name) {
814                 if (action_defs[i].id != i) {
815                         PERROR("Software Error action '%s' must have id of %d, but has %d.\n",
816                                 action_defs[i].name, i, action_defs[i].id);
817                         goto openerror;
818                 }
819                 i++;
820         }
821         i = 0; j = 1;
822         while(param_defs[i].name) {
823                 if (param_defs[i].id != j) {
824                         PERROR("Software Error param '%s' must have id of 0x%llx, but has 0x%llx.\n",
825                                 param_defs[i].name, j, param_defs[i].id);
826                         goto openerror;
827                 }
828                 i++;
829                 j<<=1;
830         }
831
832         SPRINT(filename[0], "%s/routing.conf", CONFIG_DATA);
833
834         if (!(fp[0]=fopen(filename[0],"r")))
835         {
836                 PERROR("Cannot open %s\n",filename[0]);
837                 goto openerror;
838         }
839         nesting++;
840         fduse++;
841
842         go_leaf:
843         line[nesting]=0;
844         go_root:
845         while((GETLINE(buffer, fp[nesting])))
846         {
847                 line[nesting]++;
848                 p = buffer;
849
850                 /* remove tabs */
851                 while(*p) {
852                         if (*p < 32)
853                                 *p = 32;
854                         p++;
855                 } 
856                 p = buffer;
857
858                 /* skip spaces, if any */
859                 while(*p == 32)
860                 {
861                         if (*p == 0)
862                                 break;
863                         p++;
864                 }
865
866                 /* skip comments */
867                 if (*p == '#') {
868                         p++;
869                         /* don't skip "define" */
870                         if (!!strncmp(p, "define", 6))
871                                 continue;
872                         p+=6;
873                         if (*p != 32)
874                                 continue;
875                         /* skip spaces */
876                         while(*p == 32) {
877                                 if (*p == 0)
878                                         break;
879                                 p++;
880                         }
881                         p++;
882                         p = read_string(p, key, sizeof(key), " ");
883                         if (key[0] == 1) { /* error */
884                                 SPRINT(failure, "Parsing Filename failed: %s", key+1);
885                                 goto parse_error;
886                         }
887                         if (nesting == MAXNESTING-1) {
888                                 SPRINT(failure, "'include' is nesting too deep.\n");
889                                 goto parse_error;
890                         }
891                         if (key[0] == '/')
892                                 SCPY(filename[nesting+1], key);
893                         else
894                                 SPRINT(filename[nesting+1], "%s/%s", CONFIG_DATA, key);
895                         if (!(fp[nesting+1]=fopen(filename[nesting+1],"r"))) {
896                                 PERROR("Cannot open %s\n", filename[nesting+1]);
897                                 goto parse_error;
898                         }
899                         fduse++;
900                         nesting++;
901                         goto go_leaf;
902                 }
903                 if (*p == '/') if (p[1] == '/')
904                         continue;
905
906                 /* skip empty lines */
907                 if (*p == 0)
908                         continue;
909
910                 /* expecting ruleset */
911                 if (expecting) {
912                         new_ruleset:
913                         /* expecting [ */
914                         if (*p != '[') {
915                                 SPRINT(failure, "Expecting ruleset name starting with '['.");
916                                 goto parse_error;
917                         }
918                         p++;
919
920                         /* reading ruleset name text */
921                         i = 0;
922                         while(*p>' ' && *p<127 && *p!=']') {
923                                 if (*p>='A' && *p<='Z') *p = *p-'A'+'a'; /* lower case */
924                                 key[i++] = *p++;
925                                 if (i == sizeof(key)) i--; /* limit */
926                         }
927                         key[i] = 0;
928                         if (key[0] == '\0') {
929                                 SPRINT(failure, "Missing ruleset name after '['.");
930                                 goto parse_error;
931                         }
932
933                         /* expecting ] and nothing more */
934                         if (*p != ']') {
935                                 SPRINT(failure, "Expecting ']' after ruleset name.");
936                                 goto parse_error;
937                         }
938                         p++;
939                         if (*p != 0) {
940                                 SPRINT(failure, "Unexpected character after ruleset name.");
941                                 goto parse_error;
942                         }
943
944                         /* check for duplicate rulesets */
945                         ruleset = ruleset_start;
946                         while(ruleset) {
947                                 if (!strcmp(ruleset->name, key)) {
948                                         SPRINT(failure, "Duplicate ruleset '%s', already defined in file '%s' line %d.", key, ruleset->file, ruleset->line);
949                                         goto parse_error;
950                                 }
951                                 ruleset = ruleset->next;
952                         }
953
954                         /* create ruleset */
955                         ruleset = (struct route_ruleset *)MALLOC(sizeof(struct route_ruleset));
956                         rmemuse++;
957                         *ruleset_pointer = ruleset;
958                         ruleset_pointer = &(ruleset->next);
959                         SCPY(ruleset->name, key);
960                         SCPY(ruleset->file, filename[nesting]);
961                         ruleset->line = line[nesting];
962                         rule_pointer = &(ruleset->rule_first);
963                         expecting = 0;
964                         continue;
965                 }
966
967                 /* for new ruleset [ */
968                 if (*p == '[') {
969                         goto new_ruleset;
970                 }
971
972                 /* Alloc memory for rule */
973                 rule = (struct route_rule *)MALLOC(sizeof(struct route_rule));
974                 rmemuse++;
975                 *rule_pointer = rule;
976                 rule_pointer = &(rule->next);
977                 cond_pointer = &(rule->cond_first);
978                 action_pointer = &(rule->action_first);
979                 SCPY(rule->file, filename[nesting]);
980                 rule->line = line[nesting];
981
982                 /* loop CONDITIONS */
983                 while(*p!=':' && *p!='\0') {
984                         /* read item text */
985                         i = 0;
986                         while((*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9')) {
987                                 if (*p>='A' && *p<='Z') *p = *p-'A'+'a'; /* lower case */
988                                 key[i++] = *p++;
989                                 if (i == sizeof(key)) i--; /* limit */
990                         }
991                         key[i] = 0;
992                         if (key[0] == '\0') {
993                                 SPRINT(failure, "Expecting condition item name or ':' for end of condition list.");
994                                 goto parse_error;
995                         }
996                         if (*p!=' ' && *p!='=') {
997                                 SPRINT(failure, "Illegal character '%c' after condition name '%s'. Expecting '=' for equation or ' ' to seperate condition items.", *p, key);
998                                 goto parse_error;
999                         }
1000
1001                         /* check if condition exists */
1002                         index = 0;
1003                         while(cond_defs[index].name) {
1004                                 if (!strcmp(cond_defs[index].name, key))
1005                                         break;
1006                                 index++;
1007                         }
1008                         if (cond_defs[index].name == NULL) {
1009                                 SPRINT(failure, "Unknown condition item name '%s'.", key);
1010                                 goto parse_error;
1011                         }
1012
1013                         /* items without values must not have any parameter */
1014                         if (cond_defs[index].type == COND_TYPE_NULL) {
1015                                 if (*p == '=') {
1016                                         SPRINT(failure, "Condition item '%s' must not have any value. Don't use '=' for this type of condition.", key);
1017                                         goto parse_error;
1018                                 }
1019                                 if (*p != ' ') {
1020                                         SPRINT(failure, "Condition item '%s' must not have any value. Expecting ' ' or tab after item name.", key);
1021                                         goto parse_error;
1022                                 }
1023 //                              p++;
1024                         } else {
1025                                 if (*p == ' ') {
1026                                         SPRINT(failure, "Condition item '%s' must have at least one value, '=' expected, and not a space.", key);
1027                                         goto parse_error;
1028                                 }
1029                                 if (*p != '=') {
1030                                         SPRINT(failure, "Condition item '%s' must have at least one value, '=' expected.", key);
1031                                         goto parse_error;
1032                                 }
1033                                 p++;
1034                         }
1035
1036                         /* check for duplicate condition */
1037                         cond = rule->cond_first;
1038                         while(cond) {
1039                                 if (cond->index == index) {
1040                                         SPRINT(failure, "Duplicate condition '%s', use ',' to give multiple values.", key);
1041                                         goto parse_error;
1042                                 }
1043                                 cond = cond->next;
1044                         }
1045
1046                         nextcondvalue:
1047                         /* Alloc memory for item */
1048                         cond = (struct route_cond *)MALLOC(sizeof(struct route_cond));
1049                         rmemuse++;
1050                         *cond_pointer = cond;
1051                         cond_pointer = &(cond->next);
1052                         cond->index = index;
1053                         cond->match = cond_defs[index].match;
1054                         switch(cond_defs[index].type) {
1055                                 case COND_TYPE_NULL:
1056                                 if (*p=='=') {
1057                                         SPRINT(failure, "Expecting no value.");
1058                                         goto parse_error;
1059                                 }
1060                                 value_type = VALUE_TYPE_NULL;
1061                                 break;
1062
1063                                 /* parse all integer values/ranges */
1064                                 case COND_TYPE_INTEGER:
1065                                 case COND_TYPE_TIME:
1066                                 case COND_TYPE_MDAY:
1067                                 case COND_TYPE_MONTH:
1068                                 case COND_TYPE_WDAY:
1069                                 case COND_TYPE_YEAR:
1070                                 integer = integer_to = 0;
1071                                 if (*p==',' || *p==' ' || *p=='\0') {
1072                                         SPRINT(failure, "Missing integer value.");
1073                                         goto parse_error;
1074                                 }
1075                                 while(*p>='0' && *p<='9') {
1076                                         integer = integer*10 + *p-'0';
1077                                         p++;
1078                                 }
1079                                 value_type = VALUE_TYPE_INTEGER;
1080                                 if (*p == '-') {
1081                                         p++;
1082                                         if (*p==',' || *p==' ' || *p=='\0') {
1083                                                 SPRINT(failure, "Missing integer value.");
1084                                                 goto parse_error;
1085                                         }
1086                                         while(*p>='0' && *p<='9') {
1087                                                 integer_to = integer_to*10 + *p-'0';
1088                                                 p++;
1089                                         }
1090                                         value_type = VALUE_TYPE_INTEGER_RANGE;
1091                                 }
1092                                 if (cond_defs[index].type == COND_TYPE_TIME) {
1093                                         // Simon: i store the time as decimal, later i compare it correctly:
1094                                         // hours * 100 + minutes
1095                                         if (integer == 2400)
1096                                                 integer = 0;
1097                                         if (integer >= 2400) {
1098                                                 timeoutofrange1:
1099                                                 SPRINT(failure, "Given time '%d' not in range 0000..2359 (or 2400 for 0000)", integer);
1100                                                 goto parse_error;
1101                                         }
1102                                         if (integer%100 >= 60)
1103                                                 goto timeoutofrange1;
1104                                         if (value_type == VALUE_TYPE_INTEGER)
1105                                                 goto integer_done;
1106                                         if (integer_to == 2400)
1107                                                 integer_to = 0;
1108                                         if (integer_to >= 2400) {
1109                                                 timeoutofrange2:
1110                                                 SPRINT(failure, "Given time '%d' not in range 0000..2359 (or 2400 for 0000)", integer_to);
1111                                                 goto parse_error;
1112                                         }
1113                                         if (integer_to%100 >= 60)
1114                                                 goto timeoutofrange2;
1115                                 }
1116                                 if (cond_defs[index].type == COND_TYPE_MDAY) {
1117                                         if (integer<1 || integer>31) {
1118                                                 SPRINT(failure, "Given day-of-month '%d' not in range 1..31", integer);
1119                                                 goto parse_error;
1120                                         } 
1121                                         if (value_type == VALUE_TYPE_INTEGER)
1122                                                 goto integer_done;
1123                                         if (integer_to<1 || integer_to>31) {
1124                                                 SPRINT(failure, "Given day-of-month '%d' not in range 1..31", integer_to);
1125                                                 goto parse_error;
1126                                         } 
1127                                 }
1128                                 if (cond_defs[index].type == COND_TYPE_WDAY) {
1129                                         if (integer<1 || integer>7) {
1130                                                 SPRINT(failure, "Given day-of-week '%d' not in range 1..7", integer);
1131                                                 goto parse_error;
1132                                         } 
1133                                         if (value_type == VALUE_TYPE_INTEGER)
1134                                                 goto integer_done;
1135                                         if (integer_to<1 || integer_to>7) {
1136                                                 SPRINT(failure, "Given day-of-week '%d' not in range 1..7", integer_to);
1137                                                 goto parse_error;
1138                                         } 
1139                                 }
1140                                 if (cond_defs[index].type == COND_TYPE_MONTH) {
1141                                         if (integer<1 || integer>12) {
1142                                                 SPRINT(failure, "Given month '%d' not in range 1..12", integer);
1143                                                 goto parse_error;
1144                                         } 
1145                                         if (value_type == VALUE_TYPE_INTEGER)
1146                                                 goto integer_done;
1147                                         if (integer_to<1 || integer_to>12) {
1148                                                 SPRINT(failure, "Given month '%d' not in range 1..12", integer_to);
1149                                                 goto parse_error;
1150                                         } 
1151                                 }
1152                                 if (cond_defs[index].type == COND_TYPE_YEAR) {
1153                                         if (integer<1970 || integer>2106) {
1154                                                 SPRINT(failure, "Given year '%d' not in range 1970..2106", integer);
1155                                                 goto parse_error;
1156                                         } 
1157                                         if (value_type == VALUE_TYPE_INTEGER)
1158                                                 goto integer_done;
1159                                         if (integer_to<1970 || integer_to>2106) {
1160                                                 SPRINT(failure, "Given year '%d' not in range 1970..2106", integer_to);
1161                                                 goto parse_error;
1162                                         } 
1163                                 }
1164                                 integer_done:
1165                                 cond->integer_value = integer;
1166                                 cond->integer_value_to = integer_to;
1167                                 cond->value_type = value_type;
1168                                 break;
1169
1170                                 /* parse all string values/ranges */
1171                                 case COND_TYPE_STRING:
1172                                 key[0] = key_to[0] = '\0';
1173                                 if (*p==',' || *p==' ' || *p=='\0') {
1174                                         SPRINT(failure, "Missing string value, use \"\" for empty string.");
1175                                         goto parse_error;
1176                                 }
1177                                 p = read_string(p, key, sizeof(key), "-, ");
1178                                 if (key[0] == 1) { /* error */
1179                                         SPRINT(failure, "Parsing String failed: %s", key+1);
1180                                         goto parse_error;
1181                                 }
1182                                 value_type = VALUE_TYPE_STRING;
1183                                 if (*p == '-') {
1184                                         p++;
1185                                         if (*p==',' || *p==' ' || *p=='\0') {
1186                                                 SPRINT(failure, "Missing string value, use \"\" for empty string.");
1187                                                 goto parse_error;
1188                                         }
1189                                         p = read_string(p, key_to, sizeof(key_to), "-, ");
1190                                         if (key_to[0] == 1) { /* error */
1191                                                 SPRINT(failure, "Parsing string failed: %s", key_to+1);
1192                                                 goto parse_error;
1193                                         }
1194                                         value_type = VALUE_TYPE_STRING_RANGE;
1195                                         if (strlen(key) != strlen(key_to)) {
1196                                                 SPRINT(failure, "Given range of strings \"%s\"-\"%s\" have unequal length.", key, key_to);
1197                                                 goto parse_error;
1198                                         }
1199                                         if (key[0] == '\0') {
1200                                                 SPRINT(failure, "Given range has no length.");
1201                                                 goto parse_error;
1202                                         }
1203                                 }
1204                                 alloc_string:
1205                                 cond->string_value = (char *)MALLOC(strlen(key)+1);
1206                                 rmemuse++;
1207                                 UCPY(cond->string_value, key);
1208                                 if (value_type == VALUE_TYPE_STRING_RANGE) {
1209                                         cond->string_value_to = (char *)MALLOC(strlen(key_to)+1);
1210                                         rmemuse++;
1211                                         UCPY(cond->string_value_to, key_to);
1212                                         cond->comp_string = strcmp(key, key_to);
1213                                 }
1214                                 cond->value_type = value_type;
1215                                 break;
1216
1217                                 /* parse service value */
1218                                 case COND_TYPE_CAPABILITY:
1219                                 if (!strncasecmp("speech", p, 6)) {
1220                                         cond->integer_value = INFO_BC_SPEECH;
1221                                         p += 6;
1222                                 } else if (!strncasecmp("audio", p, 5)) {
1223                                         cond->integer_value = INFO_BC_AUDIO;
1224                                         p += 5;
1225                                 } else if (!strncasecmp("video", p, 5)) {
1226                                         cond->integer_value = INFO_BC_VIDEO;
1227                                         p += 5;
1228                                 } else if (!strncasecmp("digital-restricted", p, 18)) {
1229                                         cond->integer_value = INFO_BC_DATARESTRICTED;
1230                                         p += 18;
1231                                 } else if (!strncasecmp("digital-unrestricted", p, 20)) {
1232                                         cond->integer_value = INFO_BC_DATAUNRESTRICTED;
1233                                         p += 20;
1234                                 } else if (!strncasecmp("digital-unrestricted-tones", p, 26)) {
1235                                         cond->integer_value = INFO_BC_DATAUNRESTRICTED_TONES;
1236                                         p += 26;
1237                                 } else {
1238                                         SPRINT(failure, "Given service type is invalid or misspelled.");
1239                                         goto parse_error;
1240                                 }
1241                                 cond->value_type = VALUE_TYPE_INTEGER;
1242                                 break;
1243
1244                                 /* parse bmode value */
1245                                 case COND_TYPE_BMODE:
1246                                 if (!strncasecmp("transparent", p, 11)) {
1247                                         cond->integer_value = INFO_BMODE_CIRCUIT;
1248                                         p += 11;
1249                                 } else if (!strncasecmp("hdlc", p, 4)) {
1250                                         cond->integer_value = INFO_BMODE_PACKET;
1251                                         p += 4;
1252                                 } else {
1253                                         SPRINT(failure, "Given bchannel mode is invalid or misspelled.");
1254                                         goto parse_error;
1255                                 }
1256                                 cond->value_type = VALUE_TYPE_INTEGER;
1257                                 break;
1258
1259                                 /* parse service value */
1260                                 case COND_TYPE_HLC:
1261                                 if (!strncasecmp("telephony", p, 9)) {
1262                                         cond->integer_value = INFO_HLC_TELEPHONY;
1263                                         p += 9;
1264                                 } else if (!strncasecmp("faxg2g3", p, 7)) {
1265                                         cond->integer_value = INFO_HLC_FAXG2G3;
1266                                         p += 7;
1267                                 } else if (!strncasecmp("faxg4", p, 5)) {
1268                                         cond->integer_value = INFO_HLC_FAXG4;
1269                                         p += 5;
1270                                 } else if (!strncasecmp("teletex1", p, 8)) {
1271                                         cond->integer_value = INFO_HLC_TELETEX1;
1272                                         p += 8;
1273                                 } else if (!strncasecmp("teletex2", p, 8)) {
1274                                         cond->integer_value = INFO_HLC_TELETEX2;
1275                                         p += 8;
1276                                 } else if (!strncasecmp("teletex3", p, 8)) {
1277                                         cond->integer_value = INFO_HLC_TELETEX3;
1278                                         p += 8;
1279                                 } else if (!strncasecmp("videotex1", p, 9)) {
1280                                         cond->integer_value = INFO_HLC_VIDEOTEX1;
1281                                         p += 9;
1282                                 } else if (!strncasecmp("videotex2", p, 9)) {
1283                                         cond->integer_value = INFO_HLC_VIDEOTEX2;
1284                                         p += 9;
1285                                 } else if (!strncasecmp("telex", p, 5)) {
1286                                         cond->integer_value = INFO_HLC_TELEX;
1287                                         p += 5;
1288                                 } else if (!strncasecmp("mhs", p, 3)) {
1289                                         cond->integer_value = INFO_HLC_MHS;
1290                                         p += 3;
1291                                 } else if (!strncasecmp("osi", p, 3)) {
1292                                         cond->integer_value = INFO_HLC_OSI;
1293                                         p += 3;
1294                                 } else if (!strncasecmp("maintenance", p, 11)) {
1295                                         cond->integer_value = INFO_HLC_MAINTENANCE;
1296                                         p += 11;
1297                                 } else if (!strncasecmp("management", p, 10)) {
1298                                         cond->integer_value = INFO_HLC_MANAGEMENT;
1299                                         p += 10;
1300                                 } else if (!strncasecmp("audiovisual", p, 11)) {
1301                                         cond->integer_value = INFO_HLC_AUDIOVISUAL;
1302                                         p += 11;
1303                                 } else {
1304                                         SPRINT(failure, "Given HLC type is invalid or misspelled.");
1305                                         goto parse_error;
1306                                 }
1307                                 cond->value_type = VALUE_TYPE_INTEGER;
1308                                 break;
1309
1310                                 /* parse interface attribute <if>:<value> */
1311                                 case COND_TYPE_IFATTR:
1312                                 key[0] = key_to[0] = '\0';
1313                                 if (*p==':' || *p==',' || *p==' ' || *p=='\0') {
1314                                         SPRINT(failure, "Missing interface name.");
1315                                         goto parse_error;
1316                                 }
1317                                 p = read_string(p, key, sizeof(key), ":-, ");
1318                                 if (key[0] == 1) { /* error */
1319                                         SPRINT(failure, "Parsing interface failed: %s", key+1);
1320                                         goto parse_error;
1321                                 }
1322                                 if (*p != ':') {
1323                                         SPRINT(failure, "Expeciting kolon to seperate value behind interface name.");
1324                                         goto parse_error;
1325                                 }
1326                                 SCCAT(key, *p++);
1327                                 while(*p>='0' && *p<='9') {
1328                                         SCCAT(key, *p++);
1329                                 }
1330                                 if (*p!=',' && *p!=' ' && *p!='\0') {
1331                                         SPRINT(failure, "Invalid characters behind value.");
1332                                         goto parse_error;
1333                                 }
1334                                 value_type = VALUE_TYPE_STRING;
1335                                 goto alloc_string;
1336                                 break;
1337
1338                                 default:
1339                                 SPRINT(failure, "Software error: COND_TYPE_* %d not parsed in function '%s'", cond_defs[index].type, __FUNCTION__);
1340                                 goto parse_error;
1341                         }
1342                         /* if we have another value for that item, we attach it */
1343                         if (*p == ',') {
1344                                 p++;
1345                                 /* next item */
1346                                 cond->value_extension = 1;
1347                                 goto nextcondvalue;
1348                         }
1349                         /* to seperate the items, a space is required */
1350                         if (*p != ' ') {
1351                                 SPRINT(failure, "Character '%c' not expected here. Use ',' to seperate multiple possible values.", *p);
1352                                 goto parse_error;
1353                         }
1354                         /* skip spaces */
1355                         while(*p == 32)
1356                         {
1357                                 if (*p == 0)
1358                                         break;
1359                                 p++;
1360                         }
1361                 }
1362
1363                 /* we are done with CONDITIONS, so we expect the ACTION */
1364                 if (*p != ':') {
1365                         SPRINT(failure, "Expecting ':' after condition item(s).");
1366                         goto parse_error;
1367                 }
1368                 p++;
1369
1370                 nextaction:
1371                 /* skip spaces, if any */
1372                 while(*p == 32)
1373                 {
1374                         if (*p == 0)
1375                                 break;
1376                         p++;
1377                 }
1378
1379                 /* read action name */
1380                 i = 0;
1381                 while((*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9') || *p == '-') {
1382                         if (*p>='A' && *p<='Z') *p = *p-'A'+'a'; /* lower case */
1383                         key[i++] = *p++;
1384                         if (i == sizeof(key)) i--; /* limit */
1385                 }
1386                 key[i] = 0;
1387                 if (key[0] == '\0') {
1388                         SPRINT(failure, "Expecting action name.");
1389                         goto parse_error;
1390                 }
1391
1392                 /* check if item exists */
1393                 index = 0;
1394                 while(action_defs[index].name) {
1395                         if (!action_defs[index].help) { /* not internal actions */
1396                                 index++;
1397                                 continue;
1398                         }
1399                         if (!strcmp(action_defs[index].name, key))
1400                                 break;
1401                         index++;
1402                 }
1403                 if (action_defs[index].name == NULL) {
1404                         SPRINT(failure, "Unknown action name '%s'.", key);
1405                         goto parse_error;
1406                 }
1407                 allowed_params = action_defs[index].params;
1408
1409                 /* alloc memory for action */
1410                 action = (struct route_action *)MALLOC(sizeof(struct route_action));
1411                 rmemuse++;
1412                 *action_pointer = action;
1413                 action_pointer = &(action->next);
1414                 param_pointer = &(action->param_first);
1415                 action->index = index;
1416                 action->line = line[nesting];
1417
1418                 /* skip spaces after param name */
1419                 while(*p == 32)
1420                 {
1421                         if (*p == 0)
1422                                 break;
1423                         p++;
1424                 }
1425
1426                 /* loop PARAMS */
1427                 while(*p != 0) {
1428                         /* read param text */
1429                         i = 0;
1430                         while((*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9')) {
1431                                 if (*p>='A' && *p<='Z') *p = *p-'A'+'a'; /* lower case */
1432                                 key[i++] = *p++;
1433                                 if (i == sizeof(key)) i--; /* limit */
1434                         }
1435                         key[i] = 0;
1436                         if (key[0] == '\0') {
1437                                 SPRINT(failure, "Expecting parameter name.");
1438                                 goto parse_error;
1439                         }
1440
1441                         /* check if item exists */
1442                         index = 0;
1443                         while(param_defs[index].name) {
1444                                 if (!strcmp(param_defs[index].name, key))
1445                                         break;
1446                                 index++;
1447                         }
1448                         if (param_defs[index].name == NULL) {
1449                                 SPRINT(failure, "Unknown param name '%s'.", key);
1450                                 goto parse_error;
1451                         }
1452
1453                         /* check if item is allowed for the action */
1454                         if (!(param_defs[index].id & allowed_params)) {
1455                                 SPRINT(failure, "Param name '%s' exists, but not for this action.", key);
1456                                 goto parse_error;
1457                         }
1458
1459                         /* params without values must not have any parameter */
1460                         if (param_defs[index].type == PARAM_TYPE_NULL) {
1461                                 if (*p!=' ' && *p!='\0') {
1462                                         SPRINT(failure, "Parameter '%s' must not have any value.", key);
1463                                         goto parse_error;
1464                                 }
1465                         } else {
1466                                 if (*p == ' ') {
1467                                         SPRINT(failure, "Parameter '%s' must have at least one value, '=' expected and not a space.", key);
1468                                         goto parse_error;
1469                                 }
1470                                 if (*p != '=') {
1471                                         SPRINT(failure, "Parameter '%s' must have at least one value, '=' expected.", key);
1472                                         goto parse_error;
1473                                 }
1474                                 p++;
1475                         }
1476
1477                         /* special timeout value */
1478                         if (!strcmp("timeout", key)) {
1479                                 if (action->timeout) {
1480                                         SPRINT(failure, "Duplicate timeout value.");
1481                                         goto parse_error;
1482                                 }
1483                                 if (*p==',' || *p==' ' || *p=='\0') {
1484                                         SPRINT(failure, "Missing integer value.");
1485                                         goto parse_error;
1486                                 }
1487                                 integer = 0;
1488                                 while(*p>='0' && *p<='9') {
1489                                         integer = integer*10 + *p-'0';
1490                                         p++;
1491                                 }
1492                                 if (integer < 1) {
1493                                         SPRINT(failure, "Expecting timeout value greater 0.");
1494                                         goto parse_error;
1495                                 }
1496                                 if (*p!=' ' && *p!='\0') {
1497                                         SPRINT(failure, "Character '%c' not expected here. Use ' ' to seperate parameters.", *p);
1498                                         goto parse_error;
1499                                 }
1500                                 /* skip spaces */
1501                                 while(*p == 32) {
1502                                         if (*p == 0)
1503                                                 break;
1504                                         p++;
1505                                 }
1506                                 action->timeout = integer;
1507                                 /* check for next ACTION */
1508                                 if (*p == ':') {
1509                                         p++;
1510                                         goto nextaction;
1511                                 }
1512                                 continue;
1513                         }
1514
1515                         /* check for duplicate parameters */
1516                         param = action->param_first;
1517                         while(param) {
1518                                 if (param->index == index) {
1519                                         SPRINT(failure, "Duplicate parameter '%s', use ',' to give multiple values.", key);
1520                                         goto parse_error;
1521                                 }
1522                                 param = param->next;
1523                         }
1524
1525                         nextparamvalue:
1526                         /* Alloc memory for param */
1527                         param = (struct route_param *)MALLOC(sizeof(struct route_param));
1528                         rmemuse++;
1529                         *param_pointer = param;
1530                         param_pointer = &(param->next);
1531                         param->index = index;
1532                         param->id = param_defs[index].id;
1533
1534                         switch(param_defs[index].type) {
1535                                 /* parse null value */
1536                                 case PARAM_TYPE_NULL:
1537                                 param->value_type = VALUE_TYPE_NULL;
1538                                 break;
1539
1540                                 /* parse integer value */
1541                                 case PARAM_TYPE_INTEGER:
1542                                 integer = 0;
1543                                 if (*p==',' || *p==' ' || *p=='\0') {
1544                                         SPRINT(failure, "Missing integer value.");
1545                                         goto parse_error;
1546                                 }
1547                                 while(*p>='0' && *p<='9') {
1548                                         integer = integer*10 + *p-'0';
1549                                         p++;
1550                                 }
1551                                 param->integer_value = integer;
1552                                 param->value_type = VALUE_TYPE_INTEGER;
1553                                 break;
1554
1555 #if 0
1556                                 /* parse ports value */
1557                                 case PARAM_TYPE_PORTS:
1558                                 key[0] = '\0';
1559                                 if (*p==',' || *p==' ' || *p=='\0') {
1560                                         SPRINT(failure, "Missing port number, omit parameter or give port number.");
1561                                         goto parse_error;
1562                                 }
1563                                 i = 0;
1564                                 nextport:
1565                                 integer = 0;
1566                                 while(*p>='0' && *p<='9') {
1567                                         if (i < (int)sizeof(key)-1) {
1568                                                 key[i] = *p;
1569                                                 key[i++] = '\0';
1570                                         }
1571                                         integer = integer*10 + *p-'0';
1572                                         p++;
1573                                 }
1574                                 if (integer > 255) {
1575                                         SPRINT(failure, "Port number too high.");
1576                                         goto parse_error;
1577                                 }
1578                                 if (*p==',') {
1579                                         if (i < (int)sizeof(key)-1) {
1580                                                 key[i] = *p;
1581                                                 key[i++] = '\0';
1582                                         }
1583                                         p++;
1584                                         goto nextport;
1585                                 }
1586                                 goto mallocstring;
1587 #endif
1588
1589                                 /* parse string value */
1590                                 case PARAM_TYPE_STRING:
1591                                 case PARAM_TYPE_CALLERIDTYPE:
1592                                 case PARAM_TYPE_CAPABILITY:
1593                                 case PARAM_TYPE_BMODE:
1594                                 case PARAM_TYPE_HLC:
1595                                 case PARAM_TYPE_DIVERSION:
1596                                 case PARAM_TYPE_DESTIN:
1597                                 case PARAM_TYPE_TYPE:
1598                                 case PARAM_TYPE_YESNO:
1599                                 case PARAM_TYPE_ON:
1600                                 key[0] = '\0';
1601                                 if (*p==',' || *p==' ' || *p=='\0') {
1602                                         SPRINT(failure, "Missing string value, use \"\" for empty string.");
1603                                         goto parse_error;
1604                                 }
1605                                 p = read_string(p, key, sizeof(key), " ");
1606                                 if (key[0] == 1) { /* error */
1607                                         SPRINT(failure, "Parsing string failed: %s", key+1);
1608                                         goto parse_error;
1609                                 }
1610                                 if (param_defs[index].type == PARAM_TYPE_CALLERIDTYPE) {
1611                                         param->value_type = VALUE_TYPE_INTEGER;
1612                                         if (!strcasecmp(key, "unknown")) {
1613                                                 param->integer_value = INFO_NTYPE_UNKNOWN;
1614                                                 break;
1615                                         }
1616                                         if (!strcasecmp(key, "subscriber")) {
1617                                                 param->integer_value = INFO_NTYPE_SUBSCRIBER;
1618                                                 break;
1619                                         }
1620                                         if (!strcasecmp(key, "national")) {
1621                                                 param->integer_value = INFO_NTYPE_NATIONAL;
1622                                                 break;
1623                                         }
1624                                         if (!strcasecmp(key, "international")) {
1625                                                 param->integer_value = INFO_NTYPE_INTERNATIONAL;
1626                                                 break;
1627                                         }
1628                                         SPRINT(failure, "Caller ID type '%s' unknown.", key);
1629                                         goto parse_error;
1630                                 }
1631                                 if (param_defs[index].type == PARAM_TYPE_ON) {
1632                                         param->value_type = VALUE_TYPE_INTEGER;
1633                                         if (!strcasecmp(key, "init")) {
1634                                                 param->integer_value = INFO_ON_INIT;
1635                                                 break;
1636                                         }
1637                                         if (!strcasecmp(key, "hangup")) {
1638                                                 param->integer_value = INFO_ON_HANGUP;
1639                                                 break;
1640                                         }
1641                                         SPRINT(failure, "Execute on '%s' unknown.", key);
1642                                         goto parse_error;
1643                                 }
1644                                 if (param_defs[index].type == PARAM_TYPE_CAPABILITY) {
1645                                         param->value_type = VALUE_TYPE_INTEGER;
1646                                         if (!strcasecmp(key, "speech")) {
1647                                                 param->integer_value = INFO_BC_SPEECH;
1648                                                 break;
1649                                         }
1650                                         if (!strcasecmp(key, "audio")) {
1651                                                 param->integer_value = INFO_BC_AUDIO;
1652                                                 break;
1653                                         }
1654                                         if (!strcasecmp(key, "video")) {
1655                                                 param->integer_value = INFO_BC_VIDEO;
1656                                                 break;
1657                                         }
1658                                         if (!strcasecmp(key, "digital-restricted")) {
1659                                                 param->integer_value = INFO_BC_DATARESTRICTED;
1660                                                 break;
1661                                         }
1662                                         if (!strcasecmp(key, "digital-unrestricted")) {
1663                                                 param->integer_value = INFO_BC_DATAUNRESTRICTED;
1664                                                 break;
1665                                         }
1666                                         if (!strcasecmp(key, "digital-unrestricted-tones")) {
1667                                                 param->integer_value = INFO_BC_DATAUNRESTRICTED_TONES;
1668                                                 break;
1669                                         }
1670                                         SPRINT(failure, "Service type '%s' unknown.", key);
1671                                         goto parse_error;
1672                                 }
1673                                 if (param_defs[index].type == PARAM_TYPE_BMODE) {
1674                                         param->value_type = VALUE_TYPE_INTEGER;
1675                                         if (!strcasecmp(key, "transparent")) {
1676                                                 param->integer_value = INFO_BMODE_CIRCUIT;
1677                                                 break;
1678                                         }
1679                                         if (!strcasecmp(key, "hdlc")) {
1680                                                 param->integer_value = INFO_BMODE_PACKET;
1681                                                 break;
1682                                         }
1683                                         SPRINT(failure, "Bchannel mode '%s' unknown.", key);
1684                                         goto parse_error;
1685                                 }
1686                                 if (param_defs[index].type == PARAM_TYPE_HLC) {
1687                                         param->value_type = VALUE_TYPE_INTEGER;
1688                                         if (!strcasecmp(key, "telephony")) {
1689                                                 param->integer_value = INFO_HLC_TELEPHONY;
1690                                                 break;
1691                                         }
1692                                         if (!strcasecmp(key, "faxg2g3")) {
1693                                                 param->integer_value = INFO_HLC_FAXG2G3;
1694                                                 break;
1695                                         }
1696                                         if (!strcasecmp(key, "faxg4")) {
1697                                                 param->integer_value = INFO_HLC_FAXG4;
1698                                                 break;
1699                                         }
1700                                         if (!strcasecmp(key, "teletex1")) {
1701                                                 param->integer_value = INFO_HLC_TELETEX1;
1702                                                 break;
1703                                         }
1704                                         if (!strcasecmp(key, "teletex2")) {
1705                                                 param->integer_value = INFO_HLC_TELETEX2;
1706                                                 break;
1707                                         }
1708                                         if (!strcasecmp(key, "teletex3")) {
1709                                                 param->integer_value = INFO_HLC_TELETEX3;
1710                                                 break;
1711                                         }
1712                                         if (!strcasecmp(key, "videotex1")) {
1713                                                 param->integer_value = INFO_HLC_VIDEOTEX1;
1714                                                 break;
1715                                         }
1716                                         if (!strcasecmp(key, "videotex2")) {
1717                                                 param->integer_value = INFO_HLC_VIDEOTEX2;
1718                                                 break;
1719                                         }
1720                                         if (!strcasecmp(key, "telex")) {
1721                                                 param->integer_value = INFO_HLC_TELEX;
1722                                                 break;
1723                                         }
1724                                         if (!strcasecmp(key, "mhs")) {
1725                                                 param->integer_value = INFO_HLC_MHS;
1726                                                 break;
1727                                         }
1728                                         if (!strcasecmp(key, "osi")) {
1729                                                 param->integer_value = INFO_HLC_OSI;
1730                                                 break;
1731                                         }
1732                                         if (!strcasecmp(key, "maintenance")) {
1733                                                 param->integer_value = INFO_HLC_MAINTENANCE;
1734                                                 break;
1735                                         }
1736                                         if (!strcasecmp(key, "management")) {
1737                                                 param->integer_value = INFO_HLC_MANAGEMENT;
1738                                                 break;
1739                                         }
1740                                         if (!strcasecmp(key, "audiovisual")) {
1741                                                 param->integer_value = INFO_HLC_AUDIOVISUAL;
1742                                                 break;
1743                                         }
1744                                         SPRINT(failure, "HLC type '%s' unknown.", key);
1745                                         goto parse_error;
1746                                 }
1747                                 if (param_defs[index].type == PARAM_TYPE_DIVERSION) {
1748                                         param->value_type = VALUE_TYPE_INTEGER;
1749                                         if (!strcasecmp(key, "cfu")) {
1750                                                 param->integer_value = INFO_DIVERSION_CFU;
1751                                                 break;
1752                                         }
1753                                         if (!strcasecmp(key, "cfb")) {
1754                                                 param->integer_value = INFO_DIVERSION_CFB;
1755                                                 break;
1756                                         }
1757                                         if (!strcasecmp(key, "cfnr")) {
1758                                                 param->integer_value = INFO_DIVERSION_CFNR;
1759                                                 break;
1760                                         }
1761                                         if (!strcasecmp(key, "cfp")) {
1762                                                 param->integer_value = INFO_DIVERSION_CFP;
1763                                                 break;
1764                                         }
1765                                         SPRINT(failure, "Diversion type '%s' unknown.", key);
1766                                         goto parse_error;
1767                                 }
1768                                 if (param_defs[index].type == PARAM_TYPE_TYPE) {
1769                                         param->value_type = VALUE_TYPE_INTEGER;
1770                                         if (!strcasecmp(key, "unknown")) {
1771                                                 param->integer_value = INFO_NTYPE_UNKNOWN;
1772                                                 break;
1773                                         }
1774                                         if (!strcasecmp(key, "subscriber")) {
1775                                                 param->integer_value = INFO_NTYPE_SUBSCRIBER;
1776                                                 break;
1777                                         }
1778                                         if (!strcasecmp(key, "national")) {
1779                                                 param->integer_value = INFO_NTYPE_NATIONAL;
1780                                                 break;
1781                                         }
1782                                         if (!strcasecmp(key, "international")) {
1783                                                 param->integer_value = INFO_NTYPE_INTERNATIONAL;
1784                                                 break;
1785                                         }
1786                                         SPRINT(failure, "Number type '%s' unknown.", key);
1787                                         goto parse_error;
1788                                 }
1789                                 if (param_defs[index].type == PARAM_TYPE_YESNO) {
1790                                         param->value_type = VALUE_TYPE_INTEGER;
1791                                         if (!strcasecmp(key, "yes")) {
1792                                                 param->integer_value = 1;
1793                                                 break;
1794                                         }
1795                                         if (!strcasecmp(key, "no")) {
1796                                                 param->integer_value = 0;
1797                                                 break;
1798                                         }
1799                                         SPRINT(failure, "Value '%s' unknown. ('yes' or 'no')", key);
1800                                         goto parse_error;
1801                                 }
1802                                 param->string_value = (char *)MALLOC(strlen(key)+1);
1803                                 rmemuse++;
1804                                 UCPY(param->string_value, key);
1805                                 param->value_type = VALUE_TYPE_STRING;
1806                                 break;
1807
1808                                 default:
1809                                 SPRINT(failure, "Software error: PARAM_TYPE_* %d not parsed in function '%s'", param_defs[index].type, __FUNCTION__);
1810                                 goto parse_error;
1811                         }
1812
1813                         if (*p == ',') {
1814                                 p++;
1815                                 /* next item */
1816                                 param->value_extension = 1;
1817                                 goto nextparamvalue;
1818                         }
1819
1820                         /* end of line */
1821                         if (*p == '\0')
1822                                 break;
1823
1824                         /* to seperate the items, a space is required */
1825                         if (*p != ' ') {
1826                                 SPRINT(failure, "Character '%c' not expected here. Use ' ' to seperate parameters, or ',' for multiple values.", *p);
1827                                 goto parse_error;
1828                         }
1829                         /* skip spaces */
1830                         while(*p == 32)
1831                         {
1832                                 if (*p == 0)
1833                                         break;
1834                                 p++;
1835                         }
1836
1837                         /* check for next ACTION */
1838                         if (*p == ':') {
1839                                 p++;
1840                                 goto nextaction;
1841                         }
1842                 }
1843         }
1844
1845         fclose(fp[nesting--]);
1846         fduse--;
1847
1848         if (nesting >= 0)
1849                 goto go_root;
1850
1851         if (!ruleset_start) {
1852                 SPRINT(failure, "No ruleset defined.");
1853         }
1854         return(ruleset_start);
1855
1856         parse_error:
1857         printf("While parsing %s, an error occurred in line %d:\n", filename[nesting], line[nesting]);
1858         printf("-> %s\n", buffer);
1859         memset(pointer, ' ', sizeof(pointer));
1860         pointer[p-buffer] = '^';
1861         pointer[p-buffer+1] = '\0';
1862         printf("   %s\n", pointer);
1863         printf("%s\n", failure);
1864         SPRINT(ruleset_error, "Error in file %s, line %d: %s",  filename[nesting], line[nesting], failure);
1865
1866         openerror:
1867         while(nesting >= 0) {
1868                 fclose(fp[nesting--]);
1869                 fduse--;
1870         }
1871
1872         ruleset_free(ruleset_start);
1873         return(NULL);
1874 }
1875
1876 /*
1877  * return ruleset by name
1878  */
1879 struct route_ruleset *getrulesetbyname(const char *name)
1880 {
1881         struct route_ruleset *ruleset = ruleset_first;
1882
1883         while(ruleset) {
1884                 if (!strcasecmp(name, ruleset->name)) {
1885                         break;
1886                 }
1887                 ruleset = ruleset->next;
1888         }
1889         PDEBUG(DEBUG_ROUTE, "ruleset %s %s.\n", name, ruleset?"found":"not found");
1890         return(ruleset);
1891 }
1892
1893 /*
1894  * parses the current ruleset and returns action
1895  */
1896 struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset)
1897 {
1898         int                     match,
1899                                 couldmatch = 0, /* any rule could match */
1900                                 istrue,
1901                                 couldbetrue,
1902                                 condition,
1903                                 dialing_required;
1904         struct route_rule       *rule = ruleset->rule_first;
1905         struct route_cond       *cond;
1906         struct route_action     *action = NULL;
1907         unsigned long           comp_len;
1908         int                     j;
1909         char                    isdn_port[10];
1910         char                    *argv[11]; /* check also number of args below */
1911         char                    callerid[64], callerid2[64], redirid[64];
1912         int                     integer;
1913         char                    *string;
1914         FILE                    *tfp;
1915         long long               timeout, now_ll = 0, match_timeout = 0;
1916         struct timeval          current_time;
1917 #ifdef WITH_MISDN
1918         struct mISDNport        *mISDNport;
1919         int                     avail,
1920                                 any;
1921         int                     jj;
1922 #endif
1923         struct admin_list       *admin;
1924         time_t                  now;
1925         struct tm               *now_tm;
1926         int                     pid, status;
1927
1928         /* reset timeout action */
1929         e_match_to_action = NULL;
1930
1931         SCPY(callerid, numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international));
1932         SCPY(callerid2, numberrize_callerinfo(e_callerinfo.id2, e_callerinfo.ntype2, options.national, options.international));
1933         SCPY(redirid, numberrize_callerinfo(e_redirinfo.id, e_redirinfo.ntype, options.national, options.international));
1934         
1935         PDEBUG(DEBUG_ROUTE, "parsing ruleset '%s'\n", ruleset->name);
1936         while(rule) {
1937                 PDEBUG(DEBUG_ROUTE, "checking rule in line %d\n", rule->line);
1938                 match = 1; /* this rule matches */
1939                 dialing_required = 0;
1940                 timeout = 0; /* timeout time */
1941                 cond = rule->cond_first;
1942                 while(cond) {
1943                         condition = 0; /* any condition element is true (1) or could be true (2) */
1944                         checkextension:
1945                         istrue = 0; /* this condition-element is true */
1946                         couldbetrue = 0; /* this conditions-element could be true */
1947                         switch(cond->match) {
1948                                 case MATCH_EXTERN:
1949                                 if (!e_ext.number[0])
1950                                         istrue = 1;      
1951                                 break;
1952
1953                                 case MATCH_INTERN:
1954                                 if (e_ext.number[0])
1955                                         istrue = 1;      
1956                                 break;
1957
1958                                 case MATCH_PORT:
1959 #ifdef WITH_MISDN
1960                                 if (ea_endpoint->ep_portlist)
1961                                 if ((ea_endpoint->ep_portlist->port_type & PORT_CLASS_MASK) != PORT_CLASS_mISDN)
1962                                         break;
1963                                 integer = e_callerinfo.isdn_port;
1964                                 goto match_integer;
1965 #endif
1966                                 break;
1967
1968                                 case MATCH_INTERFACE:
1969                                 if (!e_callerinfo.interface[0])
1970                                         break;
1971                                 string = e_callerinfo.interface;
1972                                 goto match_string;
1973
1974                                 case MATCH_CALLERID:
1975                                 string = callerid;
1976                                 goto match_string_prefix;
1977
1978                                 case MATCH_CALLERID2:
1979                                 string = callerid2;
1980                                 goto match_string_prefix;
1981
1982                                 case MATCH_EXTENSION:
1983                                 string = e_ext.number;
1984                                 goto match_string;
1985
1986                                 case MATCH_DIALING:
1987                                 string = e_dialinginfo.id;
1988                                 goto match_string_prefix;
1989
1990                                 case MATCH_ENBLOCK:
1991                                 if (!e_overlap)
1992                                         istrue = 1;
1993                                 break;
1994
1995                                 case MATCH_OVERLAP:
1996                                 if (e_overlap)
1997                                         istrue = 1;
1998                                 break;
1999
2000                                 case MATCH_ANONYMOUS:
2001                                 if (e_callerinfo.present != INFO_PRESENT_ALLOWED)
2002                                         istrue = 1;
2003                                 break;
2004
2005                                 case MATCH_VISIBLE:
2006                                 if (e_callerinfo.present == INFO_PRESENT_ALLOWED)
2007                                         istrue = 1;
2008                                 break;
2009
2010                                 case MATCH_UNKNOWN:
2011                                 if (e_callerinfo.present == INFO_PRESENT_NOTAVAIL)
2012                                         istrue = 1;
2013                                 break;
2014
2015                                 case MATCH_AVAILABLE:
2016                                 if (e_callerinfo.present != INFO_PRESENT_NOTAVAIL)
2017                                         istrue = 1;
2018                                 break;
2019
2020                                 case MATCH_FAKE:
2021                                 if (e_callerinfo.screen == INFO_SCREEN_USER)
2022                                         istrue = 1;
2023                                 break;
2024
2025                                 case MATCH_REAL:
2026                                 if (e_callerinfo.screen != INFO_SCREEN_USER)
2027                                         istrue = 1;
2028                                 break;
2029
2030                                 case MATCH_REDIRECTED:
2031                                 if (e_redirinfo.ntype != INFO_NTYPE_NOTPRESENT)
2032                                         istrue = 1;
2033                                 break;
2034
2035                                 case MATCH_DIRECT:
2036                                 if (e_redirinfo.ntype == INFO_NTYPE_NOTPRESENT)
2037                                         istrue = 1;
2038                                 break;
2039
2040                                 case MATCH_REDIRID:
2041                                 string = redirid;
2042                                 goto match_string_prefix;
2043
2044                                 case MATCH_TIME:
2045                                 time(&now);
2046                                 now_tm = localtime(&now);
2047                                 integer = now_tm->tm_hour*100 + now_tm->tm_min;
2048                                 goto match_integer;
2049
2050                                 case MATCH_MDAY:
2051                                 time(&now);
2052                                 now_tm = localtime(&now);
2053                                 integer = now_tm->tm_mday;
2054                                 goto match_integer;
2055
2056                                 case MATCH_MONTH:
2057                                 time(&now);
2058                                 now_tm = localtime(&now);
2059                                 integer = now_tm->tm_mon+1;
2060                                 goto match_integer;
2061
2062                                 case MATCH_YEAR:
2063                                 time(&now);
2064                                 now_tm = localtime(&now);
2065                                 integer = now_tm->tm_year + 1900;
2066                                 goto match_integer;
2067
2068                                 case MATCH_WDAY:
2069                                 time(&now);
2070                                 now_tm = localtime(&now);
2071                                 integer = now_tm->tm_wday;
2072                                 integer = integer?integer:7; /* correct sunday */
2073                                 goto match_integer;
2074
2075                                 case MATCH_CAPABILITY:
2076                                 integer = e_capainfo.bearer_capa;
2077                                 goto match_integer;
2078         
2079                                 case MATCH_INFOLAYER1:
2080                                 integer = e_capainfo.bearer_info1;
2081                                 goto match_integer;
2082
2083                                 case MATCH_HLC:
2084                                 integer = e_capainfo.hlc;
2085                                 goto match_integer;
2086
2087                                 case MATCH_FILE:
2088                                 tfp = fopen(cond->string_value, "r");
2089                                 if (!tfp) {
2090                                         break;
2091                                 }
2092                                 if (fgetc(tfp) == '1')
2093                                         istrue = 1;
2094                                 fclose(tfp);
2095                                 break;
2096
2097                                 case MATCH_EXECUTE:
2098                                 j = 0;
2099 #if 0
2100                                 argv[j++] = (char *)"/bin/sh";
2101                                 argv[j++] = (char *)"-c";
2102                                 argv[j++] = cond->string_value;
2103 #endif
2104                                 argv[j++] = cond->string_value;
2105                                 argv[j++] = e_extdialing;
2106                                 argv[j++] = (char *)numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international);
2107                                 argv[j++] = e_callerinfo.extension;
2108                                 argv[j++] = e_callerinfo.name;
2109                                 SPRINT(isdn_port, "%d", e_callerinfo.isdn_port);
2110                                 argv[j++] = isdn_port;
2111                                 argv[j++] = e_callerinfo.imsi;
2112                                 argv[j++] = NULL; /* check also number of args above */
2113                                 switch ((pid = fork())) {
2114                                 case 0:
2115                                         execve(cond->string_value, argv, environ);
2116                                         perror("execve");
2117                                         exit(1);
2118                                 case -1:
2119                                         break;
2120                                 default:
2121                                         waitpid(pid, &status, 0);
2122                                         if (0 == WEXITSTATUS(status))
2123                                                 istrue = 1;
2124                                 }
2125                                 break;
2126
2127                                 case MATCH_DEFAULT:
2128                                 if (!couldmatch)
2129                                         istrue = 1;
2130                                 break;
2131
2132                                 case MATCH_TIMEOUT:
2133                                 if (!now_ll) {
2134                                         gettimeofday(&current_time, NULL);
2135                                         now_ll = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec;
2136                                 }
2137                                 timeout = now_ll + (cond->integer_value * MICRO_SECONDS);
2138                                 istrue = 1;
2139                                 break;
2140
2141                                 case MATCH_FREE:
2142                                 case MATCH_NOTFREE:
2143 #ifdef WITH_MISDN
2144                                 if (!(comp_len = (unsigned long)strchr(cond->string_value, ':')))
2145                                         break;
2146                                 comp_len = comp_len-(unsigned long)cond->string_value;
2147                                 avail = 0;
2148                                 mISDNport = mISDNport_first;
2149                                 while(mISDNport) {
2150                                         if (mISDNport->ifport)
2151                                         if (strlen(mISDNport->ifport->interface->name) == comp_len)
2152                                         if (!strncasecmp(mISDNport->ifport->interface->name, cond->string_value, comp_len)) 
2153                                         if (!mISDNport->l2hold || mISDNport->l2link>0) {
2154                                                 j = 0;
2155                                                 jj = mISDNport->b_num;
2156                                                 avail += jj;
2157                                                 while(j < jj) {
2158                                                         if (mISDNport->b_state[j])
2159                                                                 avail--;
2160                                                         j++;
2161                                                 }
2162                                         }
2163                                         mISDNport = mISDNport->next;
2164                                 }
2165                                 if (cond->match == MATCH_FREE) {
2166                                         if (avail >= atoi(cond->string_value + comp_len + 1))
2167                                                 istrue = 1;
2168                                 } else {
2169                                         if (avail < atoi(cond->string_value + comp_len + 1))
2170                                                 istrue = 1;
2171                                 }
2172 #endif
2173                                 break;
2174
2175
2176                                 case MATCH_DOWN:
2177 #ifdef WITH_MISDN
2178                                 mISDNport = mISDNport_first;
2179                                 while(mISDNport) {
2180                                         if (mISDNport->ifport)
2181                                         if (!strcasecmp(mISDNport->ifport->interface->name, cond->string_value)) 
2182                                         if (!mISDNport->l2hold || mISDNport->l2link>0)
2183                                                 break;
2184                                         mISDNport = mISDNport->next;
2185                                 }
2186                                 if (!mISDNport) /* all down */
2187                                         istrue = 1;
2188 #endif
2189                                 break;
2190
2191                                 case MATCH_UP:
2192 #ifdef WITH_MISDN
2193                                 mISDNport = mISDNport_first;
2194                                 while(mISDNport) {
2195                                         if (mISDNport->ifport)
2196                                         if (!strcasecmp(mISDNport->ifport->interface->name, cond->string_value)) 
2197                                         if (!mISDNport->l2hold || mISDNport->l2link>0)
2198                                                 break;
2199                                         
2200                                         mISDNport = mISDNport->next;
2201                                 }
2202                                 if (mISDNport) /* one link at least */
2203                                         istrue = 1;
2204 #endif
2205                                 break;
2206
2207                                 case MATCH_BUSY:
2208                                 case MATCH_IDLE:
2209 #ifdef WITH_MISDN
2210                                 any = 0;
2211                                 mISDNport = mISDNport_first;
2212                                 while(mISDNport) {
2213                                         if (mISDNport->ifport)
2214                                         if (!strcasecmp(mISDNport->ifport->interface->name, cond->string_value)) 
2215                                         if (mISDNport->use) /* break if in use */
2216                                                 break;
2217                                         mISDNport = mISDNport->next;
2218                                 }
2219                                 if (mISDNport && cond->match==MATCH_BUSY)
2220                                         istrue = 1;
2221                                 if (!mISDNport && cond->match==MATCH_IDLE)
2222                                         istrue = 1;
2223 #endif
2224                                 break;
2225
2226                                 case MATCH_REMOTE:
2227                                 case MATCH_NOTREMOTE:
2228                                 admin = admin_first;
2229                                 while(admin) {
2230                                         if (admin->remote_name[0] && !strcmp(cond->string_value, admin->remote_name))
2231                                                 break;
2232                                         admin = admin->next;
2233                                 }
2234                                 if (admin && cond->match==MATCH_REMOTE)
2235                                         istrue = 1;
2236                                 if (!admin && cond->match==MATCH_NOTREMOTE)
2237                                         istrue = 1;
2238                                 break;
2239
2240                                 default:
2241                                 PERROR("Software error: MATCH_* %d not parsed in function '%s'", cond->match, __FUNCTION__);
2242                                 break;
2243
2244                                 match_integer:
2245                                 if (cond->value_type == VALUE_TYPE_INTEGER) {
2246                                         if (integer != cond->integer_value)
2247                                                 break;
2248                                         istrue = 1;
2249                                         break;
2250                                 }
2251                                 if (cond->value_type == VALUE_TYPE_INTEGER_RANGE) {
2252                                         /* check if negative range (2100 - 700 o'clock) */
2253                                         if (cond->integer_value > cond->integer_value_to) {
2254                                                 if (integer>=cond->integer_value && integer<=cond->integer_value_to)
2255                                                         istrue = 1;
2256                                                 break;
2257                                         }
2258                                         /* range is positive */
2259                                         if (integer>=cond->integer_value && integer<=cond->integer_value_to)
2260                                                 istrue = 1;
2261                                         break;
2262                                 }
2263                                 break;
2264
2265                                 match_string:
2266                                 if (strlen(cond->string_value) != strlen(string))
2267                                         break;
2268                                 /* fall through */
2269                                 match_string_prefix:
2270                                 comp_len = strlen(cond->string_value); /* because we must reach value's length */
2271                                 /* we must have greater or equal length to values */
2272                                 if ((unsigned long)strlen(string) < comp_len) {
2273                                         /* special case for unfinished dialing */
2274                                         if (cond->match == MATCH_DIALING) {
2275                                                 couldbetrue = 1; /* could match */
2276                                                 comp_len = strlen(string);
2277                                         } else {
2278                                                 break;
2279                                         }
2280                                 }
2281                                 /* on single string match */
2282                                 if (cond->value_type == VALUE_TYPE_STRING) {
2283                                         if (!strncmp(string, cond->string_value, comp_len)) {
2284                                                 istrue = 1;
2285                                                 /* must be set for changing 'e_extdialing' */
2286                                                 if (cond->match == MATCH_DIALING)
2287                                                         dialing_required = comp_len;
2288                                                 break;
2289                                         }
2290                                         break;
2291                                 }
2292                                 /* on range match */
2293                                 if (cond->value_type == VALUE_TYPE_STRING_RANGE) {
2294                                         /* check if negative range ("55"-"22") */
2295                                         if (cond->comp_string > 0) {
2296                                                 if (strncmp(string, cond->string_value, comp_len) >= 0) {
2297                                                         istrue = 1;
2298                                                         /* must be set for changing 'e_extdialing' */
2299                                                         if (cond->match == MATCH_DIALING)
2300                                                                 dialing_required = comp_len;
2301                                                         break;
2302                                                 }
2303                                                 if (strncmp(string, cond->string_value_to, comp_len) <= 0) {
2304                                                         /* must be set for changing 'e_extdialing' */
2305                                                         istrue = 1;
2306                                                         if (cond->match == MATCH_DIALING)
2307                                                                 dialing_required = comp_len;
2308                                                         break;
2309                                                 }
2310                                                 break;
2311                                         }
2312                                         /* range is positive */
2313                                         if (strncmp(string, cond->string_value, comp_len) < 0)
2314                                                 break;
2315                                         if (strncmp(string, cond->string_value_to, comp_len) > 0)
2316                                                 break;
2317                                         istrue = 1;
2318                                         if (cond->match == MATCH_DIALING)
2319                                                 dialing_required = comp_len;
2320                                         break;
2321                                 }
2322                                 break;
2323                         }
2324
2325                         /* set current condition */
2326                         if (istrue && !couldbetrue)
2327                                 condition = 1; /* element matches, so condition matches */
2328                         if (istrue && couldbetrue && !condition)
2329                                 condition = 2; /* element could match and other elements don't match, so condition could match */
2330
2331                         /* if not matching or could match */
2332                         if (condition != 1) {
2333                                 /* if we have more values to check */
2334                                 if (cond->value_extension && cond->next) {
2335                                         cond = cond->next;
2336                                         goto checkextension;
2337                                 }
2338                                 match = condition;
2339                                 break;
2340                         }
2341                         
2342                         /* skip exteded values, beacuse we already have one matching value */
2343                         while(cond->value_extension && cond->next)
2344                                 cond = cond->next;
2345
2346                         cond = cond->next;
2347                 }
2348                 if (timeout>now_ll && match==1) { /* the matching rule with timeout in the future */
2349                         if (match_timeout == 0 || timeout < match_timeout) { /* first timeout or lower */
2350                                 /* set timeout in the furture */
2351                                 match_timeout = timeout;
2352                                 e_match_to_action = rule->action_first;
2353                                 e_match_to_extdialing = e_dialinginfo.id + dialing_required;
2354                         }
2355                         match = 0; /* matches in the future */
2356                 }
2357                 if (match == 1) {
2358                         /* matching, we return first action */
2359                         action = rule->action_first;
2360                         match_timeout = 0; /* no timeout */
2361                         e_match_to_action = NULL;
2362                         e_extdialing = e_dialinginfo.id + dialing_required;
2363                         break;
2364                 }
2365                 if (match == 2) {
2366                         /* rule could match if more is dialed */
2367                         couldmatch = 1;
2368                 }
2369                 rule = rule->next;
2370         }
2371         if (match_timeout == 0)
2372                 unsched_timer(&e_match_timeout); /* no timeout */
2373         else {
2374                 schedule_timer(&e_match_timeout, (match_timeout-now_ll) / 1000000, (match_timeout-now_ll) % 1000000);
2375         }
2376         return(action);
2377 }
2378
2379 /*
2380  * parses the current action's parameters and return them
2381  */
2382 struct route_param *EndpointAppPBX::routeparam(struct route_action *action, unsigned long long id)
2383 {
2384         struct route_param *param = action->param_first;
2385
2386         while(param) {
2387                 if (param->id == id)
2388                         break;
2389                 param = param->next;
2390         }
2391         return(param);
2392 }
2393
2394
2395 /*
2396  * internal rules that are not defined by route.conf
2397  */
2398 struct route_action action_password = {
2399         NULL,
2400         NULL,
2401         ACTION_PASSWORD,
2402         0,
2403         0,
2404 };
2405
2406 struct route_action action_password_write = {
2407         NULL,
2408         NULL,
2409         ACTION_PASSWORD_WRITE,
2410         0,
2411         0,
2412 };
2413
2414 struct route_action action_external = {
2415         NULL,
2416         NULL,
2417         ACTION_EXTERNAL,
2418         0,
2419         0,
2420 };
2421
2422 struct route_action action_internal = {
2423         NULL,
2424         NULL,
2425         ACTION_INTERNAL,
2426         0,
2427         0,
2428 };
2429
2430 struct route_action action_vbox = {
2431         NULL,
2432         NULL,
2433         ACTION_VBOX_RECORD,
2434         0,
2435         0,
2436 };
2437
2438 struct route_action action_partyline = {
2439         NULL,
2440         NULL,
2441         ACTION_PARTYLINE,
2442         0,
2443         0,
2444 };
2445
2446 struct route_action action_disconnect = {
2447         NULL,
2448         NULL,
2449         ACTION_DISCONNECT,
2450         0,
2451         0,
2452 };
2453
2454