new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / shared / mq_op.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All rights reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation
8  */
9
10 #include "shared.h"
11 #include "os_net/os_net.h"
12
13
14 #ifndef WIN32
15
16 /* Start the Message Queue. type: WRITE||READ */
17 int StartMQ(const char *path, short int type)
18 {
19     if (type == READ) {
20         return (OS_BindUnixDomain(path, 0660, OS_MAXSTR + 512));
21     }
22
23     /* We give up to 21 seconds for the other end to start */
24     else {
25         int rc = 0;
26         if (File_DateofChange(path) < 0) {
27             sleep(1);
28             if (File_DateofChange(path) < 0) {
29                 sleep(5);
30                 if (File_DateofChange(path) < 0) {
31                     sleep(15);
32                     if (File_DateofChange(path) < 0) {
33                         merror(QUEUE_ERROR, __local_name, path, "Queue not found");
34                         return (-1);
35                     }
36                 }
37             }
38         }
39
40         /* Wait up to 3 seconds to connect to the unix domain.
41          * After three errors, exit.
42          */
43         if ((rc = OS_ConnectUnixDomain(path, OS_MAXSTR + 256)) < 0) {
44             sleep(1);
45             if ((rc = OS_ConnectUnixDomain(path, OS_MAXSTR + 256)) < 0) {
46                 sleep(2);
47                 if ((rc = OS_ConnectUnixDomain(path, OS_MAXSTR + 256)) < 0) {
48                     merror(QUEUE_ERROR, __local_name, path,
49                            strerror(errno));
50                     return (-1);
51                 }
52             }
53         }
54
55         debug1(MSG_SOCKET_SIZE, __local_name, OS_getsocketsize(rc));
56         return (rc);
57     }
58 }
59
60 /* Send a message to the queue */
61 int SendMSG(int queue, const char *message, const char *locmsg, char loc)
62 {
63     int __mq_rcode;
64     char tmpstr[OS_MAXSTR + 1];
65
66     tmpstr[OS_MAXSTR] = '\0';
67
68     /* Check for global locks */
69     os_wait();
70
71     if (loc == SECURE_MQ) {
72         loc = message[0];
73         message++;
74
75         if (message[0] != ':') {
76             merror(FORMAT_ERROR, __local_name);
77             return (0);
78         }
79         message++; /* Pointing now to the location */
80
81         if (strncmp(message, "keepalive", 9) == 0) {
82             return (0);
83         }
84
85         snprintf(tmpstr, OS_MAXSTR, "%c:%s->%s", loc, locmsg, message);
86     } else {
87         snprintf(tmpstr, OS_MAXSTR, "%c:%s:%s", loc, locmsg, message);
88     }
89
90     /* Queue not available */
91     if (queue < 0) {
92         return (-1);
93     }
94
95     /* We attempt 5 times to send the message if
96      * the receiver socket is busy.
97      * After the first error, we wait 1 second.
98      * After the second error, we wait more 3 seconds.
99      * After the third error, we wait 5 seconds.
100      * After the fourth error, we wait 10 seconds.
101      * If we failed again, the message is not going
102      * to be delivered and an error is sent back.
103      */
104     if ((__mq_rcode = OS_SendUnix(queue, tmpstr, 0)) < 0) {
105         /* Error on the socket */
106         if (__mq_rcode == OS_SOCKTERR) {
107             merror("%s: socketerr (not available).", __local_name);
108             close(queue);
109             return (-1);
110         }
111
112         /* Unable to send. Socket busy */
113         sleep(1);
114         if (OS_SendUnix(queue, tmpstr, 0) < 0) {
115             /* When the socket is to busy, we may get some
116              * error here. Just sleep 2 second and try
117              * again.
118              */
119             sleep(3);
120             /* merror("%s: socket busy", __local_name); */
121             if (OS_SendUnix(queue, tmpstr, 0) < 0) {
122                 sleep(5);
123                 merror("%s: socket busy ..", __local_name);
124                 if (OS_SendUnix(queue, tmpstr, 0) < 0) {
125                     sleep(10);
126                     merror("%s: socket busy ..", __local_name);
127                     if (OS_SendUnix(queue, tmpstr, 0) < 0) {
128                         /* Message is going to be lost
129                          * if the application does not care
130                          * about checking the error
131                          */
132                         close(queue);
133                         return (-1);
134                     }
135                 }
136             }
137         }
138     }
139
140     return (0);
141 }
142
143 #endif /* !WIN32 */