/OpenIPMI-2.0.18/sample/rmcp_ping.c
C | 324 lines | 269 code | 25 blank | 30 comment | 88 complexity | 3928268a416e252f28af1969ca1d280a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
- /*
- * rmcp_ping.c
- *
- * OpenIPMI RMCP pinger
- *
- * Author: Montavista Software
- * Corey Minyard <cminyard@mvista.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/select.h>
- #include <netdb.h>
- unsigned char ping_msg[12] =
- {
- 0x06, /* RMCP version 1.0 */
- 0x00, /* reserved */
- 0xff, /* RMCP seq num, not used for IPMI */
- 0x06, /* ASF message */
- 0x00, 0x00, 0x11, 0xbe, /* ASF IANA */
- 0x80, /* Presence Ping */
- 0x00, /* Message tag */
- 0x00, /* Reserved */
- 0x00 /* Data Length */
- };
- static char *progname;
- static void
- usage(void)
- {
- fprintf(stderr,
- "Send an RMCP ping packet onces a second to the destination,\n");
- fprintf(stderr,
- "printing unique responses it receives\n");
- fprintf(stderr,
- "Usage:\n");
- fprintf(stderr,
- " %s [-p <port>] [-t <waittime>] [-s <starttag>]"
- " [-d] [destination]\n",
- progname);
- fprintf(stderr,
- " -p - Destination port, defaults to 623\n");
- fprintf(stderr,
- " -t - Sets the number of seconds to wait for responses"
- " (default 10)\n");
- fprintf(stderr,
- " -s - Sets the start tag to start sending at"
- " (0-254, default 0\n");
- fprintf(stderr,
- " -d - enable debugging\n");
- fprintf(stderr,
- " destination - the target address, default is the broadcast\n");
- fprintf(stderr,
- " address (default 255.255.255.255)\n");
- exit(1);
- }
- int port = 0x26f;
- int waittime = 10;
- int starttag = 0;
- int debug_packet = 0;
- struct socklist
- {
- struct in_addr addr;
- struct socklist *next;
- };
- struct socklist *socklist = NULL;
- static int
- add_host(struct sockaddr *addr)
- {
- struct socklist *curr = socklist;
- struct sockaddr_in *ip;
- if (addr->sa_family != AF_INET)
- return 0;
- ip = (struct sockaddr_in *) addr;
- while (curr) {
- if (ip->sin_addr.s_addr == curr->addr.s_addr)
- break;
- curr = curr->next;
- }
- if (curr)
- return 0;
- curr = malloc(sizeof(*curr));
- curr->addr = ip->sin_addr;
- curr->next = socklist;
- socklist = curr;
- return 1;
- }
- int
- main(int argc, char *argv[])
- {
- unsigned char rsp[28];
- int sock;
- int rv;
- struct sockaddr dest;
- size_t destlen;
- struct sockaddr src;
- int val;
- socklen_t fromlen;
- fd_set readfds;
- struct timeval currtime;
- struct timeval endtime;
- struct timeval twait;
- char host[200];
- char serv[200];
- char *addrname;
- int send_next;
- int i;
- char *end;
- progname = argv[0];
- for (i=1; i<argc; i++) {
- if (argv[i][0] != '-')
- break;
- if (argv[i][1] == '\0')
- usage();
- if (strcmp(argv[i], "--") == 0) {
- i++;
- break;
- } else if (strcmp(argv[i], "-p") == 0) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "No parameter given for -p\n\n");
- usage();
- }
- port = strtoul(argv[i], &end, 0);
- if (port < 0 || port > 65535 || *end != '\0') {
- fprintf(stderr, "Wrong port specified for -p\n\n");
- usage();
- }
- } else if (strcmp(argv[i], "-t") == 0) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "No parameter given for -t\n\n");
- usage();
- }
- waittime = strtoul(argv[i], &end, 0);
- if (waittime < 0 || *end != '\0') {
- fprintf(stderr, "Wrong waittime specified for -t\n\n");
- usage();
- }
- } else if (strcmp(argv[i], "-s") == 0) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "No parameter given for -s\n\n");
- usage();
- }
- starttag = strtoul(argv[i], &end, 0);
- if (starttag < 0 || starttag > 254 || *end != '\0') {
- fprintf(stderr, "Invalid start tag for -s\n\n");
- usage();
- }
- } else if (strcmp(argv[i], "-d") == 0) {
- debug_packet++;
- }
- }
-
- if (i < argc) {
- struct addrinfo hints, *res0;
- char ports[16];
- snprintf(ports, sizeof(ports), "%d", port);
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM;
- rv = getaddrinfo(argv[i], ports, &hints, &res0);
- if (rv != 0) {
- fprintf(stderr, "Unable to handle given address: %s\n\n",
- gai_strerror(rv));
- usage();
- }
- dest = *(res0->ai_addr);
- destlen = res0->ai_addrlen;
- freeaddrinfo(res0);
- } else {
- struct sockaddr_in *ip = (struct sockaddr_in *) &dest;
- ip->sin_family = AF_INET;
- ip->sin_port = htons(port);
- ip->sin_addr.s_addr = INADDR_BROADCAST;
- destlen = sizeof(*ip);
- }
- sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (sock == -1) {
- perror("socket");
- exit(1);
- }
- /* We want it to be non-blocking. */
- rv = fcntl(sock, F_SETFL, O_NONBLOCK);
- if (rv) {
- close(sock);
- perror("fcntl(sock, F_SETFL, O_NONBLOCK)");
- exit(1);
- }
- val = 1;
- rv = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
- if (rv) {
- close(sock);
- perror("setsockopt(sock, SO_BROADCAST)");
- exit(1);
- }
- gettimeofday(&currtime, NULL);
- endtime = currtime;
- endtime.tv_sec += waittime;
- send_next = 1;
- for (;;) {
- if ((endtime.tv_sec < currtime.tv_sec)
- || ((endtime.tv_sec == currtime.tv_sec)
- && (endtime.tv_usec < currtime.tv_usec)))
- break;
- if (send_next) {
- ping_msg[9] = starttag;
- starttag++;
- if (starttag > 254)
- starttag = 0;
- rv = sendto(sock, ping_msg, sizeof(ping_msg), 0, &dest, destlen);
- if (rv < 0) {
- close(sock);
- perror("sendto");
- exit(1);
- }
- send_next = 0;
- }
- twait.tv_usec = 0;
- twait.tv_sec = 1;
- FD_ZERO(&readfds);
- FD_SET(sock, &readfds);
- rv = select(sock+1, &readfds, NULL, NULL, &twait);
- if (rv < 0) {
- close(sock);
- perror("select");
- exit(1);
- }
- if (rv == 0) {
- send_next = 1;
- goto next;
- }
-
- fromlen = sizeof(src);
- rv = recvfrom(sock, rsp, sizeof(rsp), 0, &src, &fromlen);
- if (debug_packet && (rv > 0)) {
- int i;
- printf("Got packet:");
- for (i=0; i<rv; i++) {
- if ((i % 16) == 0)
- printf("\n ");
- printf(" %2.2x", rsp[i]);
- }
- printf("\n");
- }
- if (rv < 0) {
- perror("recvfrom");
- } else if (rv < 28) {
- fprintf(stderr, "Invalid receive length: %d, should be 28\n", rv);
- } else if ((rsp[0] != 6) || (rsp[3] != 6) || (rsp[4] != 0x00)
- || (rsp[5] != 0x00) || (rsp[6] != 0x11) || (rsp[7] != 0xbe)
- || (rsp[8] != 0x40) || (rsp[11] < 16))
- {
- fprintf(stderr, "Invalid ping response\n");
- } else {
- if (! add_host(&src))
- goto next;
- rv = getnameinfo(&src, fromlen, host, sizeof(host),
- serv, sizeof(serv), 0);
- if (rv) {
- struct sockaddr_in *ip = (struct sockaddr_in *) &src;
- addrname = inet_ntoa(ip->sin_addr);
- } else
- addrname = host;
- printf("%s", addrname);
- if ((rsp[20] & 0x80) && ((rsp[20] & 0xf) == 0x01))
- printf(" IPMI");
- printf("\n");
- }
- next:
- gettimeofday(&currtime, NULL);
- }
- return 0;
- }