1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)process.c 5.10 (Berkeley) 02/26/91"; 10 #endif /* not lint */ 11 12 /* 13 * process.c handles the requests, which can be of three types: 14 * ANNOUNCE - announce to a user that a talk is wanted 15 * LEAVE_INVITE - insert the request into the table 16 * LOOK_UP - look up to see if a request is waiting in 17 * in the table for the local user 18 * DELETE - delete invitation 19 */ 20 #include <sys/param.h> 21 #include <sys/stat.h> 22 #include <sys/socket.h> 23 #include <netinet/in.h> 24 #include <protocols/talkd.h> 25 #include <netdb.h> 26 #include <syslog.h> 27 #include <stdio.h> 28 #include <string.h> 29 #include <paths.h> 30 31 CTL_MSG *find_request(); 32 CTL_MSG *find_match(); 33 34 process_request(mp, rp) 35 register CTL_MSG *mp; 36 register CTL_RESPONSE *rp; 37 { 38 register CTL_MSG *ptr; 39 extern int debug; 40 41 rp->vers = TALK_VERSION; 42 rp->type = mp->type; 43 rp->id_num = htonl(0); 44 if (mp->vers != TALK_VERSION) { 45 syslog(LOG_WARNING, "Bad protocol version %d", mp->vers); 46 rp->answer = BADVERSION; 47 return; 48 } 49 mp->id_num = ntohl(mp->id_num); 50 mp->addr.sa_family = ntohs(mp->addr.sa_family); 51 if (mp->addr.sa_family != AF_INET) { 52 syslog(LOG_WARNING, "Bad address, family %d", 53 mp->addr.sa_family); 54 rp->answer = BADADDR; 55 return; 56 } 57 mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family); 58 if (mp->ctl_addr.sa_family != AF_INET) { 59 syslog(LOG_WARNING, "Bad control address, family %d", 60 mp->ctl_addr.sa_family); 61 rp->answer = BADCTLADDR; 62 return; 63 } 64 mp->pid = ntohl(mp->pid); 65 if (debug) 66 print_request("process_request", mp); 67 switch (mp->type) { 68 69 case ANNOUNCE: 70 do_announce(mp, rp); 71 break; 72 73 case LEAVE_INVITE: 74 ptr = find_request(mp); 75 if (ptr != (CTL_MSG *)0) { 76 rp->id_num = htonl(ptr->id_num); 77 rp->answer = SUCCESS; 78 } else 79 insert_table(mp, rp); 80 break; 81 82 case LOOK_UP: 83 ptr = find_match(mp); 84 if (ptr != (CTL_MSG *)0) { 85 rp->id_num = htonl(ptr->id_num); 86 rp->addr = ptr->addr; 87 rp->addr.sa_family = htons(ptr->addr.sa_family); 88 rp->answer = SUCCESS; 89 } else 90 rp->answer = NOT_HERE; 91 break; 92 93 case DELETE: 94 rp->answer = delete_invite(mp->id_num); 95 break; 96 97 default: 98 rp->answer = UNKNOWN_REQUEST; 99 break; 100 } 101 if (debug) 102 print_response("process_request", rp); 103 } 104 105 do_announce(mp, rp) 106 register CTL_MSG *mp; 107 CTL_RESPONSE *rp; 108 { 109 struct hostent *hp; 110 CTL_MSG *ptr; 111 int result; 112 113 /* see if the user is logged */ 114 result = find_user(mp->r_name, mp->r_tty); 115 if (result != SUCCESS) { 116 rp->answer = result; 117 return; 118 } 119 #define satosin(sa) ((struct sockaddr_in *)(sa)) 120 hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr, 121 sizeof (struct in_addr), AF_INET); 122 if (hp == (struct hostent *)0) { 123 rp->answer = MACHINE_UNKNOWN; 124 return; 125 } 126 ptr = find_request(mp); 127 if (ptr == (CTL_MSG *) 0) { 128 insert_table(mp, rp); 129 rp->answer = announce(mp, hp->h_name); 130 return; 131 } 132 if (mp->id_num > ptr->id_num) { 133 /* 134 * This is an explicit re-announce, so update the id_num 135 * field to avoid duplicates and re-announce the talk. 136 */ 137 ptr->id_num = new_id(); 138 rp->id_num = htonl(ptr->id_num); 139 rp->answer = announce(mp, hp->h_name); 140 } else { 141 /* a duplicated request, so ignore it */ 142 rp->id_num = htonl(ptr->id_num); 143 rp->answer = SUCCESS; 144 } 145 } 146 147 #include <utmp.h> 148 149 /* 150 * Search utmp for the local user 151 */ 152 find_user(name, tty) 153 char *name, *tty; 154 { 155 struct utmp ubuf; 156 int status; 157 FILE *fd; 158 struct stat statb; 159 char ftty[20]; 160 161 if ((fd = fopen(_PATH_UTMP, "r")) == NULL) { 162 fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP); 163 return (FAILED); 164 } 165 #define SCMPN(a, b) strncmp(a, b, sizeof (a)) 166 status = NOT_HERE; 167 (void) strcpy(ftty, _PATH_DEV); 168 while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1) 169 if (SCMPN(ubuf.ut_name, name) == 0) { 170 if (*tty == '\0') { 171 status = PERMISSION_DENIED; 172 /* no particular tty was requested */ 173 (void) strcpy(ftty+5, ubuf.ut_line); 174 if (stat(ftty,&statb) == 0) { 175 if (!(statb.st_mode & 020)) 176 continue; 177 (void) strcpy(tty, ubuf.ut_line); 178 status = SUCCESS; 179 break; 180 } 181 } 182 if (strcmp(ubuf.ut_line, tty) == 0) { 183 status = SUCCESS; 184 break; 185 } 186 } 187 fclose(fd); 188 return (status); 189 } 190