xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/in.talkd/process.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
28  * All Rights Reserved.
29  */
30 
31 /*
32  * University Copyright- Copyright (c) 1982, 1986, 1988
33  * The Regents of the University of California.
34  * All Rights Reserved.
35  *
36  * University Acknowledgment- Portions of this document are derived from
37  * software developed by the University of California, Berkeley, and its
38  * contributors.
39  */
40 
41 #pragma ident	"%Z%%M%	%I%	%E% SMI"
42 
43 
44 /*
45  * process.c handles the requests, which can be of three types:
46  *
47  * ANNOUNCE - announce to a user that a talk is wanted
48  *
49  * LEAVE_INVITE - insert the request into the table
50  *
51  * LOOK_UP - look up to see if a request is waiting in
52  * in the table for the local user
53  *
54  * DELETE - delete invitation
55  *
56  */
57 
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 #include <fcntl.h>
61 #include <syslog.h>
62 #include <string.h>
63 #include <utmpx.h>
64 #include <unistd.h>
65 #include <stdlib.h>
66 #include <stdio.h>
67 #include "talkd_impl.h"
68 
69 static void do_announce(CTL_MSG *request, CTL_RESPONSE *response);
70 static int find_user(char *name, char *tty);
71 
72 void
73 process_request(CTL_MSG *request, CTL_RESPONSE *response)
74 {
75 	CTL_MSG *ptr;
76 
77 	response->type = request->type;
78 	response->id_num = 0;
79 
80 	/*
81 	 * Check if any of the strings within the request structure aren't
82 	 * NUL terminated, and if so don't bother processing the request
83 	 * further.
84 	 */
85 	if ((memchr(request->l_name, '\0', sizeof (request->l_name)) == NULL) ||
86 	    (memchr(request->r_name, '\0', sizeof (request->r_name)) == NULL) ||
87 	    (memchr(request->r_tty, '\0', sizeof (request->r_tty)) == NULL)) {
88 		response->answer = FAILED;
89 		openlog("talk", 0, LOG_AUTH);
90 		syslog(LOG_CRIT, "malformed talk request\n");
91 		closelog();
92 		return;
93 	}
94 
95 	switch (request->type) {
96 
97 	    case ANNOUNCE :
98 
99 		do_announce(request, response);
100 		break;
101 
102 	    case LEAVE_INVITE :
103 
104 		ptr = find_request(request);
105 		if (ptr != NULL) {
106 			response->id_num = ptr->id_num;
107 			response->answer = SUCCESS;
108 		} else {
109 			insert_table(request, response);
110 		}
111 		break;
112 
113 	    case LOOK_UP :
114 
115 		ptr = find_match(request);
116 		if (ptr != NULL) {
117 			response->id_num = ptr->id_num;
118 			response->addr = ptr->addr;
119 			response->answer = SUCCESS;
120 		} else {
121 			response->answer = NOT_HERE;
122 		}
123 		break;
124 
125 	    case DELETE :
126 
127 		response->answer = delete_invite(request->id_num);
128 		break;
129 
130 	    default :
131 
132 		response->answer = UNKNOWN_REQUEST;
133 		break;
134 	}
135 }
136 
137 static void
138 do_announce(CTL_MSG *request, CTL_RESPONSE *response)
139 {
140 	struct hostent *hp;
141 	CTL_MSG *ptr;
142 	int result;
143 
144 	/*
145 	 * See if the user is logged.
146 	 */
147 	result = find_user(request->r_name, request->r_tty);
148 	if (result != SUCCESS) {
149 		response->answer = result;
150 		return;
151 	}
152 
153 	hp = gethostbyaddr((const char *)&request->ctl_addr.sin_addr,
154 	    sizeof (struct in_addr), AF_INET);
155 	if (hp == NULL) {
156 		response->answer = MACHINE_UNKNOWN;
157 		return;
158 	}
159 
160 	ptr = find_request(request);
161 	if (ptr == NULL) {
162 		insert_table(request, response);
163 		response->answer = announce(request, hp->h_name);
164 	} else if (request->id_num > ptr->id_num) {
165 		/*
166 		 * This is an explicit re-announce, so update the id_num
167 		 * field to avoid duplicates and re-announce the talk.
168 		 */
169 		ptr->id_num = response->id_num = new_id();
170 		response->answer = announce(request, hp->h_name);
171 	} else {
172 		/* a duplicated request, so ignore it */
173 		response->id_num = ptr->id_num;
174 		response->answer = SUCCESS;
175 	}
176 }
177 
178 /*
179  * Search utmp for the local user.
180  */
181 
182 static int
183 find_user(char *name, char *tty)
184 {
185 	struct utmpx *ubuf;
186 	int tfd;
187 	char dev[MAXPATHLEN];
188 
189 	setutxent();		/* reset the utmpx file */
190 
191 	while (ubuf = getutxent()) {
192 		if (ubuf->ut_type == USER_PROCESS &&
193 		    strncmp(ubuf->ut_user, name, sizeof (ubuf->ut_user)) == 0) {
194 			/*
195 			 * Check if this entry is really a tty.
196 			 */
197 			(void) snprintf(dev, sizeof (dev), "/dev/%.*s",
198 			    sizeof (ubuf->ut_line), ubuf->ut_line);
199 			if ((tfd = open(dev, O_WRONLY|O_NOCTTY)) == -1) {
200 				continue;
201 			}
202 			if (!isatty(tfd)) {
203 				(void) close(tfd);
204 				openlog("talk", 0, LOG_AUTH);
205 				syslog(LOG_CRIT, "%.*s in utmp is not a tty\n",
206 				    sizeof (ubuf->ut_line), ubuf->ut_line);
207 				closelog();
208 				continue;
209 			}
210 			(void) close(tfd);
211 			if (*tty == '\0') {
212 				/*
213 				 * No particular tty was requested.
214 				 */
215 				(void) strlcpy(tty, ubuf->ut_line, TTY_SIZE);
216 				endutxent();	/* close the utmpx file */
217 				return (SUCCESS);
218 			} else if (strcmp(ubuf->ut_line, tty) == 0) {
219 				endutxent();	/* close the utmpx file */
220 				return (SUCCESS);
221 			}
222 		}
223 	}
224 
225 	endutxent();		/* close the utmpx file */
226 	return (NOT_HERE);
227 }
228