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