1 /*
2  * This file is not what it would appear to be at first look
3  *
4  * This file is not what becomes the sysmon file in the src
5  * directory, that is client.c, this is the sysmond <-> sysmond
6  * checks.
7  *
8  */
9 
10 #include "config.h"
11 
12 struct sysmon_data {
13 	time_t start;
14 	time_t lastact;
15 	int state;
16 	} ;
17 
18 #define SYSMON_CONNECT		1
19 #define SYSMON_WAITBAN		2
20 #define SYSMON_SENT_QUIT	3
21 #define SYSMON_GOT_BYE		4
22 
23 /* How sysmon client-srv stuff works.
24  *
25  * We connect to port 1345 of the remote sysmond, and it sends
26  * a banner reading:
27  * 111 - v1.0 Ready
28  * At this point, we know that it is answering client-queries, and
29  * hence, at least doing most of its job properly.
30  *
31  * We send a QUIT to it, and read the following banner:
32  * 333 Good Bye, please come again
33  * or some sort, of banner with 333 in it, which means "END OF LINE"
34  *
35  * The rest of it, basically looks like the other interactive
36  * client <-> server checks that we perform (SMTP, NNTP, etc..)
37  *
38  */
39 
start_check_sysmon(struct monitorent * here,time_t now_t)40 void start_check_sysmon(struct monitorent *here, time_t now_t)
41 {
42 	/* begin connect() */
43         struct sysmon_data *localstruct = NULL;
44         struct my_hostent *hp = NULL;
45         struct sockaddr_in name;
46         int serrno = -1, errcode = 0;
47 
48         /* Allocate our memory */
49         here->monitordata = MALLOC(sizeof(struct sysmon_data), "sysmon-localstruct");
50 
51         localstruct = here->monitordata;
52 
53         localstruct->start = now_t;
54 
55 	localstruct->lastact = localstruct->start;
56 
57         here->filedes = open_sock();
58 
59         if (here->filedes == -1)
60 	{
61 		here->retval = here->checkent->lastcheck;
62 		FREE(here->monitordata);
63 		return;
64 	}
65 
66         hp = my_gethostbyname(here->checkent->hostname, AF_INET);
67 
68 	if (hp == NULL)
69 	{
70 		here->retval = SYSM_NODNS;
71 		FREE(here->monitordata);
72 		return;
73 	}
74 
75         /* zero out the space */
76         memset ( &name, 0, sizeof ( name ) );
77 
78         /* copy data */
79         memcpy((char*)&name.sin_addr, (char*)hp->my_h_addr_v4, hp->h_length_v4);
80 
81         /* set family type */
82         name.sin_family = AF_INET;
83 
84         /* set the port we're connecting to */
85         name.sin_port = htons(SYSMON_PORTNUM);
86 
87         if (debug)
88 		print_err(0, "start_test_sysmon() doing connect() to %s:%d",
89                 	here->checkent->hostname, SYSMON_PORTNUM);
90 
91         errcode = connect(here->filedes, (struct sockaddr*)&name,
92                 sizeof(struct sockaddr_in));
93 	serrno = errno;
94 	if (debug)
95 		perror("connect() in start_sysmon");
96 
97         if ((errcode < 0) && (serrno != EINPROGRESS))
98         {
99                 if (close(here->filedes) == -1)
100 		{
101 			perror("sysmon.c: closing fd");
102 		}
103 		here->retval = errno_to_error(serrno);
104 
105 	        /* Free memory we'd normally leak */
106 	        FREE(localstruct);
107 	        here->monitordata = NULL;
108 
109 		print_err(0, "sysmon.c: retval = %d", here->retval);
110 		return;
111         }
112 
113 	/* doing a connect() */
114 	localstruct->state = SYSMON_CONNECT;
115 
116         /* poll it again later */
117         return;
118 }
119 
service_check_sysmon(struct monitorent * here,time_t now_t)120 void service_check_sysmon(struct monitorent *here, time_t now_t)
121 {
122 	/* finish connect() */
123 	/* do the actual real parts of the checks after
124 	   it's been set up */
125 
126 	struct sysmon_data *localstruct = NULL;
127 	char buffer[256];
128         int isopenretval = -1;
129 	int state = 0;
130 
131 	/* do some variable shufflign */
132 	localstruct = here->monitordata;
133 	if (localstruct == NULL)
134 	{
135 		print_err(0, "bug! localstruct == NULL in sysmon.c:service_test_sysmon");
136 		return;
137 	}
138 
139 	if (debug)
140 	print_err(0, "in service_test_sysmon and the state is %d",localstruct->state);
141 
142 	/* do different things based on the state */
143 	state = localstruct->state;
144 	switch (state)
145 	{
146 		case SYSMON_CONNECT:
147 		{
148 			isopenretval = is_open(here->filedes);
149 		        if ((isopenretval != -1) &&
150 				(isopenretval != SYSM_INPROG))
151 		        {
152 				localstruct->lastact = now_t;
153 		                if (debug)
154 					print_err(0, "is_open() in service_test_sysmon()");
155 				if (isopenretval != SYSM_OK)
156 				{
157 			                here->retval = isopenretval;
158 			                close(here->filedes);
159 			                FREE(localstruct);
160 			                here->monitordata = NULL;
161 			                if (debug)
162 						print_err(0, "ending service_test_sysmon() with retval = %s", errtostr(here->retval));
163 					return;
164 				}
165 		                localstruct->state = SYSMON_WAITBAN;
166 				if (debug)
167 				{
168 					print_err(0, "connected() to the sysmon port of %s",
169 						here->checkent->hostname);
170 				}
171         		}
172 			break;
173 		}
174 		case SYSMON_WAITBAN:
175 		{
176 			if (data_waiting_read(here->filedes, 0))
177 			{
178 				memset(buffer, 0, 256);
179 				read(here->filedes, buffer, 254);
180 				buffer[strlen(buffer)-1] = '\0';
181 				if (debug)
182 					print_err(0, "Got :%s:", buffer);
183 				if (strncmp(buffer, "111 ", 4) == 0)
184 				{
185 					localstruct->state = SYSMON_SENT_QUIT;
186 				} else {
187 					here->retval = SYSM_BAD_RESP;
188 				}
189 				sendline(here->filedes, "QUIT");
190 			} else {
191 	                        if ((now_t-(localstruct->start)) >= globtimeout)
192                         	{
193 					here->retval = SYSM_NORESP;
194 					close(here->filedes);
195 					FREE(localstruct);
196 					here->monitordata = NULL;
197 					if (debug)
198 					{
199 	                                        print_err(0, "ending service_test_sysmon() with retval = %s", errtostr(here->retval));
200                                 	}
201 	                                return;
202 				}
203 				break;
204 			}
205 			break;
206 		}
207 		case SYSMON_SENT_QUIT:
208 		{
209                         if (data_waiting_read(here->filedes, 0))
210                         {
211                                 memset(buffer, 0, 256);
212                                 read(here->filedes, buffer, 254);
213                                 buffer[strlen(buffer)-1] = '\0';
214                                 if (debug)
215 					print_err(0, "Got2:%s:", buffer);
216 				if (strncmp(buffer, "333 ", 4) == 0)
217 					localstruct->state = SYSMON_GOT_BYE;
218 				else
219 					here->retval = SYSM_BAD_RESP;
220                         }
221                         break;
222 		}
223 		case SYSMON_GOT_BYE:
224 		{
225 			here->retval = SYSM_OK;
226 			if (debug)
227 				print_err(0, "sysmon: returing a OK value");
228 			break;
229 		}
230 		default:
231 		{
232 			ABORT(); /* Muahaha */
233 			break;
234 		}
235 	}
236 	if (here->retval != -1)
237 	{
238 		/* insert cleanup code here */
239 		close (here->filedes);
240 		FREE(localstruct);
241 		here->monitordata = NULL;
242 	}
243 	return;
244 }
245 
stop_check_sysmon(struct monitorent * here)246 void stop_check_sysmon(struct monitorent *here)
247 {
248 	/* clean up niceley */
249 	struct sysmon_data *localstruct = NULL;
250 
251 	localstruct = here->monitordata;
252 	if (localstruct != NULL)
253 	{
254 		FREE(localstruct);
255 	}
256 
257 	close(here->filedes);
258 	here->monitordata = NULL;
259 	return;
260 }
261 
262 /* No code after here should exist */
263