X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=nwhod.c;h=9407f6fa0334af796649741e361cc4b0e30969a8;hb=3fb1d81c1b802491e95aa4d92931104bab846c40;hp=d706fbf257cbc3a78b22e2904e0c5ac9be94aee3;hpb=1342d280808b2fb2b1e8a7192986c041f9824c69;p=nwho.git diff --git a/nwhod.c b/nwhod.c index d706fbf..9407f6f 100644 --- a/nwhod.c +++ b/nwhod.c @@ -1,17 +1,14 @@ /* - * The Remote User Information Daemon 1.9 + * The Remote User Information Daemon * - * (c) 1997--2001 Martin Mares - * - * This software may be freely distributed and used according to the terms - * of the GNU General Public License. See file COPYING in any of the GNU packages. + * (c) 1997--2017 Martin Mares */ #include #include #include -#include #include +#include #include #include #include @@ -23,35 +20,22 @@ #include #include #include -#include #include -#include "net.h" +#include "nwho.h" struct hostrec { struct hostrec *next; char name[32]; time_t last_rec; /* 0=down */ - __u32 addr; + u32 addr; }; +static int do_not_daemonize; static int sock, port; static struct hostrec *first_host; static time_t now, last_local_scan; - -static void die(char *msg, ...) __attribute__((noreturn)); - -static void -die(char *msg, ...) -{ - va_list args; - - va_start(args, msg); - fprintf(stderr, "nwhod: "); - vfprintf(stderr, msg, args); - fputc('\n', stderr); - exit(1); -} +static char hostname[64]; static void net_init(char *name) @@ -62,31 +46,34 @@ net_init(char *name) if (name) { if (! (h = gethostbyname(name))) - die("%s: %m", name); + die("Failed to resolve %s", name); } else h = NULL; sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) - die("socket: %m"); + die("Cannot create socket: %m"); sa.sin_family = AF_INET; - sa.sin_port = port = NWHO_PORT; + sa.sin_port = port = htons(NWHO_PORT); sa.sin_addr.s_addr = INADDR_ANY; if (bind(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0) - die("bind: %m"); + die("Cannot bind to UDP port %d: %m", NWHO_PORT); if (h) { memcpy(&sa.sin_addr.s_addr, h->h_addr, sizeof(sa.sin_addr.s_addr)); if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0) - die("connect: %m"); + die("Cannot connect socket: %m"); } + + if (gethostname(hostname, sizeof(hostname)) < 0) + die("Unable to get my own host name: %m"); } static void -scan_utmp(struct rywho_pkt *p, time_t now) +scan_utmp(struct nwho_pkt *p, time_t now) { struct utmp *u; int cnt = 0; @@ -105,16 +92,12 @@ scan_utmp(struct rywho_pkt *p, time_t now) name[9] = 0; strcpy(h->name, name); h->login_time = htonl(now - u->ut_time); - sprintf(h->con, "%.7s", u->ut_line); - sprintf(device, "/dev/%s", u->ut_line); + snprintf(h->con, sizeof(h->con), "%s", u->ut_line); + snprintf(device, sizeof(device), "/dev/%s", u->ut_line); if (stat(device, &st) < 0) continue; h->mesg_y = !!(S_IWGRP & st.st_mode); last = st.st_atime; - if (st.st_mtime > last) - last = st.st_mtime; - if (st.st_ctime > last) - last = st.st_ctime; if (now < last) last = now; h->idle_time = htonl(now - last); @@ -124,7 +107,7 @@ scan_utmp(struct rywho_pkt *p, time_t now) } static void -scan_load(struct rywho_pkt *p) +scan_load(struct nwho_pkt *p) { int n, i, j[6]; char buf[256]; @@ -153,9 +136,9 @@ scan_load(struct rywho_pkt *p) } static void -make_pkt(struct rywho_pkt *pkt) +make_pkt(struct nwho_pkt *pkt) { - bzero(pkt, sizeof(pkt)); + bzero(pkt, sizeof(*pkt)); pkt->magic = htonl(NWHO_MAGIC); pkt->local_time = htonl(now); scan_utmp(pkt, now); @@ -178,8 +161,9 @@ cleanup(void) } static void -save_pkt(char *name, struct rywho_pkt *pkt, int len) +save_pkt(char *name, struct nwho_pkt *pkt) { + int len = nwho_pkt_size(pkt); int fd = open(name, O_WRONLY | O_CREAT, 0666); if (fd < 0) { @@ -194,7 +178,7 @@ save_pkt(char *name, struct rywho_pkt *pkt, int len) } static inline int /* Validation checks not implemented yet */ -is_valid(__u32 ipa) +is_valid(u32 ipa) { return 1; } @@ -202,16 +186,16 @@ is_valid(__u32 ipa) static void receive(void) { - int r, al; - struct rywho_pkt pkt; + int r; + struct nwho_pkt pkt; struct sockaddr_in sa; - int n = sizeof(struct rywho_pkt) - MAX_USERS * sizeof(struct userinfo); + socklen_t al = sizeof(sa); + int n = sizeof(struct nwho_pkt) - MAX_USERS * sizeof(struct userinfo); struct hostrec *e; struct hostent *h; char *c; alarm(DEFAULT_PRUNE_TIME); - al = sizeof(sa); r = recvfrom(sock, &pkt, sizeof(pkt), 0, (struct sockaddr *) &sa, &al); alarm(0); now = time(NULL); @@ -226,25 +210,23 @@ receive(void) if (!is_valid(sa.sin_addr.s_addr) || sa.sin_port != port) { - syslog(LOG_WARNING, "Received packet from invalid source %s.%d", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); + syslog(LOG_WARNING, "Received packet from invalid source %s:%d", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); return; } - if (r < n || r != n + ntohl(pkt.num_users)*sizeof(struct userinfo)) + if (r < n || + pkt.magic != htonl(NWHO_MAGIC) || + ntohl(pkt.num_users) > MAX_USERS || + r < nwho_pkt_size(&pkt)) { syslog(LOG_WARNING, "Malformed packet from %s", inet_ntoa(sa.sin_addr)); return; } - if (pkt.magic != htonl(NWHO_MAGIC)) - { - syslog(LOG_WARNING, "Received ancient nwho packet from %s", inet_ntoa(sa.sin_addr)); - return; - } - for(e=first_host; e; e=e->next) if (e->addr == sa.sin_addr.s_addr) break; + if (!e) { e = malloc(sizeof(struct hostrec)); @@ -258,8 +240,8 @@ receive(void) h = gethostbyaddr((char *) &sa.sin_addr, sizeof(sa.sin_addr), AF_INET); if (h) { - sprintf(e->name, "%.30s", h->h_name); - for(c=e->name; *c; c++) + snprintf(e->name, sizeof(e->name), "%s", h->h_name); + for (c=e->name; *c; c++) if (*c == '.') { *c = 0; @@ -277,19 +259,16 @@ receive(void) } e->last_rec = now; - save_pkt(e->name, &pkt, r); + save_pkt(e->name, &pkt); } static void local_scan(void) { - struct rywho_pkt pkt; - static char hostname[64]; + struct nwho_pkt pkt; make_pkt(&pkt); - if (!hostname[0] && gethostname(hostname, sizeof(hostname)) < 0) - die("gethostname: %m"); - save_pkt(hostname, &pkt, sizeof(pkt) - (MAX_USERS - ntohl(pkt.num_users))*sizeof(struct userinfo)); + save_pkt(hostname, &pkt); } static void @@ -314,6 +293,15 @@ do_tick(void) static void daemonize(void) { + if (do_not_daemonize) + return; + + pid_t pid = fork(); + if (pid < 0) + die("Fork failed: %m"); + if (pid) + exit(0); + close(0); close(1); close(2); @@ -352,7 +340,7 @@ server(void) static void client(char *serv) { - struct rywho_pkt pkt; + struct nwho_pkt pkt; net_init(serv); utmpname(UTMP_FILE); @@ -361,33 +349,49 @@ client(char *serv) { now = time(NULL); make_pkt(&pkt); - if (send(sock, &pkt, sizeof(pkt) - (MAX_USERS - ntohl(pkt.num_users))*sizeof(struct userinfo), 0) < 0) + if (send(sock, &pkt, nwho_pkt_size(&pkt), 0) < 0) syslog(LOG_ERR, "sendmsg: %m"); sleep(DEFAULT_SEND_TIME); } } +static void +usage(void) +{ + fprintf(stderr, "Usage: nwhod [-d] []\n"); + exit(1); +} + int main(int argc, char **argv) { - int pid; - - if (argc != 1 && argc != 2) + if (argc == 2 && !strcmp(argv[1], "--version")) { - fprintf(stderr, "Usage: nwhod []\n"); - return 1; + printf("nwho " STRINGIFY(VERSION) "\n"); + return 0; } - pid = fork(); - if (pid < 0) + + int opt; + while ((opt = getopt(argc, argv, "d")) >= 0) + switch (opt) + { + case 'd': + do_not_daemonize = 1; + break; + default: + usage(); + } + + if (optind == argc-1) { - perror("fork"); - return 1; + if (argv[optind][0]) + client(argv[optind]); + else + server(); } - if (pid) - return 0; - if (argc == 2) - client(argv[1]); - else if (argc == 1) + else if (optind == argc) server(); - return 1; + else + usage(); + return 0; }