Imported Upstream version 2.7
[ossec-hids.git] / src / client-agent / start_agent.c
1 /* @(#) $Id: ./src/client-agent/start_agent.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All right reserved.
6  *
7  * This program is a free software; you can redistribute it
8  * and/or modify it under the terms of the GNU General Public
9  * License (version 2) as published by the FSF - Free Software
10  * Foundation
11  */
12
13
14 #include "shared.h"
15 #include "agentd.h"
16
17 #include "os_net/os_net.h"
18
19
20 /** void connect_server()
21  *  Attempts to connect to all configured servers.
22  */
23 int connect_server(int initial_id)
24 {
25     int attempts = 2;
26     int rc = initial_id;
27
28
29     /* Checking if the initial is zero, meaning we have to rotate to the
30      * beginning.
31      */
32     if(logr->rip[initial_id] == NULL)
33     {
34         rc = 0;
35         initial_id = 0;
36     }
37
38
39     /* Closing socket if available. */
40     if(logr->sock >= 0)
41     {
42         sleep(1);
43         CloseSocket(logr->sock);
44         logr->sock = -1;
45
46         if(logr->rip[1])
47         {
48             verbose("%s: INFO: Closing connection to server (%s:%d).",
49                     ARGV0,
50                     logr->rip[rc],
51                     logr->port);
52         }
53
54     }
55
56
57     while(logr->rip[rc])
58     {
59         char *tmp_str;
60
61         /* Checking if we have a hostname. */
62         tmp_str = strchr(logr->rip[rc], '/');
63         if(tmp_str)
64         {
65             char *f_ip;
66             *tmp_str = '\0';
67
68             f_ip = OS_GetHost(logr->rip[rc], 5);
69             if(f_ip)
70             {
71                 char ip_str[128];
72                 ip_str[127] = '\0';
73
74                 snprintf(ip_str, 127, "%s/%s", logr->rip[rc], f_ip);
75
76                 free(f_ip);
77                 free(logr->rip[rc]);
78
79                 os_strdup(ip_str, logr->rip[rc]);
80                 tmp_str = strchr(logr->rip[rc], '/');
81                 tmp_str++;
82             }
83             else
84             {
85                 merror("%s: WARN: Unable to get hostname for '%s'.",
86                        ARGV0, logr->rip[rc]);
87                 *tmp_str = '/';
88                 tmp_str++;
89             }
90         }
91         else
92         {
93             tmp_str = logr->rip[rc];
94         }
95
96
97         verbose("%s: INFO: Trying to connect to server (%s:%d).", ARGV0,
98                 logr->rip[rc],
99                 logr->port);
100
101         /* IPv6 address: */
102         if(strchr(tmp_str,':') != NULL)
103         {
104             verbose("%s: INFO: Using IPv6 for: %s .", ARGV0, tmp_str);
105             logr->sock = OS_ConnectUDP(logr->port, tmp_str, 1);
106         }
107         else
108         {
109             verbose("%s: INFO: Using IPv4 for: %s .", ARGV0, tmp_str);
110             logr->sock = OS_ConnectUDP(logr->port, tmp_str, 0);
111         }
112
113         if(logr->sock < 0)
114         {
115             logr->sock = -1;
116             merror(CONNS_ERROR, ARGV0, tmp_str);
117             rc++;
118
119             if(logr->rip[rc] == NULL)
120             {
121                 attempts += 10;
122
123                 /* Only log that if we have more than 1 server configured. */
124                 if(logr->rip[1])
125                     merror("%s: ERROR: Unable to connect to any server.",ARGV0);
126
127                 sleep(attempts);
128                 rc = 0;
129             }
130         }
131         else
132         {
133             /* Setting socket non-blocking on HPUX */
134             #ifdef HPUX
135             //fcntl(logr->sock, O_NONBLOCK);
136             #endif
137
138             #ifdef WIN32
139             int bmode = 1;
140
141             /* Setting socket to non-blocking */
142             ioctlsocket(logr->sock, FIONBIO, (u_long FAR*) &bmode);
143             #endif
144
145             logr->rip_id = rc;
146             return(1);
147         }
148     }
149
150     return(0);
151 }
152
153
154
155 /* start_agent: Sends the synchronization message to
156  * the server and waits for the ack.
157  */
158 void start_agent(int is_startup)
159 {
160     int recv_b = 0, attempts = 0, g_attempts = 1;
161
162     char *tmp_msg;
163     char msg[OS_MAXSTR +2];
164     char buffer[OS_MAXSTR +1];
165     char cleartext[OS_MAXSTR +1];
166     char fmsg[OS_MAXSTR +1];
167
168
169     memset(msg, '\0', OS_MAXSTR +2);
170     memset(buffer, '\0', OS_MAXSTR +1);
171     memset(cleartext, '\0', OS_MAXSTR +1);
172     memset(fmsg, '\0', OS_MAXSTR +1);
173     snprintf(msg, OS_MAXSTR, "%s%s", CONTROL_HEADER, HC_STARTUP);
174
175
176     #ifdef ONEWAY
177     return;
178     #endif
179
180
181     /* Sending start message and waiting for the ack */ 
182     while(1)
183     {
184         /* Sending start up message */
185         send_msg(0, msg);
186         attempts = 0;
187
188
189         /* Read until our reply comes back */
190         while(((recv_b = recv(logr->sock, buffer, OS_MAXSTR,
191                               MSG_DONTWAIT)) >= 0) || (attempts <= 5))
192         {
193             if(recv_b <= 0)
194             {
195                 /* Sleep five seconds before trying to get the reply from
196                  * the server again.
197                  */
198                 attempts++;
199                 sleep(attempts);
200
201                 /* Sending message again (after three attempts) */
202                 if(attempts >= 3)
203                 {
204                     send_msg(0, msg);
205                 }
206
207                 continue;
208             }
209
210             /* Id of zero -- only one key allowed */
211             tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b -1);
212             if(tmp_msg == NULL)
213             {
214                 merror(MSG_ERROR, ARGV0, logr->rip[logr->rip_id]);
215                 continue;
216             }
217
218
219             /* Check for commands */
220             if(IsValidHeader(tmp_msg))
221             {
222                 /* If it is an ack reply */
223                 if(strcmp(tmp_msg, HC_ACK) == 0)
224                 {
225                     available_server = time(0);
226
227                     verbose(AG_CONNECTED, ARGV0, logr->rip[logr->rip_id],
228                                                  logr->port);
229
230                     if(is_startup)
231                     {
232                         /* Send log message about start up */
233                         snprintf(msg, OS_MAXSTR, OS_AG_STARTED,
234                                 keys.keyentries[0]->name,
235                                 keys.keyentries[0]->ip->ip);
236                         snprintf(fmsg, OS_MAXSTR, "%c:%s:%s", LOCALFILE_MQ,
237                                                   "ossec", msg);
238                         send_msg(0, fmsg);
239                     }
240                     return;
241                 }
242             }
243         }
244
245         /* Waiting for servers reply */
246         merror(AG_WAIT_SERVER, ARGV0, logr->rip[logr->rip_id]);
247
248
249         /* If we have more than one server, try all. */
250         if(logr->rip[1])
251         {
252             int curr_rip = logr->rip_id;
253             merror("%s: INFO: Trying next server ip in the line: '%s'.", ARGV0,
254                    logr->rip[logr->rip_id + 1] != NULL?logr->rip[logr->rip_id + 1]:logr->rip[0]);
255             connect_server(logr->rip_id +1);
256
257             if(logr->rip_id == curr_rip)
258             {
259                 sleep(g_attempts);
260                 g_attempts+=(attempts * 3);
261             }
262             else
263             {
264                 g_attempts+=5;
265                 sleep(g_attempts);
266             }
267         }
268         else
269         {
270             sleep(g_attempts);
271             g_attempts+=(attempts * 3);
272
273             connect_server(0);
274         }
275     }
276
277
278     return;
279 }
280
281
282
283 /* EOF */