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