Imported Upstream version 2.3
[ossec-hids.git] / src / client-agent / start_agent.c
1 /* @(#) $Id: start_agent.c,v 1.17 2009/12/01 15:40:07 dcid Exp $ */
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 3) 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         close(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     /* Sending start message and waiting for the ack */ 
165     while(1)
166     {
167         /* Sending start up message */
168         send_msg(0, msg);
169         attempts = 0;
170         
171
172         /* Read until our reply comes back */
173         while(((recv_b = recv(logr->sock, buffer, OS_MAXSTR,
174                               MSG_DONTWAIT)) >= 0) || (attempts <= 5))
175         {
176             if(recv_b <= 0)
177             {
178                 /* Sleep five seconds before trying to get the reply from
179                  * the server again.
180                  */
181                 attempts++;
182                 sleep(attempts);
183
184                 /* Sending message again (after three attempts) */
185                 if(attempts >= 3)
186                 {
187                     send_msg(0, msg);
188                 }
189                 
190                 continue;
191             }
192             
193             /* Id of zero -- only one key allowed */
194             tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b -1);
195             if(tmp_msg == NULL)
196             {
197                 merror(MSG_ERROR, ARGV0, logr->rip[logr->rip_id]);
198                 continue;
199             }
200
201
202             /* Check for commands */
203             if(IsValidHeader(tmp_msg))
204             {
205                 /* If it is an ack reply */
206                 if(strcmp(tmp_msg, HC_ACK) == 0)
207                 {
208                     available_server = time(0);
209
210                     verbose(AG_CONNECTED, ARGV0, logr->rip[logr->rip_id], 
211                                                  logr->port);
212                     
213                     if(is_startup)
214                     {
215                         /* Send log message about start up */
216                         snprintf(msg, OS_MAXSTR, OS_AG_STARTED, 
217                                 keys.keyentries[0]->name,
218                                 keys.keyentries[0]->ip->ip);
219                         snprintf(fmsg, OS_MAXSTR, "%c:%s:%s", LOCALFILE_MQ, 
220                                                   "ossec", msg);
221                         send_msg(0, fmsg);
222                     }
223                     return;
224                 }
225             }
226         }
227
228         /* Waiting for servers reply */
229         merror(AG_WAIT_SERVER, ARGV0, logr->rip[logr->rip_id]);
230
231
232         /* If we have more than one server, try all. */
233         if(logr->rip[1])
234         {
235             int curr_rip = logr->rip_id;
236             merror("%s: INFO: Trying next server ip in the line: '%s'.", ARGV0,
237                    logr->rip[logr->rip_id + 1] != NULL?logr->rip[logr->rip_id + 1]:logr->rip[0]);
238             connect_server(logr->rip_id +1);
239
240             if(logr->rip_id == curr_rip)
241             {
242                 sleep(g_attempts);
243                 g_attempts+=(attempts * 3);
244             }
245             else
246             {
247                 g_attempts+=5;
248                 sleep(g_attempts);
249             }
250         }
251         else
252         {
253             sleep(g_attempts);
254             g_attempts+=(attempts * 3);
255             
256             connect_server(0);
257         }
258     }
259     
260
261     return;
262 }
263
264
265
266 /* EOF */