1 /*
2 * check_ssh.c
3 *
4 * Made by (Remi PAULMIER)
5 * Login <remi@sinfomic.fr>
6 *
7 * Started on Fri Jul 9 09:18:23 1999 Remi PAULMIER
8 * Update Thu Jul 22 12:50:04 1999 remi paulmier
9 * $Id$
10 *
11 */
13 #include "config.h"
14 #include "common.h"
15 #include "netutils.h"
16 #include "utils.h"
18 #define PROGNAME "check_ssh"
20 #ifndef MSG_DONTWAIT
21 #define MSG_DONTWAIT 0
22 #endif
24 #define SSH_DFL_PORT 22
25 #define BUFF_SZ 256
27 short port = -1;
28 char *server_name = NULL;
29 int verbose = FALSE;
31 int process_arguments (int, char **);
32 int call_getopt (int, char **);
33 int validate_arguments (void);
34 void print_help (void);
35 void print_usage (void);
37 char *ssh_resolve (char *hostname);
38 int ssh_connect (char *haddr, short hport);
40 int
41 main (int argc, char **argv)
42 {
44 if (process_arguments (argc, argv) == ERROR)
45 usage ("Could not parse arguments\n");
47 /* initialize alarm signal handling */
48 signal (SIGALRM, socket_timeout_alarm_handler);
49 alarm (socket_timeout);
51 /* ssh_connect exits if error is found */
52 ssh_connect (ssh_resolve (server_name), port);
54 alarm (0);
56 return (STATE_OK);
57 }
60 /* process command-line arguments */
61 int
62 process_arguments (int argc, char **argv)
63 {
64 int c;
66 if (argc < 2)
67 return ERROR;
69 for (c = 1; c < argc; c++)
70 if (strcmp ("-to", argv[c]) == 0)
71 strcpy (argv[c], "-t");
73 c = 0;
74 while (c += (call_getopt (argc - c, &argv[c]))) {
75 if (argc <= c)
76 break;
77 if (server_name == NULL) {
78 server_name = argv[c];
79 }
80 else if (port == -1) {
81 if (is_intpos (argv[c])) {
82 port = atoi (argv[c]);
83 }
84 else {
85 print_usage ();
86 exit (STATE_UNKNOWN);
87 }
88 }
89 }
91 return validate_arguments ();
92 }
95 /************************************************************************
96 *
97 * Run the getopt until we encounter a non-option entry in the arglist
98 *
99 *-----------------------------------------------------------------------*/
101 int
102 call_getopt (int argc, char **argv)
103 {
104 int c, i = 1;
106 #ifdef HAVE_GETOPT_H
107 int option_index = 0;
108 static struct option long_options[] = {
109 {"version", no_argument, 0, 'V'},
110 {"help", no_argument, 0, 'h'},
111 {"verbose", no_argument, 0, 'v'},
112 {"timeout", required_argument, 0, 't'},
113 {"host", required_argument, 0, 'H'},
114 {0, 0, 0, 0}
115 };
116 #endif
118 while (1) {
119 #ifdef HAVE_GETOPT_H
120 c = getopt_long (argc, argv, "+Vhvt:H:p:", long_options, &option_index);
121 #else
122 c = getopt (argc, argv, "+Vhvt:H:p:");
123 #endif
125 if (c == -1 || c == EOF)
126 break;
128 i++;
129 switch (c) {
130 case 't':
131 case 'H':
132 case 'p':
133 i++;
134 }
136 switch (c) {
137 case '?': /* help */
138 usage ("");
139 case 'V': /* version */
140 print_revision (my_basename (argv[0]), "$Revision$");
141 exit (STATE_OK);
142 case 'h': /* help */
143 print_help ();
144 exit (STATE_OK);
145 case 'v': /* verose */
146 verbose = TRUE;
147 break;
148 case 't': /* timeout period */
149 if (!is_integer (optarg))
150 usage ("Timeout Interval must be an integer!\n\n");
151 socket_timeout = atoi (optarg);
152 break;
153 case 'H': /* host */
154 server_name = optarg;
155 break;
156 case 'p': /* port */
157 if (is_intpos (optarg)) {
158 port = atoi (optarg);
159 }
160 else {
161 printf ("Port number nust be a positive integer: %s\n", optarg);
162 usage ("");
163 }
164 }
166 }
167 return i;
168 }
170 int
171 validate_arguments (void)
172 {
173 if (server_name == NULL)
174 return ERROR;
175 if (port == -1) /* funky, but allows -p to override stray integer in args */
176 port = SSH_DFL_PORT;
177 return OK;
178 }
181 /************************************************************************
182 *
183 * Resolve hostname into IP address
184 *
185 *-----------------------------------------------------------------------*/
187 char *
188 ssh_resolve (char *hostname)
189 {
190 struct hostent *host;
192 host = gethostbyname (hostname);
193 if (!host) {
194 herror (hostname);
195 exit (STATE_CRITICAL);
196 }
197 return (host->h_addr);
198 }
201 /************************************************************************
202 *
203 * Try to connect to SSH server at specified server and port
204 *
205 *-----------------------------------------------------------------------*/
207 int
208 ssh_connect (char *haddr, short hport)
209 {
210 int s;
211 struct sockaddr_in addr;
212 int addrlen;
213 int len;
214 char *output = NULL;
215 char *buffer = NULL;
216 char *ssh_proto = NULL;
217 char *ssh_server = NULL;
218 char revision[20];
220 sscanf ("$Revision$", "$Revision: %[0123456789.]", revision);
222 addrlen = sizeof (addr);
223 memset (&addr, 0, addrlen);
224 addr.sin_port = htons (hport);
225 addr.sin_family = AF_INET;
226 bcopy (haddr, (void *) &addr.sin_addr.s_addr, 4);
228 s = socket (AF_INET, SOCK_STREAM, 0);
229 if (!s) {
230 printf ("socket(): %s for %s:%d\n", strerror (errno), server_name, hport);
231 exit (STATE_CRITICAL);
232 }
234 if (connect (s, (struct sockaddr *) &addr, addrlen)) {
235 printf ("connect(): %s for %s:%d\n", strerror (errno), server_name,
236 hport);
237 exit (STATE_CRITICAL);
238 }
240 output = (char *) malloc (BUFF_SZ + 1);
241 memset (output, 0, BUFF_SZ + 1);
242 recv (s, output, BUFF_SZ, 0);
243 if (strncmp (output, "SSH", 3)) {
244 printf ("Server answer: %s", output);
245 exit (STATE_CRITICAL);
246 }
247 else {
248 strip (output);
249 if (verbose)
250 printf ("%s\n", output);
251 ssh_proto = output + 4;
252 ssh_server = ssh_proto + strspn (ssh_proto, "0123456789-. ");
253 ssh_proto[strspn (ssh_proto, "0123456789-. ")] = 0;
254 printf
255 ("SSH ok - protocol version %s - server version %s\n",
256 ssh_proto, ssh_server);
257 buffer =
258 ssprintf (buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, revision);
259 send (s, buffer, strlen (buffer), MSG_DONTWAIT);
260 if (verbose)
261 printf ("%s\n", buffer);
262 exit (STATE_OK);
263 }
264 }
266 void
267 print_help (void)
268 {
269 print_revision (PROGNAME, "$Revision$");
270 printf ("Copyright (c) 1999 Remi Paulmier (remi@sinfomic.fr)\n\n");
271 print_usage ();
272 printf ("by default, port is %d\n", SSH_DFL_PORT);
273 }
275 void
276 print_usage (void)
277 {
278 printf
279 ("Usage:\n"
280 " %s -t [timeout] -p [port] <host>\n"
281 " %s -V prints version info\n"
282 " %s -h prints more detailed help\n", PROGNAME, PROGNAME, PROGNAME);
283 }
285 /* end of check_ssh.c */