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