/* * check_ice: Nagios plugin to check if a ICE or Shoucast stream is up. * Usage:check_ice -H host -p port [-m mount_point] Example: check_ice -H * stream.icecast.org -p 8000 -m /foobar * * Much of the socket code is stolen from: * http://pont.net/socket/prog/tcpClient.c Put up by Frederic Pont at * fred@pont.net * * The rest of it is copyright 2008 Tim Pozar * modified 2011-03-20 by Matthias Eller * */ #include #include #include #include #include #include #include /* close */ #include #include #define LF 10 #define BUF_SIZE 4096 char verrev [BUF_SIZE] = "$Id: check_ice.c,v 1.5 2008/10/07 04:11:13 pozar Exp $"; char hostname [BUF_SIZE] = "scfire-dtc-aa01.stream.aol.com"; char mount [BUF_SIZE] = "/"; char send_string[BUF_SIZE] = ""; char recv_string[BUF_SIZE] = ""; int portnum = 80; int main(int argc, char *argv[]) { int sd , rc, i, min_size; struct sockaddr_in localAddr, servAddr; struct hostent *h; if (argc < 2) { banner(); exit(3); } min_size=0; /* scan command line arguments, and look for files to work on. */ for (i = 1; i < argc; i++) { switch (argv[i][1]) { /* be case indepenent... */ case 'H': /* Hostname... */ i++; strncpy(hostname, argv[i], BUF_SIZE); break; case 'p': i++; if (argv[i]) { portnum = atoi(argv[i]); } break; case 'm': i++; /* We need a slash in front of the mount... */ if (argv[i]) { if ('/' != argv[i][0]) { sprintf(mount, "/%s", argv[i]); } else { strncpy(mount, argv[i], BUF_SIZE); } } break; case 's': /*set minimum receive size*/ i++; if (argv[i]) { min_size = atoi(argv[i]); } break; default: printf("I don't know the meaning of the command line argument: \"%s\".\n", argv[i]); banner(); exit(3); } } h = gethostbyname(hostname); if (h == NULL) { printf("%s: unknown host '%s'\n", argv[0], hostname); exit(3); } servAddr.sin_family = h->h_addrtype; memcpy((char *)&servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); servAddr.sin_port = htons(portnum); /* create socket */ sd = socket(AF_INET, SOCK_STREAM, 0); if (sd < 0) { perror("cannot open socket "); exit(3); } /* bind any port number */ localAddr.sin_family = AF_INET; localAddr.sin_addr.s_addr = htonl(INADDR_ANY); localAddr.sin_port = htons(0); rc = bind(sd, (struct sockaddr *)&localAddr, sizeof(localAddr)); if (rc < 0) { printf("%s: cannot bind port TCP %u\n", argv[0], portnum); perror("error "); exit(3); } /* connect to server */ rc = connect(sd, (struct sockaddr *)&servAddr, sizeof(servAddr)); if (rc < 0) { perror("cannot connect "); exit(2); } sprintf(send_string, "GET %s HTTP/1.1 Accept: */*\n\n", mount); rc = send(sd, send_string, strlen(send_string) + 1, 0); if (rc < 0) { perror("cannot send data "); close(sd); exit(2); } /* rc = recv(sd, recv_string, BUF_SIZE, 0); */ rc = readline(sd, recv_string); if (rc < 0) { perror("cannot recv data "); close(sd); exit(2); } if (rc == 0) { printf("Got zero bytes back.\n"); exit(2); } else { if (0 < strstr(recv_string, " 200 ")) { if (min_size > 0) { check_for_data(sd, min_size); } else { printf("Stream at: \"http://%s:%i%s\" is up.\n", hostname, portnum, mount); exit(0); } } if (0 < strstr(recv_string, " 206 ")) { printf("Stream at: \"http://%s:%i%s\" is up but only partially.\n", hostname, portnum, mount); exit(1); } if (0 < strstr(recv_string, " 400 ")) { printf("Stream at: \"http://%s:%i%s\" is full.\n", hostname, portnum, mount); exit(2); } if (0 < strstr(recv_string, " 401 ")) { printf("Stream at: \"http://%s:%i%s\" was not found.\n", hostname, portnum, mount); exit(2); } if (0 < strstr(recv_string, " 403 ")) { printf("Stream at: \"http://%s:%i%s\" was not found.\n", hostname, portnum, mount); exit(2); } if (0 < strstr(recv_string, " 404 ")) { printf("Stream at: \"http://%s:%i%s\" was not found.\n", hostname, portnum, mount); exit(2); } if (0 < strstr(recv_string, " 416 ")) { printf("Stream at: \"http://%s:%i%s\" was not found.\n", hostname, portnum, mount); exit(2); } if (0 < strstr(recv_string, " 500 ")) { printf("Stream at: \"http://%s:%i%s\" encountered a server error.\n", hostname, portnum, mount); exit(2); } if (0 < strstr(recv_string, " 503 ")) { printf("Stream at: \"http://%s:%i%s\" was not found.\n", hostname, portnum, mount); exit(2); } } /* We really shouldn't get this far... */ printf("Unknown state for stream at: \"http://%s:%i%s\"\n", hostname, portnum, mount); exit(3); } check_for_data(int sd, int min_size) { int rc; rc = read_timeout(sd, min_size); if (rc >= min_size) { printf("Stream at: \"http://%s:%i%s\" is up and delivers data.\n", hostname, portnum, mount); close(sd); exit(0); } else { printf("Stream at: \"http://%s:%i%s\" is up but to less data. %i < %i\n", hostname, portnum, mount, rc, min_size); close(sd); exit(2); } } int read_timeout(int fip, int min_size) { int i = 0; int timeout = 0; char c; int ret; while(i < min_size && timeout < 100) { ret = read(fip, &c, sizeof(char)); if (ret < 1) { timeout++; } i++; } return (i); } readline(fip, buffer) int fip; char *buffer; { int i = 0; char c; int ret; bzero(buffer, BUF_SIZE); while (i < BUF_SIZE) { ret = read(fip, &c, sizeof(char)); if (ret < 1) break; if (c == LF) break; buffer[i] = c; i++; } return (i); } banner() { printf("check_ice: Nagios plugin to check if a ICE or Shoucast stream is up and delivers data.\n"); printf("Usage:check_ice -H host -p port [-m mount_point] [-s minimum_data_size]\n"); printf(" Example: check_ice -H stream.icecast.org -p 8000 -m /foobar -s 10000\n"); return; }