/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1983, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
/* Time interval limit; ruptime will think that we are down > than this */
#define MAX_INTERVAL (11 * 60)
static char myname[MAXHOSTNAMELEN + 1];
/*
* We communicate with each neighbor in a list constructed at the time we're
* started up. Neighbors are currently directly connected via a hardware
* interface.
*/
struct neighbor {
struct neighbor *n_next;
char *n_name; /* interface name */
struct sockaddr *n_addr; /* who to send to */
int n_addrlen; /* size of address */
int n_flags; /* should forward?, interface flags */
};
static void
handleread(int s)
{
struct sockaddr_in from;
struct stat st;
char path[64];
struct whod wd;
int cc, whod;
socklen_t len = sizeof(from);
cc = recvfrom(s, (char *)&wd, sizeof(struct whod), 0,
(struct sockaddr *)&from, &len);
if (cc <= 0) {
if (cc < 0 && errno != EINTR)
syslog(LOG_WARNING, "recv: %m");
return;
}
if (from.sin_port != sp->s_port) {
syslog(LOG_WARNING, "%d: bad from port",
ntohs(from.sin_port));
return;
}
if (cc < (int)WHDRSIZE) {
syslog(LOG_WARNING, "Short packet from %s",
inet_ntoa(from.sin_addr));
return;
}
if (wd.wd_vers != WHODVERSION)
return;
if (wd.wd_type != WHODTYPE_STATUS)
return;
/*
* Ensure null termination of the name within the packet.
* Otherwise we might overflow or read past the end.
*/
wd.wd_hostname[sizeof(wd.wd_hostname)-1] = 0;
if (!verify(wd.wd_hostname)) {
syslog(LOG_WARNING, "malformed host name from %s",
inet_ntoa(from.sin_addr));
return;
}
(void)snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname);
/*
* Rather than truncating and growing the file each time,
* use ftruncate if size is less than previous size.
*/
whod = open(path, O_WRONLY | O_CREAT, 0644);
if (whod < 0) {
syslog(LOG_WARNING, "%s: %m", path);
return;
}
#if ENDIAN != BIG_ENDIAN
{
int i, n = (cc - WHDRSIZE) / sizeof(struct whoent);
struct whoent *we;
/* undo header byte swapping before writing to file */
wd.wd_sendtime = ntohl(wd.wd_sendtime);
for (i = 0; i < 3; i++)
wd.wd_loadav[i] = ntohl(wd.wd_loadav[i]);
wd.wd_boottime = ntohl(wd.wd_boottime);
we = wd.wd_we;
for (i = 0; i < n; i++) {
we->we_idle = ntohl(we->we_idle);
we->we_utmp.out_time =
ntohl(we->we_utmp.out_time);
we++;
}
}
#endif
wd.wd_recvtime = time(NULL);
(void)write(whod, (char *)&wd, cc);
if (fstat(whod, &st) < 0 || st.st_size > cc)
(void)ftruncate(whod, cc);
(void)close(whod);
}
/*
* Check out host name for unprintables
* and other funnies before allowing a file
* to be created. Sorry, but blanks aren't allowed.
*/
static int
verify(const char *name)
{
int size = 0;