#include #include #include #include #include #include #include #include #include #include #include #include "btime_int.h" /* * btime -- * * Return the boot time of a remote host if that host is running the * btimed deamon. * * Returns: * btime, or 0 on failure. */ unsigned int btime(const char *host) { int sd; char msg[BTIME_MSGLEN]; struct sockaddr_in serv_addr; struct sockaddr_in my_addr; int serv_addr_len; struct hostent *hostent; in_addr_t inaddr; unsigned int btime; ssize_t nbytes; int retry; if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "Could not create socket: %s\n", strerror(errno)); return 0; } memset(&serv_addr, 0, sizeof serv_addr); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(BTIME_PORT); if ((inaddr = inet_addr(host)) != INADDR_NONE) { memcpy(&serv_addr.sin_addr, &inaddr, sizeof inaddr); } else { if ((hostent = gethostbyname(host)) == NULL) { return 0; } memcpy(&serv_addr.sin_addr, hostent->h_addr, hostent->h_length); } memset(&my_addr, 0, sizeof my_addr); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl(INADDR_ANY); my_addr.sin_port = htons(0); if (bind(sd, (struct sockaddr *)&my_addr, sizeof my_addr) < 0) { fprintf(stderr, "Could not bind to local address: %s\n", strerror(errno)); return 0; } memset(msg, 0, BTIME_MSGLEN); for (retry = 0; retry < MAX_RETRY; retry++) { serv_addr_len = sizeof serv_addr; if ((nbytes = sendto(sd, &msg, BTIME_MSGLEN, MSG_DONTWAIT, (struct sockaddr *)&serv_addr, serv_addr_len)) < 0) { if (errno == EAGAIN) { usleep(retry * 100); } else { /* Non EAGAIN error... */ break; } } else { break; } } memset(msg, 0, BTIME_MSGLEN); for (retry = 0; retry < MAX_RETRY; retry++) { serv_addr_len = sizeof serv_addr; if ((nbytes = recvfrom(sd, &msg, BTIME_MSGLEN, MSG_DONTWAIT, (struct sockaddr *)&serv_addr, &serv_addr_len)) < 0) { if (errno == EAGAIN) { usleep(retry * 100); } else { /* Non EAGAIN error... */ break; } } else { break; } } if (nbytes == 0) { btime = 0; } else { btime = strtoul(msg, (char **)NULL, 10); } close(sd); return btime; }