11592Srgrimes/* 21592Srgrimes * Copyright (c) 1983, 1993 31592Srgrimes * The Regents of the University of California. All rights reserved. 41592Srgrimes * 51592Srgrimes * Redistribution and use in source and binary forms, with or without 61592Srgrimes * modification, are permitted provided that the following conditions 71592Srgrimes * are met: 81592Srgrimes * 1. Redistributions of source code must retain the above copyright 91592Srgrimes * notice, this list of conditions and the following disclaimer. 101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111592Srgrimes * notice, this list of conditions and the following disclaimer in the 121592Srgrimes * documentation and/or other materials provided with the distribution. 13262435Sbrueffer * 3. Neither the name of the University nor the names of its contributors 141592Srgrimes * may be used to endorse or promote products derived from this software 151592Srgrimes * without specific prior written permission. 161592Srgrimes * 171592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271592Srgrimes * SUCH DAMAGE. 281592Srgrimes */ 291592Srgrimes 301592Srgrimes#ifndef lint 3131491Scharnier#if 0 321592Srgrimesstatic char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93"; 3331491Scharnier#endif 3431491Scharnierstatic const char rcsid[] = 3550476Speter "$FreeBSD$"; 361592Srgrimes#endif /* not lint */ 371592Srgrimes 381592Srgrimes/* 391592Srgrimes * process.c handles the requests, which can be of three types: 401592Srgrimes * ANNOUNCE - announce to a user that a talk is wanted 411592Srgrimes * LEAVE_INVITE - insert the request into the table 421592Srgrimes * LOOK_UP - look up to see if a request is waiting in 431592Srgrimes * in the table for the local user 441592Srgrimes * DELETE - delete invitation 451592Srgrimes */ 461592Srgrimes#include <sys/param.h> 471592Srgrimes#include <sys/stat.h> 481592Srgrimes#include <sys/socket.h> 491592Srgrimes#include <netinet/in.h> 501592Srgrimes#include <protocols/talkd.h> 5131491Scharnier#include <ctype.h> 5231491Scharnier#include <err.h> 531592Srgrimes#include <netdb.h> 5431491Scharnier#include <paths.h> 551592Srgrimes#include <stdio.h> 561592Srgrimes#include <string.h> 5731491Scharnier#include <syslog.h> 58202210Sed#include <utmpx.h> 591592Srgrimes 6090261Simp#include "extern.h" 611592Srgrimes 6231491Scharniervoid 6390261Simpprocess_request(CTL_MSG *mp, CTL_RESPONSE *rp) 641592Srgrimes{ 6590261Simp CTL_MSG *ptr; 663793Sache char *s; 671592Srgrimes 681592Srgrimes rp->vers = TALK_VERSION; 691592Srgrimes rp->type = mp->type; 701592Srgrimes rp->id_num = htonl(0); 711592Srgrimes if (mp->vers != TALK_VERSION) { 7231491Scharnier syslog(LOG_WARNING, "bad protocol version %d", mp->vers); 731592Srgrimes rp->answer = BADVERSION; 741592Srgrimes return; 751592Srgrimes } 761592Srgrimes mp->id_num = ntohl(mp->id_num); 771592Srgrimes mp->addr.sa_family = ntohs(mp->addr.sa_family); 781592Srgrimes if (mp->addr.sa_family != AF_INET) { 7931491Scharnier syslog(LOG_WARNING, "bad address, family %d", 801592Srgrimes mp->addr.sa_family); 811592Srgrimes rp->answer = BADADDR; 821592Srgrimes return; 831592Srgrimes } 841592Srgrimes mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family); 851592Srgrimes if (mp->ctl_addr.sa_family != AF_INET) { 8631491Scharnier syslog(LOG_WARNING, "bad control address, family %d", 871592Srgrimes mp->ctl_addr.sa_family); 881592Srgrimes rp->answer = BADCTLADDR; 891592Srgrimes return; 901592Srgrimes } 913793Sache for (s = mp->l_name; *s; s++) 923793Sache if (!isprint(*s)) { 9331491Scharnier syslog(LOG_NOTICE, "illegal user name. Aborting"); 943793Sache rp->answer = FAILED; 953793Sache return; 963793Sache } 971592Srgrimes mp->pid = ntohl(mp->pid); 981592Srgrimes if (debug) 991592Srgrimes print_request("process_request", mp); 1001592Srgrimes switch (mp->type) { 1011592Srgrimes 1021592Srgrimes case ANNOUNCE: 1031592Srgrimes do_announce(mp, rp); 1041592Srgrimes break; 1051592Srgrimes 1061592Srgrimes case LEAVE_INVITE: 1071592Srgrimes ptr = find_request(mp); 1081592Srgrimes if (ptr != (CTL_MSG *)0) { 1091592Srgrimes rp->id_num = htonl(ptr->id_num); 1101592Srgrimes rp->answer = SUCCESS; 1111592Srgrimes } else 1121592Srgrimes insert_table(mp, rp); 1131592Srgrimes break; 1141592Srgrimes 1151592Srgrimes case LOOK_UP: 1161592Srgrimes ptr = find_match(mp); 1171592Srgrimes if (ptr != (CTL_MSG *)0) { 1181592Srgrimes rp->id_num = htonl(ptr->id_num); 1191592Srgrimes rp->addr = ptr->addr; 1201592Srgrimes rp->addr.sa_family = htons(ptr->addr.sa_family); 1211592Srgrimes rp->answer = SUCCESS; 1221592Srgrimes } else 1231592Srgrimes rp->answer = NOT_HERE; 1241592Srgrimes break; 1251592Srgrimes 1261592Srgrimes case DELETE: 1271592Srgrimes rp->answer = delete_invite(mp->id_num); 1281592Srgrimes break; 1291592Srgrimes 1301592Srgrimes default: 1311592Srgrimes rp->answer = UNKNOWN_REQUEST; 1321592Srgrimes break; 1331592Srgrimes } 1341592Srgrimes if (debug) 1351592Srgrimes print_response("process_request", rp); 1361592Srgrimes} 1371592Srgrimes 13831491Scharniervoid 13990261Simpdo_announce(CTL_MSG *mp, CTL_RESPONSE *rp) 1401592Srgrimes{ 1411592Srgrimes struct hostent *hp; 1421592Srgrimes CTL_MSG *ptr; 1431592Srgrimes int result; 1441592Srgrimes 1451592Srgrimes /* see if the user is logged */ 1461592Srgrimes result = find_user(mp->r_name, mp->r_tty); 1471592Srgrimes if (result != SUCCESS) { 1481592Srgrimes rp->answer = result; 1491592Srgrimes return; 1501592Srgrimes } 151201022Sed#define satosin(sa) ((struct sockaddr_in *)(void *)(sa)) 152201022Sed hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr, 1531592Srgrimes sizeof (struct in_addr), AF_INET); 1541592Srgrimes if (hp == (struct hostent *)0) { 1551592Srgrimes rp->answer = MACHINE_UNKNOWN; 1561592Srgrimes return; 1571592Srgrimes } 1581592Srgrimes ptr = find_request(mp); 1591592Srgrimes if (ptr == (CTL_MSG *) 0) { 1601592Srgrimes insert_table(mp, rp); 1611592Srgrimes rp->answer = announce(mp, hp->h_name); 1621592Srgrimes return; 1631592Srgrimes } 1641592Srgrimes if (mp->id_num > ptr->id_num) { 1651592Srgrimes /* 1661592Srgrimes * This is an explicit re-announce, so update the id_num 1671592Srgrimes * field to avoid duplicates and re-announce the talk. 1681592Srgrimes */ 1691592Srgrimes ptr->id_num = new_id(); 1701592Srgrimes rp->id_num = htonl(ptr->id_num); 1711592Srgrimes rp->answer = announce(mp, hp->h_name); 1721592Srgrimes } else { 1731592Srgrimes /* a duplicated request, so ignore it */ 1741592Srgrimes rp->id_num = htonl(ptr->id_num); 1751592Srgrimes rp->answer = SUCCESS; 1761592Srgrimes } 1771592Srgrimes} 1781592Srgrimes 1791592Srgrimes/* 1801592Srgrimes * Search utmp for the local user 1811592Srgrimes */ 18231491Scharnierint 18390261Simpfind_user(const char *name, char *tty) 1841592Srgrimes{ 185200983Sed struct utmpx *ut; 1861592Srgrimes int status; 1871592Srgrimes struct stat statb; 18814783Sjkh time_t best = 0; 189200983Sed char ftty[sizeof(_PATH_DEV) - 1 + sizeof(ut->ut_line)]; 1901592Srgrimes 191200983Sed setutxent(); 1921592Srgrimes status = NOT_HERE; 1931592Srgrimes (void) strcpy(ftty, _PATH_DEV); 194200983Sed while ((ut = getutxent()) != NULL) 195200983Sed if (ut->ut_type == USER_PROCESS && 196200983Sed strcmp(ut->ut_user, name) == 0) { 19714783Sjkh if (*tty == '\0' || best != 0) { 19814783Sjkh if (best == 0) 19914783Sjkh status = PERMISSION_DENIED; 2001592Srgrimes /* no particular tty was requested */ 2011592Srgrimes (void) strcpy(ftty + sizeof(_PATH_DEV) - 1, 202200983Sed ut->ut_line); 2031592Srgrimes if (stat(ftty, &statb) == 0) { 2041592Srgrimes if (!(statb.st_mode & 020)) 2051592Srgrimes continue; 20614783Sjkh if (statb.st_atime > best) { 20714783Sjkh best = statb.st_atime; 208200983Sed (void) strcpy(tty, ut->ut_line); 20914783Sjkh status = SUCCESS; 21014783Sjkh continue; 21114783Sjkh } 2121592Srgrimes } 2131592Srgrimes } 214200983Sed if (strcmp(ut->ut_line, tty) == 0) { 2151592Srgrimes status = SUCCESS; 2161592Srgrimes break; 2171592Srgrimes } 2181592Srgrimes } 219200983Sed endutxent(); 2201592Srgrimes return (status); 2211592Srgrimes} 222