xref: /csrg-svn/libexec/talkd/process.c (revision 26854)
122774Smckusick /*
222774Smckusick  * Copyright (c) 1983 Regents of the University of California.
322774Smckusick  * All rights reserved.  The Berkeley software License Agreement
422774Smckusick  * specifies the terms and conditions for redistribution.
522774Smckusick  */
622774Smckusick 
716365Skarels #ifndef lint
8*26854Smckusick static char sccsid[] = "@(#)process.c	5.4 (Berkeley) 03/13/86";
922774Smckusick #endif not lint
1016355Skarels 
1116365Skarels /*
1216365Skarels  * process.c handles the requests, which can be of three types:
1316365Skarels  *	ANNOUNCE - announce to a user that a talk is wanted
1416365Skarels  *	LEAVE_INVITE - insert the request into the table
1516365Skarels  *	LOOK_UP - look up to see if a request is waiting in
1616365Skarels  *		  in the table for the local user
1716365Skarels  *	DELETE - delete invitation
1816365Skarels  */
1926839Smckusick #include <sys/types.h>
2017560Sbloom #include <sys/stat.h>
2123462Sbloom #include <stdio.h>
2226839Smckusick #include <syslog.h>
2326839Smckusick #include <netdb.h>
2426839Smckusick #include <netinet/in.h>
2516355Skarels 
2626839Smckusick #include <protocols/talkd.h>
2726839Smckusick 
2826839Smckusick char	*strcpy();
2916355Skarels CTL_MSG *find_request();
3016355Skarels CTL_MSG *find_match();
3116355Skarels 
3226839Smckusick process_request(mp, rp)
3326839Smckusick 	register CTL_MSG *mp;
3426839Smckusick 	register CTL_RESPONSE *rp;
3516355Skarels {
3626839Smckusick 	register CTL_MSG *ptr;
3726839Smckusick 	extern int debug;
3816355Skarels 
3926839Smckusick 	rp->vers = TALK_VERSION;
4026839Smckusick 	rp->type = mp->type;
4126839Smckusick 	rp->id_num = htonl(0);
4226839Smckusick 	if (mp->vers != TALK_VERSION) {
4326839Smckusick 		syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
4426839Smckusick 		rp->answer = BADVERSION;
4526839Smckusick 		return;
4626839Smckusick 	}
4726839Smckusick 	mp->id_num = ntohl(mp->id_num);
4826839Smckusick 	mp->addr.sa_family = ntohs(mp->addr.sa_family);
4926839Smckusick 	if (mp->addr.sa_family != AF_INET) {
5026839Smckusick 		syslog(LOG_WARNING, "Bad address, family %d",
5126839Smckusick 		    mp->addr.sa_family);
5226839Smckusick 		rp->answer = BADADDR;
5326839Smckusick 		return;
5426839Smckusick 	}
5526839Smckusick 	mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
5626839Smckusick 	if (mp->ctl_addr.sa_family != AF_INET) {
5726839Smckusick 		syslog(LOG_WARNING, "Bad control address, family %d",
5826839Smckusick 		    mp->ctl_addr.sa_family);
5926839Smckusick 		rp->answer = BADCTLADDR;
6026839Smckusick 		return;
6126839Smckusick 	}
6226839Smckusick 	mp->pid = ntohl(mp->pid);
6326839Smckusick 	if (debug)
6426839Smckusick 		print_request("process_request", mp);
6526839Smckusick 	switch (mp->type) {
6616355Skarels 
6726839Smckusick 	case ANNOUNCE:
6826839Smckusick 		do_announce(mp, rp);
6916365Skarels 		break;
7016355Skarels 
7126839Smckusick 	case LEAVE_INVITE:
7226839Smckusick 		ptr = find_request(mp);
7326839Smckusick 		if (ptr != (CTL_MSG *)0) {
7426839Smckusick 			rp->id_num = htonl(ptr->id_num);
7526839Smckusick 			rp->answer = SUCCESS;
7616365Skarels 		} else
7726839Smckusick 			insert_table(mp, rp);
7816365Skarels 		break;
7916355Skarels 
8026839Smckusick 	case LOOK_UP:
8126839Smckusick 		ptr = find_match(mp);
8226839Smckusick 		if (ptr != (CTL_MSG *)0) {
8326839Smckusick 			rp->id_num = htonl(ptr->id_num);
8426839Smckusick 			rp->addr = ptr->addr;
8526839Smckusick 			rp->addr.sa_family = htons(ptr->addr.sa_family);
8626839Smckusick 			rp->answer = SUCCESS;
8716365Skarels 		} else
8826839Smckusick 			rp->answer = NOT_HERE;
8916365Skarels 		break;
9016355Skarels 
9126839Smckusick 	case DELETE:
9226839Smckusick 		rp->answer = delete_invite(mp->id_num);
9316365Skarels 		break;
9416355Skarels 
9526839Smckusick 	default:
9626839Smckusick 		rp->answer = UNKNOWN_REQUEST;
9716365Skarels 		break;
9816365Skarels 	}
9926839Smckusick 	if (debug)
10026839Smckusick 		print_response("process_request", rp);
10116355Skarels }
10216355Skarels 
10326839Smckusick do_announce(mp, rp)
10426839Smckusick 	register CTL_MSG *mp;
10526839Smckusick 	CTL_RESPONSE *rp;
10616355Skarels {
10716365Skarels 	struct hostent *hp;
10816365Skarels 	CTL_MSG *ptr;
10916365Skarels 	int result;
11016355Skarels 
11116355Skarels 	/* see if the user is logged */
11226839Smckusick 	result = find_user(mp->r_name, mp->r_tty);
11316365Skarels 	if (result != SUCCESS) {
11426839Smckusick 		rp->answer = result;
11516365Skarels 		return;
11616365Skarels 	}
11726839Smckusick #define	satosin(sa)	((struct sockaddr_in *)(sa))
11826839Smckusick 	hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr,
11926839Smckusick 		sizeof (struct in_addr), AF_INET);
12016365Skarels 	if (hp == (struct hostent *)0) {
12126839Smckusick 		rp->answer = MACHINE_UNKNOWN;
12216365Skarels 		return;
12316365Skarels 	}
12426839Smckusick 	ptr = find_request(mp);
12516365Skarels 	if (ptr == (CTL_MSG *) 0) {
12626839Smckusick 		insert_table(mp, rp);
12726839Smckusick 		rp->answer = announce(mp, hp->h_name);
12816365Skarels 		return;
12916365Skarels 	}
13026839Smckusick 	if (mp->id_num > ptr->id_num) {
13116365Skarels 		/*
13226839Smckusick 		 * This is an explicit re-announce, so update the id_num
13326839Smckusick 		 * field to avoid duplicates and re-announce the talk.
13416365Skarels 		 */
13526839Smckusick 		ptr->id_num = new_id();
13626839Smckusick 		rp->id_num = htonl(ptr->id_num);
13726839Smckusick 		rp->answer = announce(mp, hp->h_name);
13826839Smckusick 	} else {
13926839Smckusick 		/* a duplicated request, so ignore it */
14026839Smckusick 		rp->id_num = htonl(ptr->id_num);
14126839Smckusick 		rp->answer = SUCCESS;
14216365Skarels 	}
14316355Skarels }
14416355Skarels 
14516355Skarels #include <utmp.h>
14616355Skarels 
14716355Skarels /*
14816355Skarels  * Search utmp for the local user
14916355Skarels  */
15016355Skarels find_user(name, tty)
15126839Smckusick 	char *name, *tty;
15216355Skarels {
15316365Skarels 	struct utmp ubuf;
15423462Sbloom 	int status;
15523462Sbloom 	FILE *fd;
15617560Sbloom 	struct stat statb;
15717560Sbloom 	char ftty[20];
15816355Skarels 
15923462Sbloom 	if ((fd = fopen("/etc/utmp", "r")) == NULL) {
16016365Skarels 		perror("Can't open /etc/utmp");
16116365Skarels 		return (FAILED);
16216355Skarels 	}
16316365Skarels #define SCMPN(a, b)	strncmp(a, b, sizeof (a))
16416365Skarels 	status = NOT_HERE;
16517560Sbloom 	(void) strcpy(ftty, "/dev/");
16623462Sbloom 	while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1)
16716365Skarels 		if (SCMPN(ubuf.ut_name, name) == 0) {
16816365Skarels 			if (*tty == '\0') {
16917560Sbloom 				status = PERMISSION_DENIED;
17016365Skarels 				/* no particular tty was requested */
17117560Sbloom 				(void) strcpy(ftty+5, ubuf.ut_line);
17217560Sbloom 				if (stat(ftty,&statb) == 0) {
173*26854Smckusick 					if (!(statb.st_mode & 020))
17417560Sbloom 						continue;
17517560Sbloom 					(void) strcpy(tty, ubuf.ut_line);
17617560Sbloom 					status = SUCCESS;
17717560Sbloom 					break;
17817560Sbloom 				}
17916365Skarels 			}
18016365Skarels 			if (strcmp(ubuf.ut_line, tty) == 0) {
18116365Skarels 				status = SUCCESS;
18216365Skarels 				break;
18316365Skarels 			}
18416365Skarels 		}
18523462Sbloom 	fclose(fd);
18616365Skarels 	return (status);
18716355Skarels }
188