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