new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / client-agent / start_agent.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All right 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 "agentd.h"
12 #include "os_net/os_net.h"
13
14
15 /* Attempt to connect to all configured servers */
16 int connect_server(int initial_id)
17 {
18     unsigned int attempts = 2;
19     int rc = initial_id;
20
21     /* Checking if the initial is zero, meaning we have to
22      * rotate to the beginning
23      */
24     if (agt->rip[initial_id] == NULL) {
25         rc = 0;
26     }
27
28     /* Close socket if available */
29     if (agt->sock >= 0) {
30         sleep(1);
31         CloseSocket(agt->sock);
32         agt->sock = -1;
33
34         if (agt->rip[1]) {
35             verbose("%s: INFO: Closing connection to server %s, port %s.",
36                     ARGV0,
37                     agt->rip[rc],
38                     agt->port);
39         }
40
41     }
42
43     while (agt->rip[rc]) {
44
45         /* Connect to any useable address of the server */
46         verbose("%s: INFO: Trying to connect to server %s, port %s.", ARGV0,
47                 agt->rip[rc],
48                 agt->port);
49
50         agt->sock = OS_ConnectUDP(agt->port, agt->rip[rc]);
51
52         if (agt->sock < 0) {
53             agt->sock = -1;
54             merror(CONNS_ERROR, ARGV0, agt->rip[rc]);
55             rc++;
56
57             if (agt->rip[rc] == NULL) {
58                 attempts += 10;
59
60                 /* Only log that if we have more than 1 server configured */
61                 if (agt->rip[1]) {
62                     merror("%s: ERROR: Unable to connect to any server.", ARGV0);
63                 }
64
65                 sleep(attempts);
66                 rc = 0;
67             }
68         } else {
69 #ifdef HPUX
70             /* Set socket non-blocking on HPUX */
71             // fcntl(agt->sock, O_NONBLOCK);
72 #endif
73
74 #ifdef WIN32
75             int bmode = 1;
76
77             /* Set socket to non-blocking */
78             ioctlsocket(agt->sock, FIONBIO, (u_long FAR *) &bmode);
79 #endif
80
81             agt->rip_id = rc;
82             return (1);
83         }
84     }
85
86     return (0);
87 }
88
89 /* Send synchronization message to the server and wait for the ack */
90 void start_agent(int is_startup)
91 {
92     ssize_t recv_b = 0;
93     unsigned int attempts = 0, g_attempts = 1;
94
95     char *tmp_msg;
96     char msg[OS_MAXSTR + 2];
97     char buffer[OS_MAXSTR + 1];
98     char cleartext[OS_MAXSTR + 1];
99     char fmsg[OS_MAXSTR + 1];
100
101     memset(msg, '\0', OS_MAXSTR + 2);
102     memset(buffer, '\0', OS_MAXSTR + 1);
103     memset(cleartext, '\0', OS_MAXSTR + 1);
104     memset(fmsg, '\0', OS_MAXSTR + 1);
105     snprintf(msg, OS_MAXSTR, "%s%s", CONTROL_HEADER, HC_STARTUP);
106
107 #ifdef ONEWAY_ENABLED
108     return;
109 #endif
110
111     while (1) {
112         /* Send start up message */
113         send_msg(0, msg);
114         attempts = 0;
115
116         /* Read until our reply comes back */
117         while (((recv_b = recv(agt->sock, buffer, OS_MAXSTR,
118                                MSG_DONTWAIT)) >= 0) || (attempts <= 5)) {
119             if (recv_b <= 0) {
120                 /* Sleep five seconds before trying to get the reply from
121                  * the server again
122                  */
123                 attempts++;
124                 sleep(attempts);
125
126                 /* Send message again (after three attempts) */
127                 if (attempts >= 3) {
128                     send_msg(0, msg);
129                 }
130
131                 continue;
132             }
133
134             /* Id of zero -- only one key allowed */
135             tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b - 1);
136             if (tmp_msg == NULL) {
137                 merror(MSG_ERROR, ARGV0, agt->rip[agt->rip_id]);
138                 continue;
139             }
140
141             /* Check for commands */
142             if (IsValidHeader(tmp_msg)) {
143                 /* If it is an ack reply */
144                 if (strcmp(tmp_msg, HC_ACK) == 0) {
145                     available_server = time(0);
146
147                     verbose(AG_CONNECTED, ARGV0, agt->rip[agt->rip_id],
148                             agt->port);
149
150                     if (is_startup) {
151                         /* Send log message about start up */
152                         snprintf(msg, OS_MAXSTR, OS_AG_STARTED,
153                                  keys.keyentries[0]->name,
154                                  keys.keyentries[0]->ip->ip);
155                         snprintf(fmsg, OS_MAXSTR, "%c:%s:%s", LOCALFILE_MQ,
156                                  "ossec", msg);
157                         send_msg(0, fmsg);
158                     }
159                     return;
160                 }
161             }
162         }
163
164         /* Wait for server reply */
165         merror(AG_WAIT_SERVER, ARGV0, agt->rip[agt->rip_id]);
166
167         /* If we have more than one server, try all */
168         if (agt->rip[1]) {
169             int curr_rip = agt->rip_id;
170             merror("%s: INFO: Trying next server in the line: '%s'.", ARGV0,
171                    agt->rip[agt->rip_id + 1] != NULL ? agt->rip[agt->rip_id + 1] : agt->rip[0]);
172             connect_server(agt->rip_id + 1);
173
174             if (agt->rip_id == curr_rip) {
175                 sleep(g_attempts);
176                 g_attempts += (attempts * 3);
177             } else {
178                 g_attempts += 5;
179                 sleep(g_attempts);
180             }
181         } else {
182             sleep(g_attempts);
183             g_attempts += (attempts * 3);
184
185             connect_server(0);
186         }
187     }
188
189     return;
190 }
191