122774Smckusick /*
261449Sbostic * Copyright (c) 1983, 1993
361449Sbostic * The Regents of the University of California. All rights reserved.
434360Sbostic *
542673Sbostic * %sccs.include.redist.c%
622774Smckusick */
722774Smckusick
816365Skarels #ifndef lint
9*64883Sbostic static char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93";
1034360Sbostic #endif /* not lint */
1116355Skarels
1216365Skarels /*
1316365Skarels * process.c handles the requests, which can be of three types:
1416365Skarels * ANNOUNCE - announce to a user that a talk is wanted
1516365Skarels * LEAVE_INVITE - insert the request into the table
1616365Skarels * LOOK_UP - look up to see if a request is waiting in
1716365Skarels * in the table for the local user
1816365Skarels * DELETE - delete invitation
1916365Skarels */
2046683Sbostic #include <sys/param.h>
2117560Sbloom #include <sys/stat.h>
2246683Sbostic #include <sys/socket.h>
2326839Smckusick #include <netinet/in.h>
2426839Smckusick #include <protocols/talkd.h>
2546683Sbostic #include <netdb.h>
2646683Sbostic #include <syslog.h>
2746683Sbostic #include <stdio.h>
2846683Sbostic #include <string.h>
2937991Sbostic #include <paths.h>
3026839Smckusick
3116355Skarels CTL_MSG *find_request();
3216355Skarels CTL_MSG *find_match();
3316355Skarels
process_request(mp,rp)3426839Smckusick process_request(mp, rp)
3526839Smckusick register CTL_MSG *mp;
3626839Smckusick register CTL_RESPONSE *rp;
3716355Skarels {
3826839Smckusick register CTL_MSG *ptr;
3926839Smckusick extern int debug;
4016355Skarels
4126839Smckusick rp->vers = TALK_VERSION;
4226839Smckusick rp->type = mp->type;
4326839Smckusick rp->id_num = htonl(0);
4426839Smckusick if (mp->vers != TALK_VERSION) {
4526839Smckusick syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
4626839Smckusick rp->answer = BADVERSION;
4726839Smckusick return;
4826839Smckusick }
4926839Smckusick mp->id_num = ntohl(mp->id_num);
5026839Smckusick mp->addr.sa_family = ntohs(mp->addr.sa_family);
5126839Smckusick if (mp->addr.sa_family != AF_INET) {
5226839Smckusick syslog(LOG_WARNING, "Bad address, family %d",
5326839Smckusick mp->addr.sa_family);
5426839Smckusick rp->answer = BADADDR;
5526839Smckusick return;
5626839Smckusick }
5726839Smckusick mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
5826839Smckusick if (mp->ctl_addr.sa_family != AF_INET) {
5926839Smckusick syslog(LOG_WARNING, "Bad control address, family %d",
6026839Smckusick mp->ctl_addr.sa_family);
6126839Smckusick rp->answer = BADCTLADDR;
6226839Smckusick return;
6326839Smckusick }
6426839Smckusick mp->pid = ntohl(mp->pid);
6526839Smckusick if (debug)
6626839Smckusick print_request("process_request", mp);
6726839Smckusick switch (mp->type) {
6816355Skarels
6926839Smckusick case ANNOUNCE:
7026839Smckusick do_announce(mp, rp);
7116365Skarels break;
7216355Skarels
7326839Smckusick case LEAVE_INVITE:
7426839Smckusick ptr = find_request(mp);
7526839Smckusick if (ptr != (CTL_MSG *)0) {
7626839Smckusick rp->id_num = htonl(ptr->id_num);
7726839Smckusick rp->answer = SUCCESS;
7816365Skarels } else
7926839Smckusick insert_table(mp, rp);
8016365Skarels break;
8116355Skarels
8226839Smckusick case LOOK_UP:
8326839Smckusick ptr = find_match(mp);
8426839Smckusick if (ptr != (CTL_MSG *)0) {
8526839Smckusick rp->id_num = htonl(ptr->id_num);
8626839Smckusick rp->addr = ptr->addr;
8726839Smckusick rp->addr.sa_family = htons(ptr->addr.sa_family);
8826839Smckusick rp->answer = SUCCESS;
8916365Skarels } else
9026839Smckusick rp->answer = NOT_HERE;
9116365Skarels break;
9216355Skarels
9326839Smckusick case DELETE:
9426839Smckusick rp->answer = delete_invite(mp->id_num);
9516365Skarels break;
9616355Skarels
9726839Smckusick default:
9826839Smckusick rp->answer = UNKNOWN_REQUEST;
9916365Skarels break;
10016365Skarels }
10126839Smckusick if (debug)
10226839Smckusick print_response("process_request", rp);
10316355Skarels }
10416355Skarels
do_announce(mp,rp)10526839Smckusick do_announce(mp, rp)
10626839Smckusick register CTL_MSG *mp;
10726839Smckusick CTL_RESPONSE *rp;
10816355Skarels {
10916365Skarels struct hostent *hp;
11016365Skarels CTL_MSG *ptr;
11116365Skarels int result;
11216355Skarels
11316355Skarels /* see if the user is logged */
11426839Smckusick result = find_user(mp->r_name, mp->r_tty);
11516365Skarels if (result != SUCCESS) {
11626839Smckusick rp->answer = result;
11716365Skarels return;
11816365Skarels }
11926839Smckusick #define satosin(sa) ((struct sockaddr_in *)(sa))
12046683Sbostic hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr,
12126839Smckusick sizeof (struct in_addr), AF_INET);
12216365Skarels if (hp == (struct hostent *)0) {
12326839Smckusick rp->answer = MACHINE_UNKNOWN;
12416365Skarels return;
12516365Skarels }
12626839Smckusick ptr = find_request(mp);
12716365Skarels if (ptr == (CTL_MSG *) 0) {
12826839Smckusick insert_table(mp, rp);
12926839Smckusick rp->answer = announce(mp, hp->h_name);
13016365Skarels return;
13116365Skarels }
13226839Smckusick if (mp->id_num > ptr->id_num) {
13316365Skarels /*
13426839Smckusick * This is an explicit re-announce, so update the id_num
13526839Smckusick * field to avoid duplicates and re-announce the talk.
13616365Skarels */
13726839Smckusick ptr->id_num = new_id();
13826839Smckusick rp->id_num = htonl(ptr->id_num);
13926839Smckusick rp->answer = announce(mp, hp->h_name);
14026839Smckusick } else {
14126839Smckusick /* a duplicated request, so ignore it */
14226839Smckusick rp->id_num = htonl(ptr->id_num);
14326839Smckusick rp->answer = SUCCESS;
14416365Skarels }
14516355Skarels }
14616355Skarels
14716355Skarels #include <utmp.h>
14816355Skarels
14916355Skarels /*
15016355Skarels * Search utmp for the local user
15116355Skarels */
find_user(name,tty)15216355Skarels find_user(name, tty)
15326839Smckusick char *name, *tty;
15416355Skarels {
15516365Skarels struct utmp ubuf;
15623462Sbloom int status;
15723462Sbloom FILE *fd;
15817560Sbloom struct stat statb;
159*64883Sbostic char line[sizeof(ubuf.ut_line) + 1];
160*64883Sbostic char ftty[sizeof(_PATH_DEV) - 1 + sizeof(line)];
16116355Skarels
16237303Sbostic if ((fd = fopen(_PATH_UTMP, "r")) == NULL) {
16337303Sbostic fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP);
16416365Skarels return (FAILED);
16516355Skarels }
16616365Skarels #define SCMPN(a, b) strncmp(a, b, sizeof (a))
16716365Skarels status = NOT_HERE;
16837991Sbostic (void) strcpy(ftty, _PATH_DEV);
16923462Sbloom while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1)
17016365Skarels if (SCMPN(ubuf.ut_name, name) == 0) {
171*64883Sbostic strncpy(line, ubuf.ut_line, sizeof(ubuf.ut_line));
172*64883Sbostic line[sizeof(ubuf.ut_line)] = '\0';
17316365Skarels if (*tty == '\0') {
17417560Sbloom status = PERMISSION_DENIED;
17516365Skarels /* no particular tty was requested */
176*64883Sbostic (void) strcpy(ftty + sizeof(_PATH_DEV) - 1,
177*64883Sbostic line);
178*64883Sbostic if (stat(ftty, &statb) == 0) {
17926854Smckusick if (!(statb.st_mode & 020))
18017560Sbloom continue;
181*64883Sbostic (void) strcpy(tty, line);
18217560Sbloom status = SUCCESS;
18317560Sbloom break;
18417560Sbloom }
18516365Skarels }
186*64883Sbostic if (strcmp(line, tty) == 0) {
18716365Skarels status = SUCCESS;
18816365Skarels break;
18916365Skarels }
19016365Skarels }
19123462Sbloom fclose(fd);
19216365Skarels return (status);
19316355Skarels }
194