process.c revision 3793
111819Sjulian/*
211819Sjulian * Copyright (c) 1983, 1993
311819Sjulian *	The Regents of the University of California.  All rights reserved.
411819Sjulian *
511819Sjulian * Redistribution and use in source and binary forms, with or without
611819Sjulian * modification, are permitted provided that the following conditions
711819Sjulian * are met:
811819Sjulian * 1. Redistributions of source code must retain the above copyright
911819Sjulian *    notice, this list of conditions and the following disclaimer.
1011819Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1111819Sjulian *    notice, this list of conditions and the following disclaimer in the
1211819Sjulian *    documentation and/or other materials provided with the distribution.
1311819Sjulian * 3. All advertising materials mentioning features or use of this software
1411819Sjulian *    must display the following acknowledgement:
1511819Sjulian *	This product includes software developed by the University of
1611819Sjulian *	California, Berkeley and its contributors.
1711819Sjulian * 4. Neither the name of the University nor the names of its contributors
1811819Sjulian *    may be used to endorse or promote products derived from this software
1911819Sjulian *    without specific prior written permission.
2011819Sjulian *
2111819Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2211819Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2311819Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2411819Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2511819Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2611819Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2711819Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2811819Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2911819Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3011819Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3111819Sjulian * SUCH DAMAGE.
3211819Sjulian */
3311819Sjulian
3412057Sjulian#ifndef lint
3511819Sjulianstatic char sccsid[] = "@(#)process.c	8.2 (Berkeley) 11/16/93";
3611819Sjulian#endif /* not lint */
37116189Sobrien
38116189Sobrien/*
39116189Sobrien * process.c handles the requests, which can be of three types:
4031742Seivind *	ANNOUNCE - announce to a user that a talk is wanted
4131742Seivind *	LEAVE_INVITE - insert the request into the table
4211819Sjulian *	LOOK_UP - look up to see if a request is waiting in
4319947Sjhay *		  in the table for the local user
4495759Stanimura *	DELETE - delete invitation
4511819Sjulian */
4611819Sjulian#include <sys/param.h>
4795759Stanimura#include <sys/stat.h>
4811819Sjulian#include <sys/socket.h>
4911819Sjulian#include <netinet/in.h>
5095759Stanimura#include <protocols/talkd.h>
5119947Sjhay#include <netdb.h>
5295759Stanimura#include <syslog.h>
5311819Sjulian#include <stdio.h>
5411819Sjulian#include <string.h>
5511819Sjulian#include <ctype.h>
5611819Sjulian#include <paths.h>
5711947Sjulian
5811947SjulianCTL_MSG *find_request();
5911819SjulianCTL_MSG *find_match();
6095759Stanimura
6195759Stanimuraprocess_request(mp, rp)
6211819Sjulian	register CTL_MSG *mp;
6311819Sjulian	register CTL_RESPONSE *rp;
6411819Sjulian{
6511819Sjulian	register CTL_MSG *ptr;
6611819Sjulian	extern int debug;
6711819Sjulian	char *s;
6811819Sjulian
6933181Seivind	rp->vers = TALK_VERSION;
7019947Sjhay	rp->type = mp->type;
7119947Sjhay	rp->id_num = htonl(0);
7233181Seivind	if (mp->vers != TALK_VERSION) {
7319947Sjhay		syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
7419947Sjhay		rp->answer = BADVERSION;
7519947Sjhay		return;
7624659Sjhay	}
7783366Sjulian	mp->id_num = ntohl(mp->id_num);
7883366Sjulian	mp->addr.sa_family = ntohs(mp->addr.sa_family);
7928270Swollman	if (mp->addr.sa_family != AF_INET) {
8083366Sjulian		syslog(LOG_WARNING, "Bad address, family %d",
8124659Sjhay		    mp->addr.sa_family);
8224659Sjhay		rp->answer = BADADDR;
8324659Sjhay		return;
8428270Swollman	}
8583366Sjulian	mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
8624659Sjhay	if (mp->ctl_addr.sa_family != AF_INET) {
8783366Sjulian		syslog(LOG_WARNING, "Bad control address, family %d",
8825652Sjhay		    mp->ctl_addr.sa_family);
8924659Sjhay		rp->answer = BADCTLADDR;
9025652Sjhay		return;
91137386Sphk	}
92137386Sphk	for (s = mp->l_name; *s; s++)
93137386Sphk		if (!isprint(*s)) {
94137386Sphk			syslog(LOG_NOTICE, "Illegal user name. Aborting");
95137386Sphk			rp->answer = FAILED;
96137386Sphk			return;
97137386Sphk		}
98137386Sphk	mp->pid = ntohl(mp->pid);
99137386Sphk	if (debug)
100137386Sphk		print_request("process_request", mp);
101137386Sphk	switch (mp->type) {
10224659Sjhay
10324659Sjhay	case ANNOUNCE:
10425652Sjhay		do_announce(mp, rp);
105137386Sphk		break;
106137386Sphk
107137386Sphk	case LEAVE_INVITE:
108137386Sphk		ptr = find_request(mp);
109137386Sphk		if (ptr != (CTL_MSG *)0) {
110137386Sphk			rp->id_num = htonl(ptr->id_num);
111137386Sphk			rp->answer = SUCCESS;
112137386Sphk		} else
113137386Sphk			insert_table(mp, rp);
114137386Sphk		break;
115137386Sphk
11624659Sjhay	case LOOK_UP:
11724659Sjhay		ptr = find_match(mp);
11811819Sjulian		if (ptr != (CTL_MSG *)0) {
11911819Sjulian			rp->id_num = htonl(ptr->id_num);
12011819Sjulian			rp->addr = ptr->addr;
12111819Sjulian			rp->addr.sa_family = htons(ptr->addr.sa_family);
12211819Sjulian			rp->answer = SUCCESS;
12311819Sjulian		} else
12411819Sjulian			rp->answer = NOT_HERE;
12511819Sjulian		break;
12611819Sjulian
12711819Sjulian	case DELETE:
12815245Sjhay		rp->answer = delete_invite(mp->id_num);
12911819Sjulian		break;
13025652Sjhay
13111819Sjulian	default:
13211819Sjulian		rp->answer = UNKNOWN_REQUEST;
13311819Sjulian		break;
13411819Sjulian	}
13511819Sjulian	if (debug)
13615245Sjhay		print_response("process_request", rp);
13715245Sjhay}
13811819Sjulian
13915245Sjhaydo_announce(mp, rp)
14015245Sjhay	register CTL_MSG *mp;
14125652Sjhay	CTL_RESPONSE *rp;
14211819Sjulian{
14311819Sjulian	struct hostent *hp;
14471999Sphk	CTL_MSG *ptr;
14571999Sphk	int result;
14611819Sjulian
14711819Sjulian	/* see if the user is logged */
14811819Sjulian	result = find_user(mp->r_name, mp->r_tty);
14911819Sjulian	if (result != SUCCESS) {
15011819Sjulian		rp->answer = result;
15111819Sjulian		return;
15211819Sjulian	}
15311819Sjulian#define	satosin(sa)	((struct sockaddr_in *)(sa))
15425652Sjhay	hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr,
15525652Sjhay		sizeof (struct in_addr), AF_INET);
15625652Sjhay	if (hp == (struct hostent *)0) {
15725652Sjhay		rp->answer = MACHINE_UNKNOWN;
15811819Sjulian		return;
15911819Sjulian	}
16025652Sjhay	ptr = find_request(mp);
16111819Sjulian	if (ptr == (CTL_MSG *) 0) {
16211819Sjulian		insert_table(mp, rp);
16311819Sjulian		rp->answer = announce(mp, hp->h_name);
16411819Sjulian		return;
16511819Sjulian	}
16611819Sjulian	if (mp->id_num > ptr->id_num) {
16711819Sjulian		/*
16811819Sjulian		 * This is an explicit re-announce, so update the id_num
16911819Sjulian		 * field to avoid duplicates and re-announce the talk.
17011819Sjulian		 */
17111819Sjulian		ptr->id_num = new_id();
17211819Sjulian		rp->id_num = htonl(ptr->id_num);
17311819Sjulian		rp->answer = announce(mp, hp->h_name);
17411819Sjulian	} else {
17511819Sjulian		/* a duplicated request, so ignore it */
17611819Sjulian		rp->id_num = htonl(ptr->id_num);
17725652Sjhay		rp->answer = SUCCESS;
17811819Sjulian	}
17911819Sjulian}
18011819Sjulian
18111819Sjulian#include <utmp.h>
18211819Sjulian
18311819Sjulian/*
18411819Sjulian * Search utmp for the local user
18511819Sjulian */
18611819Sjulianfind_user(name, tty)
18711819Sjulian	char *name, *tty;
18811819Sjulian{
18911819Sjulian	struct utmp ubuf;
19025652Sjhay	int status;
19111819Sjulian	FILE *fd;
19211819Sjulian	struct stat statb;
19325652Sjhay	char line[sizeof(ubuf.ut_line) + 1];
19425652Sjhay	char ftty[sizeof(_PATH_DEV) - 1 + sizeof(line)];
19511819Sjulian
19611819Sjulian	if ((fd = fopen(_PATH_UTMP, "r")) == NULL) {
19711819Sjulian		fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP);
19825652Sjhay		return (FAILED);
19911819Sjulian	}
20011819Sjulian#define SCMPN(a, b)	strncmp(a, b, sizeof (a))
20111819Sjulian	status = NOT_HERE;
20211819Sjulian	(void) strcpy(ftty, _PATH_DEV);
20311819Sjulian	while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1)
20411819Sjulian		if (SCMPN(ubuf.ut_name, name) == 0) {
20525652Sjhay			strncpy(line, ubuf.ut_line, sizeof(ubuf.ut_line));
20611819Sjulian			line[sizeof(ubuf.ut_line)] = '\0';
20711819Sjulian			if (*tty == '\0') {
20811819Sjulian				status = PERMISSION_DENIED;
20911819Sjulian				/* no particular tty was requested */
21011819Sjulian				(void) strcpy(ftty + sizeof(_PATH_DEV) - 1,
21111819Sjulian				    line);
21211819Sjulian				if (stat(ftty, &statb) == 0) {
21311819Sjulian					if (!(statb.st_mode & 020))
21454799Sgreen						continue;
21511819Sjulian					(void) strcpy(tty, line);
21611819Sjulian					status = SUCCESS;
21711819Sjulian					break;
21811819Sjulian				}
21911819Sjulian			}
22025652Sjhay			if (strcmp(line, tty) == 0) {
22111819Sjulian				status = SUCCESS;
22211819Sjulian				break;
22311819Sjulian			}
22411819Sjulian		}
22511819Sjulian	fclose(fd);
22611819Sjulian	return (status);
22711819Sjulian}
22811819Sjulian