/*
 * IAmHere.c	I am here.
 * Copyright(C)1997 by Hiroaki Sengoku <sengoku@gcd.org>
 * Version 1.0  Jan 26, 1997
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNU Emacs; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Usage: iamhere <port> <password>
 *
 * See also: WhereAreYou.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <syslog.h>

#define BUFMAX		10
#define NPACKETS	30

main(argc,argv)
int argc;
char *argv[];
{
    struct sockaddr_in from, sin;
    char pass[BUFMAX+1], buf[BUFMAX+1];
    char xor[BUFMAX+1], prev[BUFMAX+1];
    unsigned char *p, *q;
    int sd, from_len, len, i, success;
    struct hostent *ent;
    if (argc != 3) {
	fprintf(stderr,"Usage: iamhere <port> <password>\n");
	exit(1);
    }
    memset((char *)&sin,0,sizeof(sin));		/* clear sin struct */
    sin.sin_family = AF_INET;
    sin.sin_port = htons((u_short)atoi(argv[1]));	/* port */
    len = strlen(argv[2]);				/* password */
    if (len >= BUFMAX) len = BUFMAX;
    memcpy(pass,argv[2],len);
    pass[len] = '\0';
    q = argv[argc-1] + strlen(argv[argc-1]);
    for (p=argv[1]; p < q; p++) *p = '\0';
    if ((sd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) {
	fprintf(stderr,"Can't get socket.\n");
	exit(1);
    }
    if (bind(sd, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
	fprintf(stderr,"Can't bind.\n");
	exit(1);
    }
    openlog("IamHere",0,LOG_DAEMON);
    prev[0] = '\0';
    for (;;) {
	from_len = sizeof(from);
	len = recvfrom(sd,buf,BUFMAX,0,
		       (struct sockaddr*)&from,&from_len);
	if (len <= 0) continue;
	for (i=0; i < len; i++) {
	    xor[i] = (buf[i]^pass[i]^' ');
	}
	buf[i] = xor[i] = '\0';
	if (!strcmp(xor,prev)) continue;
	ent = gethostbyaddr((char*)&from.sin_addr.s_addr,
			    sizeof(from.sin_addr.s_addr),AF_INET);
	p = (unsigned char*)&from.sin_addr.s_addr;
	syslog(LOG_NOTICE,"from %s [%d.%d.%d.%d] %s",
	       (ent ? ent->h_name : "?"),
	       p[0],p[1],p[2],p[3],buf);
	buf[0] = buf[0]%26 + 'A';	/* A-Z */
	buf[1] = buf[1]%26 + 'a';	/* a-z */
/*	fprintf("pass: %s, salt: %s\n",xor,buf);	*/
	p = crypt(xor,buf);
	len = strlen(p);
	success = 0;
	for (i=0; i < NPACKETS; i++) {
	    if (sendto(sd,p,len,0,
		       (struct sockaddr*)&from,sizeof(from)) == len) {
		success++;
	    } else {
		fprintf(stderr,"Sendto failed.\n");
	    }
	}
	if (success) {
	    strcpy(prev,xor);
	}
    }
}

