1 1.14 lukem /* $NetBSD: process.c,v 1.14 2009/03/16 01:13:38 lukem Exp $ */ 2 1.3 christos 3 1.1 cgd /* 4 1.3 christos * Copyright (c) 1983, 1993 5 1.3 christos * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.10 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.3 christos #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.3 christos #if 0 35 1.3 christos static char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93"; 36 1.3 christos #else 37 1.14 lukem __RCSID("$NetBSD: process.c,v 1.14 2009/03/16 01:13:38 lukem Exp $"); 38 1.3 christos #endif 39 1.1 cgd #endif /* not lint */ 40 1.1 cgd 41 1.1 cgd /* 42 1.1 cgd * process.c handles the requests, which can be of three types: 43 1.1 cgd * ANNOUNCE - announce to a user that a talk is wanted 44 1.1 cgd * LEAVE_INVITE - insert the request into the table 45 1.1 cgd * LOOK_UP - look up to see if a request is waiting in 46 1.1 cgd * in the table for the local user 47 1.1 cgd * DELETE - delete invitation 48 1.1 cgd */ 49 1.5 mrg 50 1.1 cgd #include <sys/param.h> 51 1.1 cgd #include <sys/stat.h> 52 1.1 cgd #include <sys/socket.h> 53 1.5 mrg 54 1.1 cgd #include <netinet/in.h> 55 1.5 mrg 56 1.1 cgd #include <protocols/talkd.h> 57 1.5 mrg 58 1.1 cgd #include <netdb.h> 59 1.1 cgd #include <syslog.h> 60 1.1 cgd #include <stdio.h> 61 1.1 cgd #include <string.h> 62 1.1 cgd #include <paths.h> 63 1.5 mrg 64 1.4 christos #include "extern.h" 65 1.1 cgd 66 1.7 christos #include "utmpentry.h" 67 1.7 christos 68 1.4 christos void 69 1.13 lukem process_request(CTL_MSG *mp, CTL_RESPONSE *rp) 70 1.1 cgd { 71 1.4 christos CTL_MSG *ptr; 72 1.1 cgd 73 1.1 cgd rp->vers = TALK_VERSION; 74 1.1 cgd rp->type = mp->type; 75 1.1 cgd rp->id_num = htonl(0); 76 1.8 itojun mp->id_num = ntohl(mp->id_num); 77 1.8 itojun mp->addr.sa_family = ntohs(mp->addr.sa_family); 78 1.8 itojun mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family); 79 1.8 itojun mp->pid = ntohl(mp->pid); 80 1.1 cgd if (mp->vers != TALK_VERSION) { 81 1.1 cgd syslog(LOG_WARNING, "Bad protocol version %d", mp->vers); 82 1.1 cgd rp->answer = BADVERSION; 83 1.1 cgd return; 84 1.1 cgd } 85 1.1 cgd if (mp->addr.sa_family != AF_INET) { 86 1.1 cgd syslog(LOG_WARNING, "Bad address, family %d", 87 1.1 cgd mp->addr.sa_family); 88 1.1 cgd rp->answer = BADADDR; 89 1.1 cgd return; 90 1.1 cgd } 91 1.1 cgd if (mp->ctl_addr.sa_family != AF_INET) { 92 1.1 cgd syslog(LOG_WARNING, "Bad control address, family %d", 93 1.1 cgd mp->ctl_addr.sa_family); 94 1.1 cgd rp->answer = BADCTLADDR; 95 1.1 cgd return; 96 1.1 cgd } 97 1.6 mrg if (debug || logging) 98 1.6 mrg print_request("request", mp); 99 1.1 cgd switch (mp->type) { 100 1.1 cgd 101 1.1 cgd case ANNOUNCE: 102 1.1 cgd do_announce(mp, rp); 103 1.1 cgd break; 104 1.1 cgd 105 1.1 cgd case LEAVE_INVITE: 106 1.1 cgd ptr = find_request(mp); 107 1.1 cgd if (ptr != (CTL_MSG *)0) { 108 1.1 cgd rp->id_num = htonl(ptr->id_num); 109 1.1 cgd rp->answer = SUCCESS; 110 1.1 cgd } else 111 1.1 cgd insert_table(mp, rp); 112 1.1 cgd break; 113 1.1 cgd 114 1.1 cgd case LOOK_UP: 115 1.1 cgd ptr = find_match(mp); 116 1.1 cgd if (ptr != (CTL_MSG *)0) { 117 1.1 cgd rp->id_num = htonl(ptr->id_num); 118 1.1 cgd rp->addr = ptr->addr; 119 1.1 cgd rp->addr.sa_family = htons(ptr->addr.sa_family); 120 1.1 cgd rp->answer = SUCCESS; 121 1.1 cgd } else 122 1.1 cgd rp->answer = NOT_HERE; 123 1.1 cgd break; 124 1.1 cgd 125 1.1 cgd case DELETE: 126 1.1 cgd rp->answer = delete_invite(mp->id_num); 127 1.1 cgd break; 128 1.1 cgd 129 1.1 cgd default: 130 1.1 cgd rp->answer = UNKNOWN_REQUEST; 131 1.1 cgd break; 132 1.1 cgd } 133 1.1 cgd if (debug) 134 1.6 mrg print_response("process_request done", rp); 135 1.1 cgd } 136 1.1 cgd 137 1.4 christos void 138 1.13 lukem do_announce(CTL_MSG *mp, CTL_RESPONSE *rp) 139 1.1 cgd { 140 1.1 cgd CTL_MSG *ptr; 141 1.1 cgd int result; 142 1.12 christos char hostname[NI_MAXHOST]; 143 1.12 christos struct sockaddr sa; 144 1.12 christos 145 1.12 christos tsa2sa(&sa, &mp->ctl_addr); 146 1.1 cgd 147 1.1 cgd /* see if the user is logged */ 148 1.8 itojun result = find_user(mp->r_name, mp->r_tty, sizeof(mp->r_tty)); 149 1.1 cgd if (result != SUCCESS) { 150 1.1 cgd rp->answer = result; 151 1.1 cgd return; 152 1.1 cgd } 153 1.12 christos if (getnameinfo(&sa, sa.sa_len, hostname, sizeof(hostname), NULL, 154 1.12 christos 0, 0)) { 155 1.1 cgd rp->answer = MACHINE_UNKNOWN; 156 1.1 cgd return; 157 1.1 cgd } 158 1.1 cgd ptr = find_request(mp); 159 1.1 cgd if (ptr == (CTL_MSG *) 0) { 160 1.1 cgd insert_table(mp, rp); 161 1.12 christos rp->answer = announce(mp, hostname); 162 1.1 cgd return; 163 1.1 cgd } 164 1.1 cgd if (mp->id_num > ptr->id_num) { 165 1.1 cgd /* 166 1.1 cgd * This is an explicit re-announce, so update the id_num 167 1.1 cgd * field to avoid duplicates and re-announce the talk. 168 1.1 cgd */ 169 1.1 cgd ptr->id_num = new_id(); 170 1.1 cgd rp->id_num = htonl(ptr->id_num); 171 1.12 christos rp->answer = announce(mp, hostname); 172 1.1 cgd } else { 173 1.1 cgd /* a duplicated request, so ignore it */ 174 1.1 cgd rp->id_num = htonl(ptr->id_num); 175 1.1 cgd rp->answer = SUCCESS; 176 1.1 cgd } 177 1.1 cgd } 178 1.1 cgd 179 1.1 cgd /* 180 1.1 cgd * Search utmp for the local user 181 1.1 cgd */ 182 1.4 christos int 183 1.14 lukem find_user(const char *name, char *tty, size_t ttysize) 184 1.1 cgd { 185 1.1 cgd int status; 186 1.1 cgd struct stat statb; 187 1.7 christos struct utmpentry *ep; 188 1.7 christos char ftty[sizeof(_PATH_DEV) + sizeof(ep->line)]; 189 1.4 christos time_t atime = 0; 190 1.4 christos int anytty = 0; 191 1.1 cgd 192 1.7 christos (void)getutentries(NULL, &ep); 193 1.7 christos 194 1.1 cgd status = NOT_HERE; 195 1.8 itojun (void) strlcpy(ftty, _PATH_DEV, sizeof(ftty)); 196 1.4 christos 197 1.4 christos if (*tty == '\0') 198 1.4 christos anytty = 1; 199 1.4 christos 200 1.7 christos for (; ep; ep = ep->next) { 201 1.7 christos if (strcmp(ep->name, name) != 0) 202 1.4 christos continue; 203 1.4 christos if (anytty) { 204 1.4 christos /* no particular tty was requested */ 205 1.11 christos (void)strlcpy(ftty + sizeof(_PATH_DEV) - 1, ep->line, 206 1.11 christos sizeof(ftty) - sizeof(_PATH_DEV) + 1); 207 1.8 itojun if (stat(ftty, &statb) != 0) 208 1.8 itojun continue; 209 1.8 itojun 210 1.8 itojun if (!(statb.st_mode & S_IWGRP)) { 211 1.8 itojun if (status != SUCCESS) 212 1.8 itojun status = PERMISSION_DENIED; 213 1.8 itojun continue; 214 1.8 itojun } 215 1.8 itojun if (statb.st_atime > atime && 216 1.8 itojun strlcpy(tty, ep->line, ttysize) < ttysize) { 217 1.8 itojun atime = statb.st_atime; 218 1.8 itojun status = SUCCESS; 219 1.1 cgd } 220 1.7 christos } else if (strcmp(ep->line, tty) == 0) { 221 1.4 christos status = SUCCESS; 222 1.4 christos break; 223 1.1 cgd } 224 1.4 christos } 225 1.1 cgd return (status); 226 1.1 cgd } 227