Annotation of src/usr.bin/talk/invite.c, Revision 1.10
1.10 ! deraadt 1: /* $OpenBSD: invite.c,v 1.9 2003/06/03 02:56:17 millert Exp $ */
1.1 deraadt 2: /* $NetBSD: invite.c,v 1.3 1994/12/09 02:14:18 jtc Exp $ */
3:
4: /*
5: * Copyright (c) 1983, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.9 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: #if 0
35: static char sccsid[] = "@(#)invite.c 8.1 (Berkeley) 6/6/93";
36: #endif
1.10 ! deraadt 37: static char rcsid[] = "$OpenBSD: invite.c,v 1.9 2003/06/03 02:56:17 millert Exp $";
1.1 deraadt 38: #endif /* not lint */
39:
1.5 pjanzen 40: #include "talk.h"
41: #include <arpa/inet.h>
1.1 deraadt 42: #include <sys/time.h>
1.4 pjanzen 43: #include <netdb.h>
1.1 deraadt 44: #include <errno.h>
45: #include <setjmp.h>
1.5 pjanzen 46: #include <unistd.h>
1.1 deraadt 47: #include "talk_ctl.h"
48:
1.4 pjanzen 49: #define STRING_LENGTH 158
50:
1.1 deraadt 51: /*
52: * There wasn't an invitation waiting, so send a request containing
53: * our sockt address to the remote talk daemon so it can invite
1.6 millert 54: * him
1.1 deraadt 55: */
56:
57: /*
58: * The msg.id's for the invitations
59: * on the local and remote machines.
1.6 millert 60: * These are used to delete the
1.1 deraadt 61: * invitations.
62: */
63: int local_id, remote_id;
64: jmp_buf invitebuf;
65:
1.5 pjanzen 66: void
1.10 ! deraadt 67: invite_remote(void)
1.1 deraadt 68: {
1.5 pjanzen 69: int new_sockt;
1.1 deraadt 70: struct itimerval itimer;
71: CTL_RESPONSE response;
1.4 pjanzen 72: struct sockaddr rp;
73: int rplen = sizeof(struct sockaddr);
74: struct hostent *rphost;
75: char rname[STRING_LENGTH];
1.1 deraadt 76:
77: itimer.it_value.tv_sec = RING_WAIT;
78: itimer.it_value.tv_usec = 0;
79: itimer.it_interval = itimer.it_value;
80: if (listen(sockt, 5) != 0)
1.7 millert 81: quit("Error on attempt to listen for caller", 1);
1.1 deraadt 82: #ifdef MSG_EOR
83: /* copy new style sockaddr to old, swap family (short in old) */
84: msg.addr = *(struct osockaddr *)&my_addr; /* XXX new to old style*/
85: msg.addr.sa_family = htons(my_addr.sin_family);
86: #else
87: msg.addr = *(struct sockaddr *)&my_addr;
88: #endif
89: msg.id_num = htonl(-1); /* an impossible id_num */
90: invitation_waiting = 1;
91: announce_invite();
92: /*
93: * Shut off the automatic messages for a while,
1.4 pjanzen 94: * so we can use the interrupt timer to resend the invitation.
95: * We no longer turn automatic messages back on to avoid a bonus
96: * message after we've connected; this is okay even though end_msgs()
97: * gets called again in main().
1.1 deraadt 98: */
99: end_msgs();
100: setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
101: message("Waiting for your party to respond");
102: signal(SIGALRM, re_invite);
103: (void) setjmp(invitebuf);
1.4 pjanzen 104: while ((new_sockt = accept(sockt, &rp, &rplen)) < 0) {
1.1 deraadt 105: if (errno == EINTR)
106: continue;
1.7 millert 107: quit("Unable to connect with your party", 1);
1.1 deraadt 108: }
109: close(sockt);
110: sockt = new_sockt;
111:
112: /*
113: * Have the daemons delete the invitations now that we
114: * have connected.
115: */
116: msg.id_num = htonl(local_id);
117: ctl_transact(my_machine_addr, msg, DELETE, &response);
118: msg.id_num = htonl(remote_id);
119: ctl_transact(his_machine_addr, msg, DELETE, &response);
120: invitation_waiting = 0;
1.4 pjanzen 121:
122: /*
123: * Check to see if the other guy is coming from the machine
124: * we expect.
125: */
126: if (his_machine_addr.s_addr !=
127: ((struct sockaddr_in *)&rp)->sin_addr.s_addr) {
128: rphost = gethostbyaddr((char *) &((struct sockaddr_in
129: *)&rp)->sin_addr, sizeof(struct in_addr), AF_INET);
130: if (rphost)
131: snprintf(rname, STRING_LENGTH,
132: "Answering talk request from %s@%s", msg.r_name,
133: rphost->h_name);
134: else
135: snprintf(rname, STRING_LENGTH,
136: "Answering talk request from %s@%s", msg.r_name,
137: inet_ntoa(((struct sockaddr_in *)&rp)->sin_addr));
138: message(rname);
139: }
1.1 deraadt 140: }
141:
142: /*
143: * Routine called on interupt to re-invite the callee
144: */
145: void
1.10 ! deraadt 146: re_invite(int dummy)
1.1 deraadt 147: {
148: message("Ringing your party again");
149: /* force a re-announce */
150: msg.id_num = htonl(remote_id + 1);
151: announce_invite();
152: longjmp(invitebuf, 1);
153: }
154:
155: static char *answers[] = {
156: "answer #0", /* SUCCESS */
157: "Your party is not logged on", /* NOT_HERE */
158: "Target machine is too confused to talk to us", /* FAILED */
159: "Target machine does not recognize us", /* MACHINE_UNKNOWN */
160: "Your party is refusing messages", /* PERMISSION_REFUSED */
161: "Target machine can not handle remote talk", /* UNKNOWN_REQUEST */
162: "Target machine indicates protocol mismatch", /* BADVERSION */
163: "Target machine indicates protocol botch (addr)",/* BADADDR */
164: "Target machine indicates protocol botch (ctl_addr)",/* BADCTLADDR */
165: };
1.5 pjanzen 166: #define NANSWERS (sizeof (answers) / sizeof (answers[0]))
1.1 deraadt 167:
168: /*
169: * Transmit the invitation and process the response
170: */
1.5 pjanzen 171: void
1.10 ! deraadt 172: announce_invite(void)
1.1 deraadt 173: {
174: CTL_RESPONSE response;
175:
176: current_state = "Trying to connect to your party's talk daemon";
177: ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
178: remote_id = response.id_num;
1.7 millert 179: if (response.answer != SUCCESS)
180: quit(response.answer < NANSWERS ? answers[response.answer] : NULL, 0);
1.1 deraadt 181: /* leave the actual invitation on my talk daemon */
182: ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response);
183: local_id = response.id_num;
184: }
185:
186: /*
187: * Tell the daemon to remove your invitation
188: */
1.5 pjanzen 189: void
1.10 ! deraadt 190: send_delete(void)
1.1 deraadt 191: {
192:
193: msg.type = DELETE;
194: /*
195: * This is just a extra clean up, so just send it
196: * and don't wait for an answer
197: */
198: msg.id_num = htonl(remote_id);
199: daemon_addr.sin_addr = his_machine_addr;
200: if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
201: (struct sockaddr *)&daemon_addr,
202: sizeof (daemon_addr)) != sizeof(msg))
1.6 millert 203: warn("send_delete (remote)");
1.1 deraadt 204: msg.id_num = htonl(local_id);
205: daemon_addr.sin_addr = my_machine_addr;
206: if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
207: (struct sockaddr *)&daemon_addr,
208: sizeof (daemon_addr)) != sizeof (msg))
1.6 millert 209: warn("send_delete (local)");
1.1 deraadt 210: }