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