Added layer1 hold feature. Requires new mISDN and mISDNuser package from git.
[lcr.git] / lcradmin.c
index 1df16c5..306a0da 100644 (file)
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <curses.h>
 #include "macro.h"
+#include "options.h"
 #include "join.h"
 #include "joinpbx.h"
 #include "extension.h"
@@ -42,6 +43,7 @@ int   show_interfaces = 2,
 
 enum {
        MODE_STATE,
+       MODE_PORTINFO,
        MODE_INTERFACE,
        MODE_ROUTE,
        MODE_DIAL,
@@ -53,14 +55,14 @@ enum {
        MODE_TRACE,
 };
 
-char *text_interfaces[] = {
+const char *text_interfaces[] = {
        "off",
        "brief",
        "active channels",
        "all channels",
 };
 
-char *text_calls[] = {
+const char *text_calls[] = {
        "off",
        "brief",
        "structured",
@@ -449,7 +451,8 @@ int debug_join(struct admin_message *msg, struct admin_message *m, int line, int
 
        return(line);
 }
-char *admin_state(int sock, char *argv[])
+
+const char *admin_state(int sock, char *argv[])
 {
        struct admin_message    msg,
                                *m;
@@ -666,18 +669,36 @@ char *admin_state(int sock, char *argv[])
                        color(white);
                        if (m[i].u.i.block >= 2)
                        {
-                               SPRINT(buffer, "%s (%d)%s", m[i].u.i.interface_name, m[i].u.i.portnum, (m[i].u.i.extension)?" (extension)":"");
+                               if (m[i].u.i.portnum < 0)
+                                       SPRINT(buffer, "%s (port ?: %s)%s", m[i].u.i.interface_name, m[i].u.i.portname, (m[i].u.i.extension)?" extension":"");
+                               else
+                                       SPRINT(buffer, "%s (port %d: %s)%s", m[i].u.i.interface_name, m[i].u.i.portnum, m[i].u.i.portname, (m[i].u.i.extension)?" extension":"");
                                addstr(buffer);
                                color(red);
                                addstr("  not loaded");
                        } else
                        {
-                               SPRINT(buffer, "%s (%d) %s %s%s use:%d", m[i].u.i.interface_name, m[i].u.i.portnum, (m[i].u.i.ntmode)?"NT-mode":"TE-mode", (m[i].u.i.ptp)?"ptp ":"ptmp", (m[i].u.i.extension)?" extension":"", m[i].u.i.use);
+                               SPRINT(buffer, "%s", m[i].u.i.interface_name);
+                               addstr(buffer);
+                               color(yellow);
+                               SPRINT(buffer, "(port %d: %s)", m[i].u.i.portnum, m[i].u.i.portname);
+                               addstr(buffer);
+                               color(cyan);
+                               SPRINT(buffer, " %s %s%s%s%s", (m[i].u.i.ntmode)?"NT-mode":"TE-mode", (m[i].u.i.ptp)?"ptp":"ptmp", (m[i].u.i.l1hold)?" l1hold":"", (m[i].u.i.l2hold)?" l2hold":"", (m[i].u.i.extension)?" extension":"");
+                               addstr(buffer);
+                               if (m[i].u.i.use)
+                                       color(green);
+                               else
+                                       color(blue);
+                               SPRINT(buffer, " use:%d", m[i].u.i.use);
                                addstr(buffer);
                                if (m[i].u.i.ptp || !m[i].u.i.ntmode)
                                {
-                                       color((m[i].u.i.l2link)?green:red);
-                                       addstr((m[i].u.i.l2link)?"  L2 UP":"  L2 down");
+                                       color((m[i].u.i.l2link > 0)?green:red);
+                                       if (m[i].u.i.l2link < 0)
+                                               addstr("  L2 unknown");
+                                       else
+                                               addstr((m[i].u.i.l2link)?"  L2 UP":"  L2 down");
                                }
                                color((m[i].u.i.l1link > 0)?green:blue);
                                if (m[i].u.i.l1link < 0)
@@ -1121,6 +1142,7 @@ char *admin_state(int sock, char *argv[])
                            !!strncmp(enter_string, "release ", 8) &&
                            !!strncmp(enter_string, "block ", 6) &&
                            !!strncmp(enter_string, "unblock ", 8) &&
+                           !!strncmp(enter_string, "load ", 5) &&
                            !!strncmp(enter_string, "unload ", 7))
                        {
                                SPRINT(logline[logcur++ % LOGLINES], "usage:");
@@ -1128,7 +1150,7 @@ char *admin_state(int sock, char *argv[])
                                SPRINT(logline[logcur++ % LOGLINES], "route (reload routing.conf)");
                                SPRINT(logline[logcur++ % LOGLINES], "release <EP> (release endpoint with given ID)");
                                SPRINT(logline[logcur++ % LOGLINES], "block <port> (block port for further calls)");
-                               SPRINT(logline[logcur++ % LOGLINES], "unblock <port> (unblock port for further calls, load if not loaded)");
+                               SPRINT(logline[logcur++ % LOGLINES], "unblock/load <port> (unblock port for further calls, load if not loaded)");
                                SPRINT(logline[logcur++ % LOGLINES], "unload <port> (unload mISDN stack, release call calls)");
                        } else
                        {
@@ -1252,11 +1274,175 @@ char *admin_state(int sock, char *argv[])
        return(NULL);
 }
 
+const char *admin_portinfo(int sock, int argc, char *argv[])
+{
+       struct admin_message    msg,
+                               *m;
+       int                     i, ii, j;
+       int                     num;
+       int                     len;
+       int                     off;
+
+       /* send state request command */
+       memset(&msg, 0, sizeof(msg));
+       msg.message = ADMIN_REQUEST_STATE;
+       if (write(sock, &msg, sizeof(msg)) != sizeof(msg))
+       {
+               cleanup_curses();
+               return("Broken pipe while sending command.");
+       }
+
+       /* receive response */
+       if (read(sock, &msg, sizeof(msg)) != sizeof(msg))
+       {
+               cleanup_curses();
+               return("Broken pipe while receiving response.");
+       }
+
+       if (msg.message != ADMIN_RESPONSE_STATE)
+       {
+               cleanup_curses();
+               return("Response not valid. Expecting state response.");
+       }
+       num = msg.u.s.interfaces + msg.u.s.remotes + msg.u.s.joins + msg.u.s.epoints + msg.u.s.ports;
+       m = (struct admin_message *)MALLOC(num*sizeof(struct admin_message));
+       off=0;
+       if (num)
+       {
+               readagain:
+               if ((len = read(sock, ((unsigned char *)(m))+off, num*sizeof(struct admin_message)-off)) != num*(int)sizeof(struct admin_message)-off)
+               {
+                       if (len <= 0) {
+                               FREE(m, 0);
+                               cleanup_curses();
+                               return("Broken pipe while receiving state infos.");
+                       }
+                       if (len < num*(int)sizeof(struct admin_message))
+                       {
+                               off+=len;
+                               goto readagain;
+                       }
+               }
+       }
+       j = 0;
+       i = 0;
+       while(i < msg.u.s.interfaces)
+       {
+               if (m[j].message != ADMIN_RESPONSE_S_INTERFACE)
+               {
+                       FREE(m, 0);
+                       cleanup_curses();
+                       return("Response not valid. Expecting interface information.");
+               }
+               i++;
+               j++;
+       }
+       i = 0;
+       while(i < msg.u.s.remotes)
+       {
+               if (m[j].message != ADMIN_RESPONSE_S_REMOTE)
+               {
+                       FREE(m, 0);
+                       cleanup_curses();
+                       return("Response not valid. Expecting remote application information.");
+               }
+               i++;
+               j++;
+       }
+       i = 0;
+       while(i < msg.u.s.joins)
+       {
+               if (m[j].message != ADMIN_RESPONSE_S_JOIN)
+               {
+                       FREE(m, 0);
+                       cleanup_curses();
+                       return("Response not valid. Expecting join information.");
+               }
+               i++;
+               j++;
+       }
+       i = 0;
+       while(i < msg.u.s.epoints)
+       {
+               if (m[j].message != ADMIN_RESPONSE_S_EPOINT)
+               {
+                       FREE(m, 0);
+                       cleanup_curses();
+                       return("Response not valid. Expecting endpoint information.");
+               }
+               i++;
+               j++;
+       }
+       i = 0;
+       while(i < msg.u.s.ports)
+       {
+               if (m[j].message != ADMIN_RESPONSE_S_PORT)
+               {
+                       FREE(m, 0);
+                       cleanup_curses();
+                       return("Response not valid. Expecting port information.");
+               }
+               i++;
+               j++;
+       }
+       // now j is the number of message blocks
+
+       /* output interfaces */
+       i = 0;
+       ii = i + msg.u.s.interfaces;
+       while(i < ii)
+       {
+               if (argc > 2)
+               {
+                       if (!!strcmp(argv[2], m[i].u.i.interface_name))
+                       {
+                               i++;
+                               continue;
+                       }
+               }
+               printf("%s:\n", m[i].u.i.interface_name);
+               if (m[i].u.i.portnum < 0)
+                       printf("\t port = unknown\n");
+               else
+                       printf("\t port = %d \"%s\"\n",m[i].u.i.portnum, m[i].u.i.portname);
+               printf("\t extension = %s\n", (m[i].u.i.extension)?"yes":"no");
+               if (m[i].u.i.block >= 2)
+               {
+                       printf("\t status = not loaded\n");
+               } else
+               {
+                       if (m[i].u.i.block)
+                               printf("\t status = blocked\n");
+                       else
+                               printf("\t status = unblocked\n");
+                       printf("\t mode = %s %s%s%s\n", (m[i].u.i.ntmode)?"NT-mode":"TE-mode", (m[i].u.i.ptp)?"ptp":"ptmp", (m[i].u.i.l1hold)?" l1hold":"", (m[i].u.i.l2hold)?" l2hold":"");
+                       if (m[i].u.i.l1link < 0)
+                               printf("\t l1 link = unknown\n");
+                       else
+                               printf("\t l1 link = %s\n", (m[i].u.i.l1link)?"up":"down");
+                       if (m[i].u.i.ptp || !m[i].u.i.ntmode)
+                       {
+                               if (m[i].u.i.l2link < 0)
+                                       printf("\t l2 link = unknown\n");
+                               else
+                                       printf("\t l2 link = %s\n", (m[i].u.i.l2link)?"up":"down");
+                       }
+                       printf("\t usage = %d\n", m[i].u.i.use);
+               }
+               i++;
+       }
+
+       /* free memory */
+       FREE(m, 0);
+
+       return(NULL);
+}
+
 
 /*
  * Send command and show error message.
  */
-char *admin_cmd(int sock, int mode, char *extension, char *number)
+const char *admin_cmd(int sock, int mode, char *extension, char *number)
 {
        static struct admin_message msg;
 
@@ -1344,7 +1530,7 @@ char *admin_cmd(int sock, int mode, char *extension, char *number)
        gettimeofday(&now_tv, &now_tz); \
        now_d = ((double)(now_tv.tv_usec))/1000000 + now_tv.tv_sec; \
        }
-char *admin_testcall(int sock, int argc, char *argv[])
+const char *admin_testcall(int sock, int argc, char *argv[])
 {
        static struct admin_message msg;
        int ar = 2;
@@ -1554,7 +1740,7 @@ next:
 /*
  * makes a trace
  */
-char *admin_trace(int sock, int argc, char *argv[])
+const char *admin_trace(int sock, int argc, char *argv[])
 {
        static struct admin_message msg;
        int i;
@@ -1583,6 +1769,7 @@ char *admin_trace(int sock, int argc, char *argv[])
        memset(&msg, 0, sizeof(msg));
        msg.message = ADMIN_TRACE_REQUEST;
        msg.u.trace_req.detail = 3;
+       msg.u.trace_req.port = -1;
 
        /* parse args */
        i = 2;
@@ -1630,10 +1817,9 @@ next:
 int main(int argc, char *argv[])
 {
        int mode;
-       char *socket_name = SOCKET_NAME;
        int sock, conn;
        struct sockaddr_un sock_address;
-       char *ret;
+       const char *ret;
 
 
        /* show options */
@@ -1643,12 +1829,13 @@ int main(int argc, char *argv[])
                printf("\n");
                printf("Usage: %s state | interface | route | dial ...\n", argv[0]);
                printf("state - View current states using graphical console output.\n");
-               printf("interface - Tell LCR to reload \"interface.conf\".\n");
+               printf("portinfo - Get info of current ports.\n");
+               printf("interface [<portname>] - Tell LCR to reload \"interface.conf\".\n");
                printf("route - Tell LCR to reload \"route.conf\".\n");
                printf("dial <extension> <number> - Tell LCR the next number to dial for extension.\n");
                printf("release <number> - Tell LCR to release endpoint with given number.\n");
                printf("block <port> - Block given port.\n");
-               printf("unblock <port> - Unblock given port.\n");
+               printf("unblock/load <port> - Unblock given port.\n");
                printf("unload <port> - Unload port. To load port use 'block' or 'unblock'.\n");
                printf("testcall [options] <interface> <callerid> <number> [present|restrict [<capability>]] - Testcall\n");
                printf(" -> options = --setup-timeout <seconds> --proceeding-timeout <seconds>\n");
@@ -1665,6 +1852,10 @@ int main(int argc, char *argv[])
        {
                mode = MODE_STATE;
        } else
+       if (!(strcasecmp(argv[1],"portinfo")))
+       {
+               mode = MODE_PORTINFO;
+       } else
        if (!(strcasecmp(argv[1],"interface")))
        {
                mode = MODE_INTERFACE;
@@ -1685,7 +1876,8 @@ int main(int argc, char *argv[])
                        goto usage;
                mode = MODE_RELEASE;
        } else
-       if (!(strcasecmp(argv[1],"unblock")))
+       if (!(strcasecmp(argv[1],"unblock"))
+        || !(strcasecmp(argv[1],"load")))
        {
                if (argc <= 2)
                        goto usage;
@@ -1717,6 +1909,10 @@ int main(int argc, char *argv[])
                goto usage;
        }
 
+       if (read_options() == 0) {
+               exit(EXIT_FAILURE);
+       }
+
 //pipeagain:
        /* open socket */
        if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
@@ -1725,8 +1921,8 @@ int main(int argc, char *argv[])
                exit(EXIT_FAILURE);
        }
        memset(&sock_address, 0, sizeof(sock_address));
+       SPRINT(sock_address.sun_path, SOCKET_NAME, options.lock);
        sock_address.sun_family = PF_UNIX;
-       UCPY(sock_address.sun_path, socket_name);
        if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0)
        {
                close(sock);
@@ -1741,6 +1937,10 @@ int main(int argc, char *argv[])
                ret = admin_state(sock, argv);
                break;
        
+               case MODE_PORTINFO:
+               ret = admin_portinfo(sock, argc, argv);
+               break;
+       
                case MODE_INTERFACE:
                case MODE_ROUTE:
                ret = admin_cmd(sock, mode, NULL, NULL);