LCR now runs as a user.
[lcr.git] / socket_server.c
index 5ad827f..e1853d3 100644 (file)
@@ -9,26 +9,13 @@
 **                                                                           **
 \*****************************************************************************/
 
-#include <stdio.h>
-//#include <stdlib.h>
-//#include <string.h>
-#include <sys/types.h>
-//#include <sys/stat.h>
-//#include <unistd.h>
-//#include <signal.h>
-//#include <fcntl.h>
-#include <sys/ioctl.h>
-//#include <sys/file.h>
-//#include <errno.h>
-//#include <sys/mman.h>
-//#include <sys/resource.h>
+#include "main.h"
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <curses.h>
-#include "main.h"
 
 
-char *socket_name = SOCKET_NAME;
+char socket_name[128];
 int sock = -1;
 struct sockaddr_un sock_address;
 
@@ -39,7 +26,7 @@ struct admin_list *admin_first = NULL;
  */
 int admin_init(void)
 {
-       unsigned long on = 1;
+       unsigned int on = 1;
 
        /* open and bind socket */
        if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
@@ -49,6 +36,7 @@ int admin_init(void)
        }
        fhuse++;
        memset(&sock_address, 0, sizeof(sock_address));
+       SPRINT(socket_name, SOCKET_NAME, options.lock);
        sock_address.sun_family = AF_UNIX;
        UCPY(sock_address.sun_path, socket_name);
        unlink(socket_name);
@@ -79,6 +67,10 @@ int admin_init(void)
                PERROR("Failed to set socket \"%s\" into non-blocking mode. (errno=%d)\n", sock_address.sun_path, errno);
                return(-1);
        }
+       if (chmod(socket_name, options.socketrights) < 0)
+       {
+               PERROR("Failed to change socket rigts to %d. (errno=%d)\n", options.socketrights, errno);
+       }
        return(0);
 }
 
@@ -93,10 +85,42 @@ void free_connection(struct admin_list *admin)
        void *temp;
        union parameter param;
        class Join *join, *joinnext;
+       struct mISDNport *mISDNport;
+       int i, ii;
 
        /* free remote joins */
        if (admin->remote_name[0])
        {
+               start_trace(0,
+                       NULL,
+                       NULL,
+                       NULL,
+                       DIRECTION_NONE,
+                       0,
+                       0,
+                       "REMOTE APP release");
+               add_trace("app", "name", "%s", admin->remote_name);
+               end_trace();
+               /* release all exported channels */
+               mISDNport = mISDNport_first;
+               while(mISDNport)
+               {
+                       i = 0;
+                       ii = mISDNport->b_num;
+                       while(i < ii)
+                       {
+                               if (mISDNport->b_remote_id[i] == admin->sock)
+                               {
+                                       mISDNport->b_state[i] = B_STATE_IDLE;
+                                       mISDNport->b_timer[i] = 0;
+                                       mISDNport->b_remote_id[i] = 0;
+                                       mISDNport->b_remote_ref[i] = 0;
+                               }
+                               i++;
+                       }
+                       mISDNport = mISDNport->next;
+               }
+               /* release join */
                join = join_first;
                while(join)
                {
@@ -157,6 +181,8 @@ void admin_cleanup(void)
                close(sock);
                fhuse--;
        }
+
+       unlink(socket_name);
 }
 
 
@@ -274,7 +300,7 @@ int admin_route(struct admin_queue **responsep)
                        apppbx->release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
                        start_trace(0,
                                NULL,
-                               numberrize_callerinfo(apppbx->e_callerinfo.id, apppbx->e_callerinfo.ntype),
+                               numberrize_callerinfo(apppbx->e_callerinfo.id, apppbx->e_callerinfo.ntype, options.national, options.international),
                                apppbx->e_dialinginfo.id,
                                DIRECTION_NONE,
                                CATEGORY_EP,
@@ -283,7 +309,7 @@ int admin_route(struct admin_queue **responsep)
                        end_trace();
                }
 
-               apppbx->e_action_timeout = NULL;
+               apppbx->e_action_timeout = 0;
                apppbx->e_rule = NULL;
                apppbx->e_ruleset = NULL;
 
@@ -465,7 +491,7 @@ int admin_block(struct admin_queue **responsep, int portnum, int block)
  */
 int admin_release(struct admin_queue **responsep, char *message)
 {
-       unsigned long           id;
+       unsigned int            id;
        struct admin_queue      *response;      /* response pointer */
        class EndpointAppPBX    *apppbx;
 
@@ -516,7 +542,7 @@ int admin_call(struct admin_list *admin, struct admin_message *msg)
                FATAL("No memory for Endpoint Application instance\n");
        apppbx->e_adminid = admin->sockserial;
        admin->epointid = epoint->ep_serial;
-       SCPY(apppbx->e_callerinfo.id, nationalize_callerinfo(msg->u.call.callerid, &apppbx->e_callerinfo.ntype));
+       SCPY(apppbx->e_callerinfo.id, nationalize_callerinfo(msg->u.call.callerid, &apppbx->e_callerinfo.ntype, options.national, options.international));
        if (msg->u.call.present)
                apppbx->e_callerinfo.present = INFO_PRESENT_ALLOWED;
        else
@@ -592,39 +618,49 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i
 /*
  * send data to the remote socket join instance
  */
-int admin_message_to_join(struct admin_msg *msg, char *remote_name, int sock_id)
+int admin_message_to_join(struct admin_msg *msg, struct admin_list *admin)
 {
        class Join                      *join;
-       struct admin_list               *admin;
+       struct admin_list               *temp;
 
        /* hello message */
        if (msg->type == MESSAGE_HELLO)
        {
-               if (remote_name[0])
+               if (admin->remote_name[0])
                {
                        PERROR("Remote application repeats hello message.\n");
                        return(-1);
                }
                /* look for second application */
-               admin = admin_first;
-               while(admin)
+               temp = admin_first;
+               while(temp)
                {
-                       if (!strcmp(admin->remote_name, msg->param.hello.application))
+                       if (!strcmp(temp->remote_name, msg->param.hello.application))
                                break;
-                       admin = admin->next;
+                       temp = temp->next;
                }
-               if (admin)
+               if (temp)
                {
                        PERROR("Remote application connects twice??? (ignoring)\n");
                        return(-1);
                }
                /* set remote socket instance */
-               SCPY(remote_name, msg->param.hello.application);
+               SCPY(admin->remote_name, msg->param.hello.application);
+               start_trace(0,
+                       NULL,
+                       NULL,
+                       NULL,
+                       DIRECTION_NONE,
+                       0,
+                       0,
+                       "REMOTE APP registers");
+               add_trace("app", "name", "%s", admin->remote_name);
+               end_trace();
                return(0);
        }
 
        /* check we have no application name */
-       if (remote_name[0])
+       if (!admin->remote_name[0])
        {
                PERROR("Remote application did not send us a hello message.\n");
                return(-1);
@@ -634,9 +670,12 @@ int admin_message_to_join(struct admin_msg *msg, char *remote_name, int sock_id)
        if (msg->type == MESSAGE_NEWREF)
        {
                /* create new join instance */
-               join = new JoinRemote(0, remote_name, sock_id); // must have no serial, because no endpoint is connected
+               join = new JoinRemote(0, admin->remote_name, admin->sock); // must have no serial, because no endpoint is connected
                if (!join)
+               {
                        FATAL("No memory for remote join instance\n");
+                       return(-1);
+               }
                return(0);
        }
 
@@ -644,10 +683,11 @@ int admin_message_to_join(struct admin_msg *msg, char *remote_name, int sock_id)
         * no ref given for *_ack */
        if (msg->type == MESSAGE_BCHANNEL)
        if (msg->param.bchannel.type == BCHANNEL_ASSIGN_ACK
-        || msg->param.bchannel.type == BCHANNEL_REMOVE_ACK)
+        || msg->param.bchannel.type == BCHANNEL_REMOVE_ACK
+        || msg->param.bchannel.type == BCHANNEL_RELEASE)
        {
                /* no ref, but address */
-               message_bchannel_from_join(NULL, msg->param.bchannel.type, msg->param.bchannel.handle);
+               message_bchannel_from_remote(NULL, msg->param.bchannel.type, msg->param.bchannel.handle);
                return(0);
        }
        
@@ -668,8 +708,8 @@ int admin_message_to_join(struct admin_msg *msg, char *remote_name, int sock_id)
        }
        if (!join)
        {
-               PERROR("No join found with serial %d.\n", msg->ref);
-               return(-1);
+               PDEBUG(DEBUG_LOG, "No join found with serial %d. (May have been already released.)\n", msg->ref);
+               return(0);
        }
 
        /* check application */
@@ -678,9 +718,9 @@ int admin_message_to_join(struct admin_msg *msg, char *remote_name, int sock_id)
                PERROR("Ref %d does not belong to a remote join instance.\n", msg->ref);
                return(-1);
        }
-       if (sock_id != ((class JoinRemote *)join)->j_remote_id)
+       if (admin->sock != ((class JoinRemote *)join)->j_remote_id)
        {
-               PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, ((class JoinRemote *)join)->j_remote_name, remote_name);
+               PERROR("Ref %d belongs to remote application %s, but not to sending application %s.\n", msg->ref, ((class JoinRemote *)join)->j_remote_name, admin->remote_name);
                return(-1);
        }
 
@@ -694,10 +734,10 @@ int admin_message_to_join(struct admin_msg *msg, char *remote_name, int sock_id)
 /*
  * this function is called for every message to remote socket
  */
-int admin_message_from_join(int remote_id, unsigned long ref, int message_type, union parameter *param)
+int admin_message_from_join(int remote_id, unsigned int ref, int message_type, union parameter *param)
 {
        struct admin_list       *admin;
-       struct admin_queue      *response, **responsep; /* response pointer */
+       struct admin_queue      **responsep;    /* response pointer */
 
        /* searching for admin id
         * maybe there is no given remote application
@@ -714,27 +754,22 @@ int admin_message_from_join(int remote_id, unsigned long ref, int message_type,
                return(-1);
 
        /* seek to end of response list */
-       response = admin->response;
        responsep = &admin->response;
-       while(response)
+       while(*responsep)
        {
-               responsep = &response->next;
-               response = response->next;
+               responsep = &(*responsep)->next;
        }
 
        /* create state response */
-       response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message));
+       *responsep = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message));
        memuse++;
-       response->num = 1;
+       (*responsep)->num = 1;
 
        /* message */
-       response->am[0].u.msg.type = message_type;
-       response->am[0].u.msg.ref = ref;
-       memcpy(&response->am[0].u.msg.param, param, sizeof(union parameter));
-
-       /* attach to response chain */
-       *responsep = response;
-       responsep = &response->next;
+       (*responsep)->am[0].message = ADMIN_MESSAGE;
+       (*responsep)->am[0].u.msg.type = message_type;
+       (*responsep)->am[0].u.msg.ref = ref;
+       memcpy(&(*responsep)->am[0].u.msg.param, param, sizeof(union parameter));
 
        return(0);
 }
@@ -826,8 +861,12 @@ int admin_state(struct admin_queue **responsep)
        *responsep = response;
        responsep = &response->next;
 
-       /* create response for all interfaces */
-       num = (response->am[0].u.s.interfaces)+(response->am[0].u.s.joins)+(response->am[0].u.s.epoints)+(response->am[0].u.s.ports);
+       /* create response for all instances */
+       num = (response->am[0].u.s.interfaces)
+           + (response->am[0].u.s.remotes)
+           + (response->am[0].u.s.joins)
+           + (response->am[0].u.s.epoints)
+           + (response->am[0].u.s.ports);
        if (num == 0)
                return(0);
        response = (struct admin_queue *)MALLOC(sizeof(admin_queue)+(num*sizeof(admin_message)));
@@ -868,6 +907,15 @@ int admin_state(struct admin_queue **responsep)
                                response->am[num].u.i.l1link = mISDNport->l1link;
                                /* l2link */
                                response->am[num].u.i.l2link = mISDNport->l2link;
+                               /* los */
+                               response->am[num].u.i.los = mISDNport->los;
+                               /* ais */
+                               response->am[num].u.i.ais = mISDNport->ais;
+                               /* rdi */
+                               response->am[num].u.i.rdi = mISDNport->rdi;
+                               /* slip */
+                               response->am[num].u.i.slip_tx = mISDNport->slip_tx;
+                               response->am[num].u.i.slip_rx = mISDNport->slip_rx;
                                /* channels */
                                response->am[num].u.i.channels = mISDNport->b_num;
                                /* channel info */
@@ -878,6 +926,7 @@ int admin_state(struct admin_queue **responsep)
                                        response->am[num].u.i.busy[i] = mISDNport->b_state[i];
                                        if (mISDNport->b_port[i])
                                                response->am[num].u.i.port[i] = mISDNport->b_port[i]->p_serial;
+                                       response->am[num].u.i.mode[i] = mISDNport->b_mode[i];
                                        i++;
                                }
                        }
@@ -1079,7 +1128,7 @@ int admin_handle(void)
        int                     len;
        int                     new_sock;
        socklen_t               sock_len = sizeof(sock_address);
-       unsigned long           on = 1;
+       unsigned int            on = 1;
        int                     work = 0; /* if work was done */
        struct Endpoint         *epoint;
 
@@ -1173,7 +1222,7 @@ int admin_handle(void)
                        continue;
                }
                /* process socket command */
-               if (admin->response)
+               if (admin->response && msg.message != ADMIN_MESSAGE)
                {
                        PERROR("Data from socket %d while sending response.\n", admin->sock);
                        *adminp = admin->next;
@@ -1240,7 +1289,7 @@ int admin_handle(void)
                        break;
 
                        case ADMIN_MESSAGE:
-                       if (admin_message_to_join(&msg.u.msg, admin->remote_name, admin->sock) < 0)
+                       if (admin_message_to_join(&msg.u.msg, admin) < 0)
                        {
                                PERROR("Failed to deliver message for socket %d.\n", admin->sock);
                                goto response_error;
@@ -1299,7 +1348,7 @@ int admin_handle(void)
                        work = 1;
                        if (len == 0)
                                goto end;
-                       if (len < (int)(sizeof(struct admin_message)*(admin->response->num)-admin->response->offset))
+                       if (len < (int)(sizeof(struct admin_message)*(admin->response->num) - admin->response->offset))
                        {
                                admin->response->offset+=len;
                                goto next;