+ /* copy values */
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
+ return(-1);
+ }
+ SCPY(interface->gsm_ms_name, value);
+
+ /* check if name is used multiple times */
+ searchif = interface_newlist;
+ while(searchif) {
+ if (searchif != interface && searchif->gsm_bs && !strcmp(searchif->gsm_ms_name, interface->gsm_ms_name)) {
+ SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, interface->gsm_ms_name, searchif->gsm_ms_name);
+ return(-1);
+ }
+ searchif = searchif->next;
+ }
+
+ return(0);
+#endif
+}
+static int inter_sip(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_SIP
+ SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
+ return(-1);
+#else
+ char *p;
+
+ interface->sip = 1;
+
+ /* copy values */
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing SIP local peer.\n", filename, line);
+ return(-1);
+ }
+ p = get_seperated(value);
+ SCPY(interface->sip_local_peer, value);
+ SCPY(interface->sip_remote_peer, p);
+
+ return(0);
+#endif
+}
+static int inter_authenticate(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_SIP
+ SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
+ return(-1);
+#else
+ char *p, *q;
+
+ if (!interface->sip) {
+ SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
+ return(-1);
+ }
+
+ /* copy values */
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing SIP user.\n", filename, line);
+ return(-1);
+ }
+ p = get_seperated(value);
+ if (!p[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing SIP password.\n", filename, line);
+ return(-1);
+ }
+ q = get_seperated(p);
+ SCPY(interface->sip_auth_user, value);
+ SCPY(interface->sip_auth_password, p);
+ if (q[0])
+ SCPY(interface->sip_auth_realm, q);
+
+ return(0);
+#endif
+}
+static int options_interval(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_SIP
+ SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
+ return(-1);
+#else
+ if (!interface->sip) {
+ SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
+ return(-1);
+ }
+
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing options interval.\n", filename, line);
+ return(-1);
+ }
+ interface->sip_options_interval = atoi(value);
+
+ return(0);
+#endif
+}
+static int options_asserted_id(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_SIP
+ SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
+ return(-1);
+#else
+ if (!interface->sip) {
+ SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
+ return(-1);
+ }
+
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing asserted caller ID.\n", filename, line);
+ return(-1);
+ }
+ SCPY(interface->sip_asserted_id, value);
+
+ return(0);
+#endif
+}
+static int options_public(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_SIP
+ SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
+ return(-1);
+#else
+ if (!interface->sip) {
+ SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
+ return(-1);
+ }
+ if (interface->sip_stun_server[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Don't specify STUN, if you want to define public IP.\n", filename, line);
+ return(-1);
+ }
+
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing public IP.\n", filename, line);
+ return(-1);
+ }
+ SCPY(interface->sip_public_ip, value);
+
+ return(0);
+#endif
+}
+static int options_stun(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_SIP
+ SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
+ return(-1);
+#else
+ char *p;
+
+ if (!interface->sip) {
+ SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
+ return(-1);
+ }
+ if (interface->sip_public_ip[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Don't specify public IP, if you want to define STUN.\n", filename, line);
+ return(-1);
+ }
+
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing STUN server.\n", filename, line);
+ return(-1);
+ }
+ p = get_seperated(value);
+ if (!p[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing STUN timer.\n", filename, line);
+ return(-1);
+ }
+ SCPY(interface->sip_stun_server, value);
+ interface->sip_stun_interval = atoi(p);
+
+ return(0);
+#endif
+}
+static int inter_rtp_ports(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_SIP
+ SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
+ return(-1);
+#else
+ char *p;
+
+ if (!interface->sip) {
+ SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
+ return(-1);
+ }
+
+ /* copy values */
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing 'from' port.\n", filename, line);
+ return(-1);
+ }
+ p = get_seperated(value);
+ if (!p[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing 'to' port.\n", filename, line);
+ return(-1);
+ }
+ interface->rtp_port_from = atoi(value);
+ interface->rtp_port_to = atoi(p);
+
+ return(0);
+#endif
+}
+static int inter_register(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_SIP
+ SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
+ return(-1);
+#else
+ char *p, *q;
+
+ if (!interface->sip) {
+ SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
+ return(-1);
+ }
+
+ /* copy values */
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing SIP user.\n", filename, line);
+ return(-1);
+ }
+ p = get_seperated(value);
+ if (!p[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing SIP host\n", filename, line);
+ return(-1);
+ }
+ q = get_seperated(p);
+ if (!q[0])
+ interface->sip_register_interval = 0;
+ else
+ interface->sip_register_interval = atoi(q);
+ interface->sip_register = 1;
+ SCPY(interface->sip_register_user, value);
+ SCPY(interface->sip_register_host, p);
+
+ return(0);
+#endif
+}
+static int inter_rtp_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ int supported = 0;
+
+#ifdef WITH_GSM_BS
+ if (interface->gsm_bs)
+ supported = 1;
+#endif
+#ifdef WITH_SIP
+ if (interface->sip)
+ supported = 1;
+#endif
+ if (!supported) {
+ SPRINT(interface_error, "Error in %s (line %d): Interface does not support RTP\n", filename, line);
+ return(-1);
+ }
+
+ if (interface->app != EAPP_TYPE_BRIDGE) {
+ SPRINT(interface_error, "Error in %s (line %d): '%s' requires previous 'bridge' parameter.\n", filename, line, parameter);
+ return(-1);
+ }
+
+ interface->rtp_bridge = 1;
+
+ return(0);
+}
+#if 0
+static int inter_rtp_payload(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_GSM_BS
+ SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
+ return(-1);
+#else
+ if (!interface->gsm_bs) {
+ SPRINT(interface_error, "Error in %s (line %d): This parameter only works for GSM BS side interface\n", filename, line);
+ return(-1);
+ }
+ if (!interface->rtp_bridge) {
+ SPRINT(interface_error, "Error in %s (line %d): This parameter only works here, if RTP bridging is enabled\n", filename, line);
+ return(-1);
+ }
+ if (!value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one payload type\n", filename, line, parameter);
+ return(-1);
+ }
+ if (interface->gsm_bs_payloads == sizeof(interface->gsm_bs_payload_types)) {
+ SPRINT(interface_error, "Error in %s (line %d): Too many payload types defined\n", filename, line);
+ return(-1);
+ }
+ interface->gsm_bs_payload_types[interface->gsm_bs_payloads++] = atoi(value);
+
+ return(0);
+#endif
+}
+#endif
+static int inter_nonotify(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ struct interface_port *ifport;
+
+ /* port in chain ? */
+ if (!interface->ifport) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+ return(-1);
+ }
+ /* goto end of chain */
+ ifport = interface->ifport;
+ while(ifport->next)
+ ifport = ifport->next;
+ ifport->nonotify = 1;
+ return(0);
+}
+#ifdef WITH_SS5
+static int inter_ss5(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ struct interface_port *ifport;
+ char *element;
+
+ /* port in chain ? */
+ if (!interface->ifport) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+ return(-1);
+ }
+ /* goto end of chain */
+ ifport = interface->ifport;
+ while(ifport->next)
+ ifport = ifport->next;
+ ifport->ss5 |= SS5_ENABLE;
+ while((element = strsep(&value, " "))) {
+ if (element[0] == '\0')
+ continue;
+ if (!strcasecmp(element, "connect"))
+ ifport->ss5 |= SS5_FEATURE_CONNECT;
+ else
+ if (!strcasecmp(element, "nodisconnect"))
+ ifport->ss5 |= SS5_FEATURE_NODISCONNECT;
+ else
+ if (!strcasecmp(element, "releaseguardtimer"))
+ ifport->ss5 |= SS5_FEATURE_RELEASEGUARDTIMER;
+ else
+ if (!strcasecmp(element, "bell"))
+ ifport->ss5 |= SS5_FEATURE_BELL;
+ else
+ if (!strcasecmp(element, "pulsedialing"))
+ ifport->ss5 |= SS5_FEATURE_PULSEDIALING;
+ else
+ if (!strcasecmp(element, "delay"))
+ ifport->ss5 |= SS5_FEATURE_DELAY;
+ else
+ if (!strcasecmp(element, "release"))
+ ifport->ss5 |= SS5_FEATURE_RELEASE;
+ else
+ if (!strcasecmp(element, "mute-rx"))
+ ifport->ss5 |= SS5_FEATURE_MUTE_RX;
+ else
+ if (!strcasecmp(element, "mute-tx"))
+ ifport->ss5 |= SS5_FEATURE_MUTE_TX;
+ else
+ if (!strcasecmp(element, "quality"))
+ ifport->ss5 |= SS5_FEATURE_QUALITY;
+ else {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' does not allow value element '%s'.\n", filename, line, parameter, element);
+ return(-1);
+ }
+ }
+ return(0);
+}
+#endif
+static int inter_remote(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ struct interface *searchif;
+
+ if (!value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application name as value.\n", filename, line, parameter);
+ return(-1);
+ }
+ searchif = interface_newlist;
+ while(searchif) {
+ if (interface->remote && !strcmp(interface->remote_app, value)) {
+ SPRINT(interface_error, "Error in %s (line %d): interface '%s' already uses remote application '%s'.\n", filename, line, interface->name, value);
+ return(-1);
+ }
+ searchif = searchif->next;
+ }
+
+ /* goto end of chain again to set application name */
+ interface->remote = 1;
+ SCPY(interface->remote_app, value);
+
+ return(0);
+}
+static int inter_context(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ if (!value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application context as value.\n", filename, line, parameter);
+ return(-1);
+ }
+ SCPY(interface->remote_context, value);
+
+ return(0);
+}
+static int inter_pots_flash(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ struct interface_port *ifport;
+
+ /* port in chain ? */
+ if (!interface->ifport) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+ return(-1);
+ }
+ /* goto end of chain */
+ ifport = interface->ifport;
+ while(ifport->next)
+ ifport = ifport->next;
+
+ ifport->pots_flash = 1;
+ return(0);
+}
+static int inter_pots_ring(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ struct interface_port *ifport;
+
+ /* port in chain ? */
+ if (!interface->ifport) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+ return(-1);
+ }
+ /* goto end of chain */
+ ifport = interface->ifport;
+ while(ifport->next)
+ ifport = ifport->next;
+
+ ifport->pots_ring = 1;
+ return(0);
+}
+static int inter_pots_transfer(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ struct interface_port *ifport;
+
+ /* port in chain ? */
+ if (!interface->ifport) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+ return(-1);
+ }
+ /* goto end of chain */
+ ifport = interface->ifport;
+ while(ifport->next)
+ ifport = ifport->next;
+
+ ifport->pots_transfer = 1;
+ return(0);
+}
+static int inter_shutdown(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ interface->shutdown = 1;
+
+ return(0);
+}
+static int inter_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing destination interface name.\n", filename, line);
+ return(-1);
+ }
+ interface->app = EAPP_TYPE_BRIDGE;
+ SCPY(interface->bridge_if, value);
+
+ return(0);
+}
+
+
+/*
+ * structure of parameters
+ */
+struct interface_param interface_param[] = {
+ { "extension", &inter_extension, "",
+ "If keyword is given, calls to interface are handled as internal extensions."},
+
+ { "extern", &inter_extern, "",
+ "If keyword is given, this interface will be used for external calls.\n"
+ "Calls require an external interface, if the routing action 'extern' is used\nwithout specific interface given.\n"
+ "Calls forwarded by extension's 'settings' also require an external interface."},
+
+ {"tones", &inter_tones, "yes | no",
+ "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
+
+ {"earlyb", &inter_earlyb, "yes | no",
+ "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
+
+ {"hunt", &inter_hunt, "linear | roundrobin",
+ "Select the algorithm for selecting port with free channel."},
+
+ {"port", &inter_port, "<number>",
+ ""},
+ {"portnum", &inter_portnum, "<number>",
+ "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
+ {"portname", &inter_portname, "<name>",
+ "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
+
+ {"block", &inter_block, "",
+ "If keyword is given, calls on this interface are blocked.\n"
+ "This parameter must follow a 'port' parameter."},
+
+ {"ptp", &inter_ptp, "",
+ "The given port above is opened as point-to-point.\n"
+ "This is required on NT-mode ports that are multipoint by default.\n"
+ "This parameter must follow a 'port' parameter."},
+
+#if 0
+ {"ptmp", &inter_ptmp, "",
+ "The given port above is opened as point-to-multipoint.\n"
+ "This is required on PRI NT-mode ports that are point-to-point by default.\n"
+ "This parameter must follow a 'port' parameter."},
+#endif
+
+ {"nt", &inter_nt, "",
+ "The given port above is opened in NT-mode.\n"
+ "This is required on interfaces that support both NT-mode and TE-mode.\n"
+ "This parameter must follow a 'port' parameter."},
+
+ {"te-special", &inter_tespecial, "",
+ "The given port uses a modified TE-mode.\n"
+ "All information elements that are allowed Network->User will then be\n"
+ "transmitted User->Network also. This is usefull to pass all informations\n"
+ "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
+ "Note that this is not compliant with ISDN protocol.\n"
+ "This parameter must follow a 'port' parameter."},
+
+ {"layer1hold", &inter_l1hold, "yes | no",
+ "The given port will not release layer 1 after layer 2 is down.\n"
+ "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
+ "This parameter must follow a 'port' parameter."},
+
+ {"layer2hold", &inter_l2hold, "yes | no",
+ "The given port will continuously try to establish layer 2 link and hold it.\n"
+ "It is required for PTP links in most cases, therefore it is default.\n"
+ "This parameter must follow a 'port' parameter."},
+
+ {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
+ "Channel selection list for all outgoing calls to the interface.\n"
+ "A free channels is searched in order of appearance.\n"
+ "This parameter must follow a 'port' parameter.\n"
+ " force - Forces the selected port with no acceptable alternative (see Q.931).\n"
+ " -> this will be automatically set for multipoint (ptmp) NT-mode ports\n"
+ " <number>[,...] - List of channels to search.\n"