1 /*-
2 * Copyright (c) 1998-2008 DHIS, Dynamic Host Information System
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28
29 #include "dhisd.h"
30 #include "nsupdate.h"
31 #include "online.h"
32 #include "network.h"
33 #include "misc.h"
34 #include "ddb.h"
35
36 #include <string.h>
37 #include <time.h>
38
39 online_t *onbase=NULL;
40
on_add(int id,int addr,int port,int vers,int refresh)41 int on_add(int id,int addr,int port,int vers,int refresh) {
42
43 online_t *p;
44
45 int proto;
46 if(vers<30) return 0;
47 if(vers<40) proto=3;
48 else if(vers<50) proto=4;
49 else proto=5;
50
51 p=onbase;
52 if(p!=NULL)
53 while(p->next!=NULL) p=p->next;
54 if(p==NULL) {
55 onbase=(online_t *)malloc(sizeof(online_t));
56 p=onbase;
57 } else {
58 p->next=(online_t *)malloc(sizeof(online_t));
59 p=p->next;
60 }
61 if(p==NULL) return(0);
62 p->next=NULL;
63 p->id=id;
64 p->addr=addr;
65 if(proto>=4) p->port=port;
66 else p->port=DHISD_PORT;
67 p->proto=proto;
68 p->check_fails=0;
69 p->sid=0;
70 if(vers>=54) p->client_refresh=1;
71 else p->client_refresh=0;
72
73 if(refresh>=MIN_NEXT_CHECK && refresh <=MAX_NEXT_CHECK) {
74 p->refresh=refresh;
75 }
76 else {
77
78 if(refresh)
79 DSYSLOG(1,(LOG_DEBUG,"on_add(): Refresh rate out of limits\n"));
80
81 p->refresh=NEXT_CHECK;
82 }
83 if(p->proto>=4)
84 p->ka=time(NULL) + p->refresh;
85 else
86 p->ka=time(NULL);
87
88 srandom(time(NULL));
89 while(!(p->sid=random()));
90
91 DSYSLOG(1,(LOG_DEBUG,"on_add(): Marking Host %d Online\n",p->id));
92
93 mark_online(p->id,p->addr);
94
95 return(p->sid);
96 }
97
on_delete(int id)98 int on_delete(int id) {
99
100 online_t *p1,*p2;
101
102 p2=onbase;
103 p1=onbase;
104 while(p1!=NULL) {
105 if(p1->id==id) break;
106 p2=p1;
107 p1=p1->next;
108 }
109
110 if(p1==NULL) return(0);
111
112 if(p1==onbase) onbase=p1->next;
113 else p2->next=p1->next;
114
115 DSYSLOG(1,(LOG_DEBUG,"on_delete(): Marking Host %d Offline\n",p1->id));
116 mark_offline(p1->id,p1->addr);
117 free(p1);
118 return(1);
119 }
120
on_update(int id,int addr,int port,int vers,int refresh)121 int on_update(int id,int addr,int port,int vers,int refresh) {
122
123 online_t *p;
124 int oaddr;
125
126
127 int proto;
128 if(vers<30) return 0;
129 else if(vers<40) proto=3;
130 else if(vers<50) proto=4;
131 else proto=5;
132
133 p=onbase;
134 while(p!=NULL) {
135 if(p->id==id) break;
136 p=p->next;
137 }
138
139 if(p==NULL) {
140 return(on_add(id,addr,port,vers,refresh));
141 }
142
143 if(proto>=4) {
144 p->ka=time(NULL)+p->refresh;
145 p->check_fails=0;
146 }
147 else
148 p->ka=time(NULL);
149
150 if(p->addr==addr) return(p->sid);
151
152 DSYSLOG(1,(LOG_DEBUG,"on_update(): Updating host %d \n",p->id));
153
154 oaddr= p->addr;
155 p->addr=addr;
156 mark_update(p->id,p->addr,oaddr);
157
158 return(p->sid);
159 }
160
on_parse(void)161 int on_parse(void) {
162
163 online_t *p1,*p2;
164 time_t t = time(NULL);
165
166 DSYSLOG(2,(LOG_DEBUG,"on_parse(): Executing.\n"));
167
168 p2=onbase;
169 p1=onbase;
170 while(p1!=NULL) {
171
172
173 p2=p1->next;
174 if(db_is_locked(p1->id)) {
175 on_delete(p1->id);
176 p1=p2;
177 continue;
178 }
179 if(p1->proto==3)
180 if((t - p1->ka) > KA_OFFLINE)
181 on_delete(p1->id);
182 if(p1->proto==4 || p1->proto ==5) {
183 if(p1->check_fails >= CHECK_FAILS)
184 on_delete(p1->id);
185 else {
186 if (p1->proto == 4) {
187 if(p1->ka < t) {
188 r4_check_req_t m;
189
190 DSYSLOG(1,(LOG_DEBUG,"on_parse(): Sending R4_CHECK_REQ to %d\n",
191 p1->id));
192
193 m.hdr.opcode=R4_CHECK_REQ;
194 m.next_check=p1->refresh;
195 net_write_message((msg_t *)&m,p1->addr,p1->port);
196 p1->check_fails++;
197 } /* end if ka */
198 } /* end proto */
199
200 if(p1->proto==5) {
201 if(p1->ka < t) {
202 if(p1->client_refresh) {
203 p1->ka=time(NULL)+p1->refresh;
204 } else {
205 check_req_t m;
206
207 DSYSLOG(1,(LOG_DEBUG,"on_parse(): Sending CHECK_REQ to %d\n",p1->id));
208
209 m.hdr.opcode=CHECK_REQ;
210 m.hdr.hostid=p1->id;
211 m.next_check=p1->refresh;
212 net_write_message((msg_t *)&m,p1->addr,p1->port);
213 }
214 p1->check_fails++;
215 } /* end if ka */
216 } /* end proto 5 */
217 }}
218 p1=p2;
219 }
220 return(1);
221 }
222
on_free(void)223 void on_free(void) {
224
225 online_t *op;
226
227 op=onbase;
228 while(op!=NULL) {
229 mark_offline(op->id,op->addr);
230 op=op->next;
231 free(onbase);
232 onbase=op;
233 }
234 }
235
236
237
mark_online(int id,int addr)238 void mark_online(int id,int addr) {
239
240 struct in_addr sa;
241 char addrs[32];
242 char str[512];
243 struct dhis_rec *dp;
244 sa.s_addr=addr;
245 strcpy(addrs,inet_ntoa((struct in_addr)sa));
246
247 dp=get_rec(id);
248 DSYSLOG(1,(LOG_DEBUG,"mark_online() Got record from databse"));
249
250 if(dp==NULL) return;
251 if(!dp->status) return;
252
253 DSYSLOG(1,(LOG_DEBUG,"mark_online() %d %s\n",id,addrs));
254
255 dns_update(NSUPDATE_DEL,dp->hostname,"");
256 dns_update(NSUPDATE_ADD,dp->hostname,addrs);
257
258 sprintf(str,"-> online (%d) %s [%s]",dp->hostid,dp->hostname,addrs);
259 msg_log(str);
260
261 #ifdef WITH_MYSQL
262 sql_update_lastlogin(dp->hostid);
263 #endif
264
265 if(dp->oncmd!=NULL)
266 if(dp->oncmd[0]!='\0')
267 fork_cmd(dp->oncmd,id,addrs);
268
269 return;
270 }
271
mark_offline(int id,int addr)272 void mark_offline(int id,int addr) {
273
274 struct in_addr sa;
275 char addrs[32];
276 char str[512];
277 struct dhis_rec *dp;
278
279 sa.s_addr=addr;
280 strcpy(addrs,inet_ntoa((struct in_addr)sa));
281
282 dp=get_rec(id);
283 if(dp==NULL) return;
284
285 DSYSLOG(1,(LOG_DEBUG,"mark_offline() %d %s\n",id,addrs));
286
287 dns_update(NSUPDATE_DEL,dp->hostname,"");
288 dns_update(NSUPDATE_ADD,dp->hostname,DYN_IP);
289
290 sprintf(str,"-> offline (%d) %s [%s]",dp->hostid,dp->hostname,addrs);
291 msg_log(str);
292
293 if(dp->offcmd!=NULL)
294 if(dp->offcmd[0]!='\0')
295 fork_cmd(dp->offcmd,id,addrs);
296
297 return;
298 }
299
mark_update(int id,int addr,int oaddr)300 void mark_update(int id,int addr,int oaddr) {
301
302 struct in_addr sa,osa;
303 char addrs[32],oaddrs[32];
304 char str[512];
305 struct dhis_rec *dp;
306
307 sa.s_addr=addr;
308 osa.s_addr=oaddr;
309 strcpy(addrs,inet_ntoa((struct in_addr)sa));
310 strcpy(oaddrs,inet_ntoa((struct in_addr)osa));
311
312 dp=get_rec(id);
313
314 if(dp==NULL) return;
315 if(!dp->status) return;
316
317 DSYSLOG(1,(LOG_DEBUG,"mark_update() %d %s -> %s\n",id,oaddrs,addrs));
318
319 dns_update(NSUPDATE_DEL,dp->hostname,"");
320 dns_update(NSUPDATE_ADD,dp->hostname,addrs);
321
322 sprintf(str,"-> update (%d) %s [%s -> %s]",dp->hostid,dp->hostname,
323 oaddrs,addrs);
324 msg_log(str);
325
326 if(dp->offcmd!=NULL)
327 if(dp->offcmd[0]!='\0')
328 fork_cmd(dp->offcmd,id,addrs);
329
330 sleep(2); // Wait a little bit
331
332 if(dp->oncmd!=NULL)
333 if(dp->oncmd[0]!='\0')
334 fork_cmd(dp->oncmd,id,addrs);
335
336 return;
337 }
338
fork_cmd(char * cmd,int id,char * addr)339 void fork_cmd(char *cmd,int id,char *addr) {
340
341 char line[1024];
342 char path[1024];
343
344 strcpy(path,line_entry(1,cmd));
345 sprintf(line,"%s %d %s %s",path,id,addr,line_ptr(2,cmd));
346
347 if(!fork()) {
348 system(line);
349 exit(0);
350 }
351 return;
352 }
353
354
355