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