+ if (interface->ifscreen_in) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
+ return(-1);
+ }
+
+ /* process list */
+ p = value;
+ while(*p) {
+ el = p;
+ p = get_seperated(p);
+ /* add MSN to list */
+ ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
+ memuse++;
+ /* set value */
+ SCPY(ifmsn->msn, el);
+ /* tail port */
+ ifmsnp = &interface->ifmsn;
+ while(*ifmsnp)
+ ifmsnp = &((*ifmsnp)->next);
+ *ifmsnp = ifmsn;
+ }
+ return(0);
+}
+static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ struct interface_screen *ifscreen;
+ char *p, *el;
+
+ if (!value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
+ return(-1);
+ }
+ /* add screen entry to list*/
+ ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
+ memuse++;
+ ifscreen->match_type = -1; /* unchecked */
+ ifscreen->match_present = -1; /* unchecked */
+ ifscreen->result_type = -1; /* unchanged */
+ ifscreen->result_present = -1; /* unchanged */
+ /* tail port */
+ while(*ifscreenp)
+ ifscreenp = &((*ifscreenp)->next);
+ *ifscreenp = ifscreen;
+// printf("interface=%s\n", interface->name);
+ /* get match */
+ p = value;
+ while(*p) {
+ el = p;
+ p = get_seperated(p);
+ if (!strcasecmp(el, "unknown")) {
+ if (ifscreen->match_type != -1) {
+ typeerror:
+ SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
+ return(-1);
+ }
+ ifscreen->match_type = INFO_NTYPE_UNKNOWN;
+ } else
+ if (!strcasecmp(el, "subscriber")) {
+ if (ifscreen->match_type != -1)
+ goto typeerror;
+ ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
+ } else
+ if (!strcasecmp(el, "national")) {
+ if (ifscreen->match_type != -1)
+ goto typeerror;
+ ifscreen->match_type = INFO_NTYPE_NATIONAL;
+ } else
+ if (!strcasecmp(el, "international")) {
+ if (ifscreen->match_type != -1)
+ goto typeerror;
+ ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
+ } else
+ if (!strcasecmp(el, "allowed")) {
+ if (ifscreen->match_present != -1) {
+ presenterror:
+ SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
+ return(-1);
+ }
+ ifscreen->match_present = INFO_PRESENT_ALLOWED;
+ } else
+ if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted")) {
+ if (ifscreen->match_present != -1)
+ goto presenterror;
+ ifscreen->match_present = INFO_PRESENT_RESTRICTED;
+ } else {
+ SCPY(ifscreen->match, el);
+ /* check for % at the end */
+ if (strchr(el, '%')) {
+ if (strchr(el, '%') != el+strlen(el)-1) {
+ SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
+ return(-1);
+ }
+ }
+ break;
+ }
+ }
+ if (ifscreen->match[0] == '\0') {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
+ return(-1);
+ }
+ /* get result */
+ while(*p) {
+ el = p;
+ p = get_seperated(p);
+ if (!strcasecmp(el, "unknown")) {
+ if (ifscreen->result_type != -1)
+ goto typeerror;
+ ifscreen->result_type = INFO_NTYPE_UNKNOWN;
+ } else
+ if (!strcasecmp(el, "subscriber")) {
+ if (ifscreen->result_type != -1)
+ goto typeerror;
+ ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
+ } else
+ if (!strcasecmp(el, "national")) {
+ if (ifscreen->result_type != -1)
+ goto typeerror;
+ ifscreen->result_type = INFO_NTYPE_NATIONAL;
+ } else
+ if (!strcasecmp(el, "international")) {
+ if (ifscreen->result_type != -1)
+ goto typeerror;
+ ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
+ } else
+ if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow")) {
+ if (ifscreen->result_present != -1)
+ goto presenterror;
+ ifscreen->result_present = INFO_PRESENT_ALLOWED;
+ } else
+ if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied")) {
+ if (ifscreen->result_present != -1)
+ goto presenterror;
+ ifscreen->result_present = INFO_PRESENT_RESTRICTED;
+ } else {
+ SCPY(ifscreen->result, el);
+ /* check for % at the end */
+ if (strchr(el, '%')) {
+ if (strchr(el, '%') != el+strlen(el)-1) {
+ SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
+ return(-1);
+ }
+ }
+ break;
+ }
+ }
+ if (ifscreen->result[0] == '\0') {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
+ return(-1);
+ }
+ return(0);
+}
+static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ if (interface->ifmsn) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
+ return(-1);
+ }
+
+ return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
+}
+static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
+}
+static int inter_nodtmf(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->nodtmf = 1;
+ return(0);
+}
+static int inter_dtmf_threshold(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->dtmf_threshold = atoi(value);
+ return(0);
+}
+static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ char *p, *q;
+
+ /* seperate parameter from filter */
+ p = value;
+ while(*p > 32)
+ p++;
+ if (*p) {
+ *p++ = 0;
+ while(*p > 0 && *p <= 32)
+ p++;
+ }
+
+ if (!strcasecmp(value, "gain")) {
+ q = p;
+ while(*q > 32)
+ q++;
+ if (*q) {
+ *q++ = 0;
+ while(*q > 0 && *q <= 32)
+ q++;
+ }
+ if (*p == 0 || *q == 0) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
+ return(-1);
+ }
+ if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
+ return(-1);
+ }
+ interface->tx_gain = atoi(p);
+ interface->rx_gain = atoi(q);
+ } else
+ if (!strcasecmp(value, "pipeline")) {
+ if (*p == 0) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
+ return(-1);
+ }
+ SCPY(interface->pipeline, p);
+ } else
+ if (!strcasecmp(value, "blowfish")) {
+ unsigned char key[56];
+ int l;
+
+ if (!!strncmp(p, "0x", 2)) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
+ return(-1);
+ }
+ p += 2;
+ l = 0;
+ while(*p) {
+ if (l == 56) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
+ return(-1);
+ }
+ if (*p >= '0' && *p <= '9')
+ key[l] = (*p-'0')<<4;
+ else if (*p >= 'a' && *p <= 'f')
+ key[l] = (*p-'a'+10)<<4;
+ else if (*p >= 'A' && *p <= 'F')
+ key[l] = (*p-'A'+10)<<4;
+ else {
+ digout:
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key has digits out of range. (0...9, a...f)\n", filename, line, parameter, value);
+ return(-1);
+ }
+ p++;
+ if (*p == 0) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key must end on an 8 bit boundary (two character boundary).\n", filename, line, parameter, value);
+ return(-1);
+ }
+ if (*p >= '0' && *p <= '9')
+ key[l] = (*p-'0')<<4;
+ else if (*p >= 'a' && *p <= 'f')
+ key[l] = (*p-'a'+10)<<4;
+ else if (*p >= 'A' && *p <= 'F')
+ key[l] = (*p-'A'+10)<<4;
+ else
+ goto digout;
+ p++;
+ l++;
+ }
+ if (l < 4) {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key must be at least 4 bytes (8 characters).\n", filename, line, parameter, value);
+ return(-1);
+ }
+ memcpy(interface->bf_key, key, l);
+ interface->bf_len = l;
+ } else {
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
+ return(-1);
+ }
+ return(0);
+}
+static int inter_dialmax(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->dialmax = atoi(value);
+ return(0);
+}
+static int inter_tones_dir(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ if (!value || !value[0]) {
+ SPRINT(interface_error, "Error in %s (line %d): Missing tones directory.\n", filename, line);
+ return(-1);
+ }
+ SCPY(interface->tones_dir, value);
+
+ return(0);
+}
+static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+ SPRINT(interface_error, "Error in %s (line %d): parameter '%s' is outdated.\nPlease use 'gsm-bs' for base station or 'gsm-ms' for mobile station interface!\n", filename, line, parameter);
+ return(-1);
+}
+static int inter_gsm_bs(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
+ struct interface *searchif;
+
+ interface->gsm_bs = 1;
+
+ if (!value)
+ interface->gsm_bs_name[0] = '\0';
+ else
+ SCPY(interface->gsm_bs_name, value);
+
+ /* check if name is used multiple times */
+ searchif = interface_newlist;
+ while(searchif) {
+ if (searchif != interface && searchif->gsm_bs && !strcmp(searchif->gsm_bs_name, interface->gsm_bs_name)) {
+ SPRINT(interface_error, "Error in %s (line %d): network '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, interface->gsm_bs_name, searchif->gsm_bs_name);
+ return(-1);
+ }
+ searchif = searchif->next;
+ }
+
+ return(0);
+#endif
+}
+static int inter_gsm_bs_hr(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
+ interface->gsm_bs_hr = 1;
+
+ return(0);
+#endif
+}
+static int inter_gsm_ms(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifndef WITH_GSM_MS
+ SPRINT(interface_error, "Error in %s (line %d): GSM MS side not compiled in.\n", filename, line);
+ return(-1);
+#else
+ struct interface *searchif;
+
+ interface->gsm_ms = 1;
+
+ /* 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);