xref: /original-bsd/libexec/talkd/process.c (revision 2e271f8d)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)process.c	5.6 (Berkeley) 06/18/88";
20 #endif /* not lint */
21 
22 /*
23  * process.c handles the requests, which can be of three types:
24  *	ANNOUNCE - announce to a user that a talk is wanted
25  *	LEAVE_INVITE - insert the request into the table
26  *	LOOK_UP - look up to see if a request is waiting in
27  *		  in the table for the local user
28  *	DELETE - delete invitation
29  */
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stdio.h>
33 #include <syslog.h>
34 #include <netdb.h>
35 #include <netinet/in.h>
36 
37 #include <protocols/talkd.h>
38 
39 char	*strcpy();
40 CTL_MSG *find_request();
41 CTL_MSG *find_match();
42 
43 process_request(mp, rp)
44 	register CTL_MSG *mp;
45 	register CTL_RESPONSE *rp;
46 {
47 	register CTL_MSG *ptr;
48 	extern int debug;
49 
50 	rp->vers = TALK_VERSION;
51 	rp->type = mp->type;
52 	rp->id_num = htonl(0);
53 	if (mp->vers != TALK_VERSION) {
54 		syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
55 		rp->answer = BADVERSION;
56 		return;
57 	}
58 	mp->id_num = ntohl(mp->id_num);
59 	mp->addr.sa_family = ntohs(mp->addr.sa_family);
60 	if (mp->addr.sa_family != AF_INET) {
61 		syslog(LOG_WARNING, "Bad address, family %d",
62 		    mp->addr.sa_family);
63 		rp->answer = BADADDR;
64 		return;
65 	}
66 	mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
67 	if (mp->ctl_addr.sa_family != AF_INET) {
68 		syslog(LOG_WARNING, "Bad control address, family %d",
69 		    mp->ctl_addr.sa_family);
70 		rp->answer = BADCTLADDR;
71 		return;
72 	}
73 	mp->pid = ntohl(mp->pid);
74 	if (debug)
75 		print_request("process_request", mp);
76 	switch (mp->type) {
77 
78 	case ANNOUNCE:
79 		do_announce(mp, rp);
80 		break;
81 
82 	case LEAVE_INVITE:
83 		ptr = find_request(mp);
84 		if (ptr != (CTL_MSG *)0) {
85 			rp->id_num = htonl(ptr->id_num);
86 			rp->answer = SUCCESS;
87 		} else
88 			insert_table(mp, rp);
89 		break;
90 
91 	case LOOK_UP:
92 		ptr = find_match(mp);
93 		if (ptr != (CTL_MSG *)0) {
94 			rp->id_num = htonl(ptr->id_num);
95 			rp->addr = ptr->addr;
96 			rp->addr.sa_family = htons(ptr->addr.sa_family);
97 			rp->answer = SUCCESS;
98 		} else
99 			rp->answer = NOT_HERE;
100 		break;
101 
102 	case DELETE:
103 		rp->answer = delete_invite(mp->id_num);
104 		break;
105 
106 	default:
107 		rp->answer = UNKNOWN_REQUEST;
108 		break;
109 	}
110 	if (debug)
111 		print_response("process_request", rp);
112 }
113 
114 do_announce(mp, rp)
115 	register CTL_MSG *mp;
116 	CTL_RESPONSE *rp;
117 {
118 	struct hostent *hp;
119 	CTL_MSG *ptr;
120 	int result;
121 
122 	/* see if the user is logged */
123 	result = find_user(mp->r_name, mp->r_tty);
124 	if (result != SUCCESS) {
125 		rp->answer = result;
126 		return;
127 	}
128 #define	satosin(sa)	((struct sockaddr_in *)(sa))
129 	hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr,
130 		sizeof (struct in_addr), AF_INET);
131 	if (hp == (struct hostent *)0) {
132 		rp->answer = MACHINE_UNKNOWN;
133 		return;
134 	}
135 	ptr = find_request(mp);
136 	if (ptr == (CTL_MSG *) 0) {
137 		insert_table(mp, rp);
138 		rp->answer = announce(mp, hp->h_name);
139 		return;
140 	}
141 	if (mp->id_num > ptr->id_num) {
142 		/*
143 		 * This is an explicit re-announce, so update the id_num
144 		 * field to avoid duplicates and re-announce the talk.
145 		 */
146 		ptr->id_num = new_id();
147 		rp->id_num = htonl(ptr->id_num);
148 		rp->answer = announce(mp, hp->h_name);
149 	} else {
150 		/* a duplicated request, so ignore it */
151 		rp->id_num = htonl(ptr->id_num);
152 		rp->answer = SUCCESS;
153 	}
154 }
155 
156 #include <utmp.h>
157 
158 /*
159  * Search utmp for the local user
160  */
161 find_user(name, tty)
162 	char *name, *tty;
163 {
164 	struct utmp ubuf;
165 	int status;
166 	FILE *fd;
167 	struct stat statb;
168 	char ftty[20];
169 
170 	if ((fd = fopen("/etc/utmp", "r")) == NULL) {
171 		perror("Can't open /etc/utmp");
172 		return (FAILED);
173 	}
174 #define SCMPN(a, b)	strncmp(a, b, sizeof (a))
175 	status = NOT_HERE;
176 	(void) strcpy(ftty, "/dev/");
177 	while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1)
178 		if (SCMPN(ubuf.ut_name, name) == 0) {
179 			if (*tty == '\0') {
180 				status = PERMISSION_DENIED;
181 				/* no particular tty was requested */
182 				(void) strcpy(ftty+5, ubuf.ut_line);
183 				if (stat(ftty,&statb) == 0) {
184 					if (!(statb.st_mode & 020))
185 						continue;
186 					(void) strcpy(tty, ubuf.ut_line);
187 					status = SUCCESS;
188 					break;
189 				}
190 			}
191 			if (strcmp(ubuf.ut_line, tty) == 0) {
192 				status = SUCCESS;
193 				break;
194 			}
195 		}
196 	fclose(fd);
197 	return (status);
198 }
199