added filter options (gain, pipeline, blowfish) to interface configuration.
[lcr.git] / interface.c
index 95973f5..b2995ff 100644 (file)
@@ -186,6 +186,31 @@ static int inter_ptmp(struct interface *interface, char *filename, int line, cha
        ifport->ptmp = 1;
        return(0);
 }
+static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+#ifdef SOCKET_MISDN
+       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;
+       /* add value */
+       if (value[0])
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
+               return(-1);
+       }
+       ifport->nt = 1;
+#endif
+       return(0);
+}
 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
 {
        if (!strcasecmp(value, "yes"))
@@ -454,9 +479,6 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
                SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
                return(-1);
        }
-       p = value;
-       el = p;
-       p = get_seperated(p);
        /* add screen entry to list*/
        ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
        memuse++;
@@ -468,7 +490,9 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
        while(*ifscreenp)
                ifscreenp = &((*ifscreenp)->next);
        *ifscreenp = ifscreen;
+//     printf("interface=%s\n", interface->name);
        /* get match */
+       p = value;
        while(*p)
        {
                el = p;
@@ -511,7 +535,7 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
                        }
                        ifscreen->match_present = INFO_PRESENT_ALLOWED;
                } else
-               if (!strcasecmp(el, "restricted"))
+               if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
                {
                        if (ifscreen->match_present != -1)
                                goto presenterror;
@@ -570,7 +594,7 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
                                goto presenterror;
                        ifscreen->result_present = INFO_PRESENT_ALLOWED;
                } else
-               if (!strcasecmp(el, "restricted"))
+               if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
                {
                        if (ifscreen->result_present != -1)
                                goto presenterror;
@@ -627,13 +651,116 @@ static int inter_nodtmf(struct interface *interface, char *filename, int line, c
        ifport->nodtmf = 1;
        return(0);
 }
-#warning filter to be done
-#if 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->gain_tx = atoi(p);
+               interface->gain_rx = 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);
 }
-#endif
 
 
 /*
@@ -667,6 +794,14 @@ struct interface_param interface_param[] = {
        "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."},
+       {"nt", &inter_nt, "",
+       "The given port above is opened in NT-mode.\n"
+#ifdef SOCKET_MISDN
+       "This is required on interfaces that support both NT-mode and TE-mode.\n"
+#else
+       "This parameter is only required for socket based mISDN driver.\n"
+#endif
+       "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"
@@ -678,7 +813,7 @@ struct interface_param interface_param[] = {
        " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
        " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
 
-       {"channel-in", &inter_channel_in, "[force,][<number>][,...][,free][,any][,no]",
+       {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
        "Channel selection list for all incomming calls from the interface.\n"
        "A free channels is accepted if in the list.\n"
        "If any channel was requested, the first free channel found is selected.\n"
@@ -710,12 +845,17 @@ struct interface_param interface_param[] = {
        "This parameter must follow a 'port' parameter."},
 
 #if 0
-#warning todo: filter, also in the PmISDN object
-       {"filter", &inter_filter, "<filter> [parameters]",
+       {"layer2keep", &inter_layer2keep, "yes | no",
+       "By default, layer 2 is establised and kept up on PTP interfaces.\n"
+       ".\n"
+       "This parameter must follow a 'port' parameter."},
+#endif
+
+       {"filter", &inter_filter, "<filter> <parameters>",
        "Adds/appends a filter. Filters are ordered in transmit direction.\n"
        "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
+       "pipeline <string> - Sets echo cancelation pipeline.\n"
        "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
-#endif
 
        {NULL, NULL, NULL, NULL}
 };
@@ -895,7 +1035,6 @@ void free_interfaces(struct interface *interface)
        struct select_channel *selchannel;
        struct interface_msn *ifmsn;
        struct interface_screen *ifscreen;
-       struct interface_filter *iffilter;
 
        while(interface)
        {
@@ -947,14 +1086,6 @@ void free_interfaces(struct interface *interface)
                        FREE(temp, sizeof(struct interface_screen));
                        memuse--;
                }
-               iffilter = interface->iffilter;
-               while(iffilter)
-               {
-                       temp = iffilter;
-                       iffilter = iffilter->next;
-                       FREE(temp, sizeof(struct interface_filter));
-                       memuse--;
-               }
                temp = interface;
                interface = interface->next;
                FREE(temp, sizeof(struct interface));
@@ -1074,7 +1205,7 @@ void load_port(struct interface_port *ifport)
        struct mISDNport *mISDNport;
 
        /* open new port */
-       mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp, ifport->interface);
+       mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp, ifport->nt, ifport->interface);
        if (mISDNport)
        {
                /* link port */
@@ -1114,3 +1245,156 @@ void doc_interface(void)
        }
 }
 
+
+/* screen caller id
+ * out==0: incomming caller id, out==1: outgoing caller id
+ */
+void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
+{
+       char                    *msn1;
+       struct interface_msn    *ifmsn;
+       struct interface_screen *ifscreen;
+       char suffix[64];
+
+       /* screen incoming caller id */
+       if (!out)
+       {
+               /* check for MSN numbers, use first MSN if no match */
+               msn1 = NULL;
+               ifmsn = interface->ifmsn;
+               while(ifmsn)
+               {
+                       if (!msn1)
+                               msn1 = ifmsn->msn;
+                       if (!strcmp(ifmsn->msn, id))
+                       {
+                               break;
+                       }
+                       ifmsn = ifmsn->next;
+               }
+               if (ifmsn)
+               {
+                       start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (fount in MSN list)");
+                       add_trace("msn", NULL, "%s", id);
+                       end_trace();
+               }
+               if (!ifmsn && msn1) // not in list, first msn given
+               {
+                       start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (not fount in MSN list)");
+                       add_trace("msn", "given", "%s", id);
+                       add_trace("msn", "used", "%s", msn1);
+                       end_trace();
+                       UNCPY(id, msn1, idsize);
+                       id[idsize-1] = '\0';
+               }
+       }
+
+       /* check screen list */
+       if (out)
+               ifscreen = interface->ifscreen_out;
+       else
+               ifscreen = interface->ifscreen_in;
+       while (ifscreen)
+       {
+               if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
+               if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
+               {
+                       if (strchr(ifscreen->match,'%'))
+                       {
+                               if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
+                                       break;
+                       } else
+                       {
+                               if (!strcmp(ifscreen->match, id))
+                                       break;
+                       }
+               }
+               ifscreen = ifscreen->next;
+       }
+       if (ifscreen) // match
+       {
+               start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (fount in screen list)");
+               switch(*type)
+               {
+                       case INFO_NTYPE_UNKNOWN:
+                       add_trace("given", "type", "unknown");
+                       break;
+                       case INFO_NTYPE_SUBSCRIBER:
+                       add_trace("given", "type", "subscriber");
+                       break;
+                       case INFO_NTYPE_NATIONAL:
+                       add_trace("given", "type", "national");
+                       break;
+                       case INFO_NTYPE_INTERNATIONAL:
+                       add_trace("given", "type", "international");
+                       break;
+               }
+               switch(*present)
+               {
+                       case INFO_PRESENT_ALLOWED:
+                       add_trace("given", "present", "allowed");
+                       break;
+                       case INFO_PRESENT_RESTRICTED:
+                       add_trace("given", "present", "restricted");
+                       break;
+                       case INFO_PRESENT_NOTAVAIL:
+                       add_trace("given", "present", "not available");
+                       break;
+               }
+               add_trace("given", "id", "%s", id[0]?id:"<empty>");
+               if (ifscreen->result_type != -1)
+               {
+                       *type = ifscreen->result_type;
+                       switch(*type)
+                       {
+                               case INFO_NTYPE_UNKNOWN:
+                               add_trace("used", "type", "unknown");
+                               break;
+                               case INFO_NTYPE_SUBSCRIBER:
+                               add_trace("used", "type", "subscriber");
+                               break;
+                               case INFO_NTYPE_NATIONAL:
+                               add_trace("used", "type", "national");
+                               break;
+                               case INFO_NTYPE_INTERNATIONAL:
+                               add_trace("used", "type", "international");
+                               break;
+                       }
+               }
+               if (ifscreen->result_present != -1)
+               {
+                       *present = ifscreen->result_present;
+                       switch(*present)
+                       {
+                               case INFO_PRESENT_ALLOWED:
+                               add_trace("used", "present", "allowed");
+                               break;
+                               case INFO_PRESENT_RESTRICTED:
+                               add_trace("used", "present", "restricted");
+                               break;
+                               case INFO_PRESENT_NOTAVAIL:
+                               add_trace("used", "present", "not available");
+                               break;
+                       }
+               }
+               if (strchr(ifscreen->match,'%'))
+               {
+                       SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
+                       UNCPY(id, ifscreen->result, idsize);
+                       id[idsize-1] = '\0';
+                       if (strchr(id,'%'))
+                       {
+                               *strchr(id,'%') = '\0';
+                               UNCAT(id, suffix, idsize);
+                               id[idsize-1] = '\0';
+                       }
+               } else
+               {
+                       UNCPY(id, ifscreen->result, idsize);
+                       id[idsize-1] = '\0';
+               }
+               add_trace("used", "id", "%s", id[0]?id:"<empty>");
+               end_trace();
+       }
+}
+