added exporting/importing bchannel stacks to the remote application
[lcr.git] / interface.c
index 8ff0932..9842e19 100644 (file)
@@ -18,62 +18,44 @@ struct interface *interface_first = NULL; /* first interface is current list */
 struct interface *interface_newlist = NULL; /* first interface in new list */
 
 
 struct interface *interface_newlist = NULL; /* first interface in new list */
 
 
-/* set default selchannel */
-void default_selchannel(struct interface_port *ifport)
+/* set default out_channel */
+void default_out_channel(struct interface_port *ifport)
 {
        struct select_channel *selchannel, **selchannelp;
 
 {
        struct select_channel *selchannel, **selchannelp;
 
-       /* channel selection for TE-ports */
-       if (!ifport->mISDNport->ntmode)
+       selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
+       memuse++;
+       
+       if (ifport->mISDNport->ntmode)
+               selchannel->channel = CHANNEL_FREE;
+       else
+               selchannel->channel = CHANNEL_ANY;
+       
+       ifport->out_channel = selchannel;
+
+       /* additional channel selection for multipoint NT ports */
+       if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
        {
        {
-               selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-               if (!selchannel)
-               {
-                       PERROR("No memory!");
-                       return;
-               }
+               selchannelp = &(selchannel->next);
+               selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
                memuse++;
                memuse++;
-               memset(*selchannelp, 0, sizeof(struct select_channel));
-               *selchannelp->channel = SEL_CHANNEL_ANY;
-               selchannelp = &ifport->selchannel;
-               while(*selchannelp)
-                       selchannelp = &((*selchannelp)->next);
+               selchannel->channel = CHANNEL_NO; // call waiting
                *selchannelp = selchannel;
                *selchannelp = selchannel;
-               return(0);
        }
        }
+}
 
 
-       /* channel selection for NT-ports */
-       selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-       if (!selchannel)
-       {
-               PERROR("No memory!");
-               return;
-       }
+
+/* set default in_channel */
+void default_in_channel(struct interface_port *ifport)
+{
+       struct select_channel *selchannel;
+
+       selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
        memuse++;
        memuse++;
-       memset(*selchannelp, 0, sizeof(struct select_channel));
-       *selchannelp->channel = SEL_CHANNEL_FREE;
-       selchannelp = &ifport->selchannel;
-       while(*selchannelp)
-               selchannelp = &((*selchannelp)->next);
-       *selchannelp = selchannel;
-
-       /* additional channel selection for multipoint ports */
-       if (!ifport->mISDNport->ptp)
-       {
-               selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-               if (!selchannel)
-               {
-                       PERROR("No memory!");
-                       return;
-               }
-               memuse++;
-               memset(*selchannelp, 0, sizeof(struct select_channel));
-               *selchannelp->channel = SEL_CHANNEL_NO; // call waiting
-               selchannelp = &ifport->selchannel;
-               while(*selchannelp)
-                       selchannelp = &((*selchannelp)->next);
-               *selchannelp = selchannel;
-       }
+       
+       selchannel->channel = CHANNEL_FREE;
+       
+       ifport->in_channel = selchannel;
 }
 
 
 }
 
 
@@ -158,6 +140,11 @@ static int inter_ptp(struct interface *interface, char *filename, int line, char
                SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
                return(-1);
        }
                SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
                return(-1);
        }
+       if (interface->ifport->ptmp)
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter);
+               return(-1);
+       }
        /* goto end of chain */
        ifport = interface->ifport;
        while(ifport->next)
        /* goto end of chain */
        ifport = interface->ifport;
        while(ifport->next)
@@ -171,6 +158,34 @@ static int inter_ptp(struct interface *interface, char *filename, int line, char
        ifport->ptp = 1;
        return(0);
 }
        ifport->ptp = 1;
        return(0);
 }
+static int inter_ptmp(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);
+       }
+       if (interface->ifport->ptp)
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\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->ptmp = 1;
+       return(0);
+}
 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
 {
        if (!strcasecmp(value, "yes"))
 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
 {
        if (!strcasecmp(value, "yes"))
@@ -223,7 +238,6 @@ static int inter_port(struct interface *interface, char *filename, int line, cha
 {
        struct interface_port *ifport, **ifportp;
        struct interface *searchif;
 {
        struct interface_port *ifport, **ifportp;
        struct interface *searchif;
-       struct interface_port *searchport;
        int val;
 
        val = get_number(value);
        int val;
 
        val = get_number(value);
@@ -236,7 +250,7 @@ static int inter_port(struct interface *interface, char *filename, int line, cha
        searchif = interface_newlist;
        while(searchif)
        {
        searchif = interface_newlist;
        while(searchif)
        {
-               searchport = searchif->ifport;
+               ifport = searchif->ifport;
                while(ifport)
                {
                        if (ifport->portnum == val)
                while(ifport)
                {
                        if (ifport->portnum == val)
@@ -249,14 +263,8 @@ static int inter_port(struct interface *interface, char *filename, int line, cha
                searchif = searchif->next;
        }
        /* alloc port substructure */
                searchif = searchif->next;
        }
        /* alloc port substructure */
-       ifport = (struct interface_port *)malloc(sizeof(struct interface_port));
-       if (!ifport)
-       {
-               SPRINT(interface_error, "No memory!");
-               return(-1);
-       }
+       ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
        memuse++;
        memuse++;
-       memset(ifport, 0, sizeof(struct interface_port));
        ifport->interface = interface;
        /* set value */
        ifport->portnum = val;
        ifport->interface = interface;
        /* set value */
        ifport->portnum = val;
@@ -292,7 +300,7 @@ static int inter_channel_out(struct interface *interface, char *filename, int li
                if (!strcasecmp(el, "force"))
                {
                        ifport->channel_force = 1;
                if (!strcasecmp(el, "force"))
                {
                        ifport->channel_force = 1;
-                       if (ifport->selchannel)
+                       if (ifport->out_channel)
                        {
                                SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
                                return(-1);
                        {
                                SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
                                return(-1);
@@ -300,17 +308,17 @@ static int inter_channel_out(struct interface *interface, char *filename, int li
                } else
                if (!strcasecmp(el, "any"))
                {
                } else
                if (!strcasecmp(el, "any"))
                {
-                       val = SEL_CHANNEL_ANY;
+                       val = CHANNEL_ANY;
                        goto selchannel;
                } else
                if (!strcasecmp(el, "free"))
                {
                        goto selchannel;
                } else
                if (!strcasecmp(el, "free"))
                {
-                       val = SEL_CHANNEL_FREE;
+                       val = CHANNEL_FREE;
                        goto selchannel;
                } else
                if (!strcasecmp(el, "no"))
                {
                        goto selchannel;
                } else
                if (!strcasecmp(el, "no"))
                {
-                       val = SEL_CHANNEL_NO;
+                       val = CHANNEL_NO;
                        goto selchannel;
                } else
                {
                        goto selchannel;
                } else
                {
@@ -328,18 +336,12 @@ static int inter_channel_out(struct interface *interface, char *filename, int li
                        }
                        selchannel:
                        /* add to select-channel list */
                        }
                        selchannel:
                        /* add to select-channel list */
-                       selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-                       if (!selchannel)
-                       {
-                               SPRINT(interface_error, "No memory!");
-                               return(-1);
-                       }
+                       selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
                        memuse++;
                        memuse++;
-                       memset(selchannel, 0, sizeof(struct select_channel));
                        /* set value */
                        selchannel->channel = val;
                        /* tail port */
                        /* set value */
                        selchannel->channel = val;
                        /* tail port */
-                       selchannelp = &ifport->selchannel;
+                       selchannelp = &ifport->out_channel;
                        while(*selchannelp)
                                selchannelp = &((*selchannelp)->next);
                        *selchannelp = selchannel;
                        while(*selchannelp)
                                selchannelp = &((*selchannelp)->next);
                        *selchannelp = selchannel;
@@ -369,14 +371,14 @@ static int inter_channel_in(struct interface *interface, char *filename, int lin
        {
                el = p;
                p = get_seperated(p);
        {
                el = p;
                p = get_seperated(p);
-               if (ifport->in_select) if (ifport->in_select->channel == SEL_CHANNEL_FREE)
+               if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
                {
                        SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
                                return(-1);
                }
                if (!strcasecmp(el, "free"))
                {
                {
                        SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
                                return(-1);
                }
                if (!strcasecmp(el, "free"))
                {
-                       val = SEL_CHANNEL_FREE;
+                       val = CHANNEL_FREE;
                        goto selchannel;
                } else
                {
                        goto selchannel;
                } else
                {
@@ -394,18 +396,12 @@ static int inter_channel_in(struct interface *interface, char *filename, int lin
                        }
                        selchannel:
                        /* add to select-channel list */
                        }
                        selchannel:
                        /* add to select-channel list */
-                       selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-                       if (!selchannel)
-                       {
-                               SPRINT(interface_error, "No memory!");
-                               return(-1);
-                       }
+                       selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
                        memuse++;
                        memuse++;
-                       memset(selchannel, 0, sizeof(struct select_channel));
                        /* set value */
                        selchannel->channel = val;
                        /* tail port */
                        /* set value */
                        selchannel->channel = val;
                        /* tail port */
-                       selchannelp = &ifport->in_select;
+                       selchannelp = &ifport->in_channel;
                        while(*selchannelp)
                                selchannelp = &((*selchannelp)->next);
                        *selchannelp = selchannel;
                        while(*selchannelp)
                                selchannelp = &((*selchannelp)->next);
                        *selchannelp = selchannel;
@@ -436,14 +432,8 @@ static int inter_msn(struct interface *interface, char *filename, int line, char
                el = p;
                p = get_seperated(p);
                /* add MSN to list */
                el = p;
                p = get_seperated(p);
                /* add MSN to list */
-               ifmsn = (struct interface_msn *)malloc(sizeof(struct interface_msn));
-               if (!ifmsn)
-               {
-                       SPRINT(interface_error, "No memory!");
-                       return(-1);
-               }
+               ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
                memuse++;
                memuse++;
-               memset(ifmsn, 0, sizeof(struct interface_msn));
                /* set value */
                SCPY(ifmsn->msn, el);
                /* tail port */
                /* set value */
                SCPY(ifmsn->msn, el);
                /* tail port */
@@ -468,15 +458,10 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
        el = p;
        p = get_seperated(p);
        /* add screen entry to list*/
        el = p;
        p = get_seperated(p);
        /* add screen entry to list*/
-       ifscreen = (struct interface_screen *)malloc(sizeof(struct interface_screen));
-       if (!ifscreen)
-       {
-               SPRINT(interface_error, "No memory!");
-               return(-1);
-       }
+       ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
        memuse++;
        memuse++;
-       memset(ifscreen, 0, sizeof(struct interface_screen));
-#warning handle unchanged as unchanged!!
+       ifscreen->match_type = -1; /* unchecked */
+       ifscreen->match_present = -1; /* unchecked */
        ifscreen->result_type = -1; /* unchanged */
        ifscreen->result_present = -1; /* unchanged */
        /* tail port */
        ifscreen->result_type = -1; /* unchanged */
        ifscreen->result_present = -1; /* unchanged */
        /* tail port */
@@ -521,7 +506,7 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
                        if (ifscreen->match_present != -1)
                        {
                                presenterror:
                        if (ifscreen->match_present != -1)
                        {
                                presenterror:
-                               SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line, parameter);
+                               SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
                                return(-1);
                        }
                        ifscreen->match_present = INFO_PRESENT_ALLOWED;
                                return(-1);
                        }
                        ifscreen->match_present = INFO_PRESENT_ALLOWED;
@@ -533,6 +518,15 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
                        ifscreen->match_present = INFO_PRESENT_RESTRICTED;
                } else {
                        SCPY(ifscreen->match, el);
                        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;
                }
        }
                        break;
                }
        }
@@ -583,6 +577,15 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
                        ifscreen->result_present = INFO_PRESENT_RESTRICTED;
                } else {
                        SCPY(ifscreen->result, el);
                        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;
                }
        }
                        break;
                }
        }
@@ -607,11 +610,30 @@ static int inter_screen_out(struct interface *interface, char *filename, int lin
 {
        return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
 }
 {
        return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
 }
-static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *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);
+}
 #warning filter to be done
 #warning filter to be done
+#if 0
+static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
        return(0);
 }
        return(0);
 }
+#endif
 
 
 /*
 
 
 /*
@@ -621,10 +643,10 @@ struct interface_param interface_param[] = {
        { "extension", &inter_extension, "",
        "If keyword is given, calls to interface are handled as internal extensions."},
        {"tones", &inter_tones, "yes | no",
        { "extension", &inter_extension, "",
        "If keyword is given, calls to interface are handled as internal extensions."},
        {"tones", &inter_tones, "yes | no",
-       "Interface generates tones during call setup and release, or not.\nBy default only NT-mode interfaces generate tones."},
+       "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
 
        {"earlyb", &inter_earlyb, "yes | no",
 
        {"earlyb", &inter_earlyb, "yes | no",
-       "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode interfaces receive tones."},
+       "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."},
 
        {"hunt", &inter_hunt, "linear | roundrobin",
        "Select the algorithm for selecting port with free channel."},
@@ -641,7 +663,12 @@ struct interface_param interface_param[] = {
        "This is required on NT-mode ports that are multipoint by default.\n"
        "This parameter must follow a 'port' parameter."},
 
        "This is required on NT-mode ports that are multipoint by default.\n"
        "This parameter must follow a 'port' parameter."},
 
-       {"channel_out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
+       {"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."},
+
+       {"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"
        "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"
@@ -651,37 +678,44 @@ 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)"},
 
        " 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"
        "Channel selection list for all incomming calls from the interface.\n"
        "A free channels is accepted if in the list.\n"
-       "If no channel was requested, the first free channel found is selected.\n"
+       "If any channel was requested, the first free channel found is selected.\n"
        "This parameter must follow a 'port' parameter.\n"
        " <number>[,...] - List of channels to accept.\n"
        "This parameter must follow a 'port' parameter.\n"
        " <number>[,...] - List of channels to accept.\n"
-       " free - Accept any free channel\n"
+       " free - Accept any free channel"},
 
        {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
        "Incomming caller ID is checked against given MSN numbers.\n"
        "If the caller ID is not found in this list, it is overwritten by the first MSN"},
 
 
        {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
        "Incomming caller ID is checked against given MSN numbers.\n"
        "If the caller ID is not found in this list, it is overwritten by the first MSN"},
 
-       {"screen-in", &inter_screen_in, "[options] <old caller ID>[%%] [options] <new caller ID>[%%]",
+       {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
        "Adds an entry for incomming calls to the caller ID screen list.\n"
        "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
        "Adds an entry for incomming calls to the caller ID screen list.\n"
        "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
-       "If '%%' is given after old caller ID, it matches even if caller ID has\n"
+       "If '%' is given after old caller ID, it matches even if caller ID has\n"
        "additional digits.\n"
        "additional digits.\n"
-       "If '%%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
+       "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
        "are added.\n"
        "Options can be:\n"
        " unknown | subsciber | national | international - Change caller ID type.\n"
        " present | restrict - Change presentation of caller ID."},
                
        "are added.\n"
        "Options can be:\n"
        " unknown | subsciber | national | international - Change caller ID type.\n"
        " present | restrict - Change presentation of caller ID."},
                
-       {"screen-out", &inter_screen_out, "<old caller ID> <new caller ID> [options]",
+       {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
        "Adds an entry for outgoing calls to the caller ID screen list.\n"
        "See 'screen-in' for help."},
 
        "Adds an entry for outgoing calls to the caller ID screen list.\n"
        "See 'screen-in' for help."},
 
+       {"nodtmf", &inter_nodtmf, "",
+       "Disables DTMF detection for this interface.\n"
+       "This parameter must follow a 'port' parameter."},
+
+#if 0
+#warning todo: filter, also in the PmISDN object
        {"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"
        "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
        {"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"
        "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
+#endif
 
        {NULL, NULL, NULL, NULL}
 };
 
        {NULL, NULL, NULL, NULL}
 };
@@ -706,10 +740,7 @@ struct interface *read_interfaces(void)
        struct interface_param  *ifparam;
 
        if (interface_newlist != NULL)
        struct interface_param  *ifparam;
 
        if (interface_newlist != NULL)
-       {
-               PERROR("software error, list is not empty.\n");
-               exit(-1);
-       }
+               FATAL("list is not empty.\n");
        interface_error[0] = '\0';
        SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
 
        interface_error[0] = '\0';
        SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
 
@@ -800,7 +831,7 @@ struct interface *read_interfaces(void)
                        parameter[strlen(parameter)-1] = '\0';
 
                        /* check if interface name already exists */
                        parameter[strlen(parameter)-1] = '\0';
 
                        /* check if interface name already exists */
-                       interface = interface_first;
+                       interface = interface_newlist;
                        while(interface)
                        {
                                if (!strcasecmp(interface->name, parameter+1))
                        while(interface)
                        {
                                if (!strcasecmp(interface->name, parameter+1))
@@ -812,14 +843,8 @@ struct interface *read_interfaces(void)
                        }
 
                        /* append interface to new list */
                        }
 
                        /* append interface to new list */
-                       interface = (struct interface *)malloc(sizeof(struct interface));
-                       if (!interface)
-                       {
-                               SPRINT(interface_error, "No memory!");
-                               goto error;
-                       }
+                       interface = (struct interface *)MALLOC(sizeof(struct interface));
                        memuse++;
                        memuse++;
-                       memset(interface, 0, sizeof(struct interface));
 
                        /* name interface */
                        SCPY(interface->name, parameter+1);
 
                        /* name interface */
                        SCPY(interface->name, parameter+1);
@@ -838,10 +863,12 @@ struct interface *read_interfaces(void)
                        {
                                if (ifparam->func(interface, filename, line, parameter, value))
                                        goto error;
                        {
                                if (ifparam->func(interface, filename, line, parameter, value))
                                        goto error;
-                               continue;
+                               break;
                        }
                        ifparam++;
                }
                        }
                        ifparam++;
                }
+               if (ifparam->name)
+                       continue;
 
                SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
                goto error;
 
                SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
                goto error;
@@ -880,8 +907,7 @@ void free_interfaces(struct interface *interface)
                        {
                                temp = selchannel;
                                selchannel = selchannel->next;
                        {
                                temp = selchannel;
                                selchannel = selchannel->next;
-                               memset(temp, 0, sizeof(struct select_channel));
-                               free(temp);
+                               FREE(temp, sizeof(struct select_channel));
                                memuse--;
                        }
                        selchannel = ifport->out_channel;
                                memuse--;
                        }
                        selchannel = ifport->out_channel;
@@ -889,14 +915,12 @@ void free_interfaces(struct interface *interface)
                        {
                                temp = selchannel;
                                selchannel = selchannel->next;
                        {
                                temp = selchannel;
                                selchannel = selchannel->next;
-                               memset(temp, 0, sizeof(struct select_channel));
-                               free(temp);
+                               FREE(temp, sizeof(struct select_channel));
                                memuse--;
                        }
                        temp = ifport;
                        ifport = ifport->next;
                                memuse--;
                        }
                        temp = ifport;
                        ifport = ifport->next;
-                       memset(temp, 0, sizeof(struct interface_port));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_port));
                        memuse--;
                }
                ifmsn = interface->ifmsn;
                        memuse--;
                }
                ifmsn = interface->ifmsn;
@@ -904,8 +928,7 @@ void free_interfaces(struct interface *interface)
                {
                        temp = ifmsn;
                        ifmsn = ifmsn->next;
                {
                        temp = ifmsn;
                        ifmsn = ifmsn->next;
-                       memset(temp, 0, sizeof(struct interface_msn));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_msn));
                        memuse--;
                }
                ifscreen = interface->ifscreen_in;
                        memuse--;
                }
                ifscreen = interface->ifscreen_in;
@@ -913,8 +936,7 @@ void free_interfaces(struct interface *interface)
                {
                        temp = ifscreen;
                        ifscreen = ifscreen->next;
                {
                        temp = ifscreen;
                        ifscreen = ifscreen->next;
-                       memset(temp, 0, sizeof(struct interface_screen));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_screen));
                        memuse--;
                }
                ifscreen = interface->ifscreen_out;
                        memuse--;
                }
                ifscreen = interface->ifscreen_out;
@@ -922,8 +944,7 @@ void free_interfaces(struct interface *interface)
                {
                        temp = ifscreen;
                        ifscreen = ifscreen->next;
                {
                        temp = ifscreen;
                        ifscreen = ifscreen->next;
-                       memset(temp, 0, sizeof(struct interface_screen));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_screen));
                        memuse--;
                }
                iffilter = interface->iffilter;
                        memuse--;
                }
                iffilter = interface->iffilter;
@@ -931,18 +952,43 @@ void free_interfaces(struct interface *interface)
                {
                        temp = iffilter;
                        iffilter = iffilter->next;
                {
                        temp = iffilter;
                        iffilter = iffilter->next;
-                       memset(temp, 0, sizeof(struct interface_filter));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_filter));
                        memuse--;
                }
                temp = interface;
                interface = interface->next;
                        memuse--;
                }
                temp = interface;
                interface = interface->next;
-               memset(temp, 0, sizeof(struct interface));
-               free(temp);
+               FREE(temp, sizeof(struct interface));
                memuse--;
        }
 }
 
                memuse--;
        }
 }
 
+/*
+ * defaults of ports if not specified by config
+ */
+static void set_defaults(struct interface_port *ifport)
+{
+       /* default channel selection list */
+       if (!ifport->out_channel)
+               default_out_channel(ifport);
+       if (!ifport->in_channel)
+               default_in_channel(ifport);
+       /* default is_tones */
+       if (ifport->interface->is_tones)
+               ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
+       else
+               ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
+       /* default is_earlyb */
+       if (ifport->interface->is_earlyb)
+               ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
+       else
+               ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
+       /* set locally flag */
+       if (ifport->interface->extension)
+               ifport->mISDNport->locally = 1;
+       else
+               ifport->mISDNport->locally = 0;
+}
+
 
 /*
  * all links between mISDNport and interface are made
 
 /*
  * all links between mISDNport and interface are made
@@ -977,6 +1023,7 @@ void relink_interfaces(void)
                                {
                                        ifport->mISDNport = mISDNport;
                                        mISDNport->ifport = ifport;
                                {
                                        ifport->mISDNport = mISDNport;
                                        mISDNport->ifport = ifport;
+                                       set_defaults(ifport);
                                }
                                mISDNport = mISDNport->next;
                        }
                                }
                                mISDNport = mISDNport->next;
                        }
@@ -1009,22 +1056,37 @@ void relink_interfaces(void)
                {
                        if (!ifport->mISDNport)
                        {
                {
                        if (!ifport->mISDNport)
                        {
-                               /* open new port */
-                               mISDNport = mISDNport_open(ifport->portnum, ifport->ptp);
-                               if (mISDNport)
-                               {
-                                       ifport->mISDNport = mISDNport;
-                                       mISDNport->ifport = ifport;
-                               }
+                               load_port(ifport);
                        }
                        }
-                       if (ifport->mISDNport && !ifport->selchannel)
-                               default_selchannel(ifport);
+                       ifport = ifport->next;
                }
                interface = interface->next;
        }
 
 }
 
                }
                interface = interface->next;
        }
 
 }
 
+
+/*
+ * load port
+ */
+void load_port(struct interface_port *ifport)
+{
+       struct mISDNport *mISDNport;
+
+       /* open new port */
+       mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp, ifport->interface);
+       if (mISDNport)
+       {
+               /* link port */
+               ifport->mISDNport = mISDNport;
+               mISDNport->ifport = ifport;
+               set_defaults(ifport);
+       } else
+       {
+               ifport->block = 2; /* not available */
+       }
+}
+
 /*
  * give summary of interface syntax
  */
 /*
  * give summary of interface syntax
  */
@@ -1052,4 +1114,3 @@ void doc_interface(void)
        }
 }
 
        }
 }
 
-