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