1 /* $OpenBSD: invite.c,v 1.17 2016/03/16 15:41:11 krw Exp $ */
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.
16 * 3. Neither the name of the University nor the names of its contributors
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 #include <sys/socket.h>
34 #include <arpa/inet.h>
35
36 #include <err.h>
37 #include <errno.h>
38 #include <netdb.h>
39 #include <setjmp.h>
40 #include <unistd.h>
41
42 #include "talk.h"
43 #include "talk_ctl.h"
44
45 #define STRING_LENGTH 158
46
47 /*
48 * There wasn't an invitation waiting, so send a request containing
49 * our sockt address to the remote talk daemon so it can invite
50 * him
51 */
52
53 /*
54 * The msg.id's for the invitations
55 * on the local and remote machines.
56 * These are used to delete the
57 * invitations.
58 */
59 int local_id, remote_id;
60 jmp_buf invitebuf;
61
62 void
invite_remote(void)63 invite_remote(void)
64 {
65 int new_sockt;
66 struct itimerval itimer;
67 CTL_RESPONSE response;
68 struct sockaddr rp;
69 socklen_t rplen = sizeof(struct sockaddr);
70 struct hostent *rphost;
71 char rname[STRING_LENGTH];
72
73 itimer.it_value.tv_sec = RING_WAIT;
74 itimer.it_value.tv_usec = 0;
75 itimer.it_interval = itimer.it_value;
76 if (listen(sockt, 5) != 0)
77 quit("Error on attempt to listen for caller", 1);
78 #ifdef MSG_EOR
79 /* copy new style sockaddr to old, swap family (short in old) */
80 msg.addr = *(struct osockaddr *)&my_addr; /* XXX new to old style*/
81 msg.addr.sa_family = htons(my_addr.sin_family);
82 #else
83 msg.addr = *(struct sockaddr *)&my_addr;
84 #endif
85 msg.id_num = htonl(-1); /* an impossible id_num */
86 invitation_waiting = 1;
87 announce_invite();
88 /*
89 * Shut off the automatic messages for a while,
90 * so we can use the interrupt timer to resend the invitation.
91 * We no longer turn automatic messages back on to avoid a bonus
92 * message after we've connected; this is okay even though end_msgs()
93 * gets called again in main().
94 */
95 end_msgs();
96 setitimer(ITIMER_REAL, &itimer, NULL);
97 message("Waiting for your party to respond");
98 signal(SIGALRM, re_invite);
99 (void) setjmp(invitebuf);
100 while ((new_sockt = accept(sockt, &rp, &rplen)) == -1) {
101 if (errno == EINTR || errno == EWOULDBLOCK ||
102 errno == ECONNABORTED)
103 continue;
104 quit("Unable to connect with your party", 1);
105 }
106 close(sockt);
107 sockt = new_sockt;
108
109 /*
110 * Have the daemons delete the invitations now that we
111 * have connected.
112 */
113 msg.id_num = htonl(local_id);
114 ctl_transact(my_machine_addr, msg, DELETE, &response);
115 msg.id_num = htonl(remote_id);
116 ctl_transact(his_machine_addr, msg, DELETE, &response);
117 invitation_waiting = 0;
118
119 /*
120 * Check to see if the other guy is coming from the machine
121 * we expect.
122 */
123 if (his_machine_addr.s_addr !=
124 ((struct sockaddr_in *)&rp)->sin_addr.s_addr) {
125 rphost = gethostbyaddr((char *) &((struct sockaddr_in
126 *)&rp)->sin_addr, sizeof(struct in_addr), AF_INET);
127 if (rphost)
128 snprintf(rname, STRING_LENGTH,
129 "Answering talk request from %s@%s", msg.r_name,
130 rphost->h_name);
131 else
132 snprintf(rname, STRING_LENGTH,
133 "Answering talk request from %s@%s", msg.r_name,
134 inet_ntoa(((struct sockaddr_in *)&rp)->sin_addr));
135 message(rname);
136 }
137 }
138
139 /*
140 * Routine called on interrupt to re-invite the callee
141 */
142 void
re_invite(int dummy)143 re_invite(int dummy)
144 {
145 message("Ringing your party again");
146 /* force a re-announce */
147 msg.id_num = htonl(remote_id + 1);
148 announce_invite();
149 longjmp(invitebuf, 1);
150 }
151
152 static char *answers[] = {
153 "answer #0", /* SUCCESS */
154 "Your party is not logged on", /* NOT_HERE */
155 "Target machine is too confused to talk to us", /* FAILED */
156 "Target machine does not recognize us", /* MACHINE_UNKNOWN */
157 "Your party is refusing messages", /* PERMISSION_REFUSED */
158 "Target machine can not handle remote talk", /* UNKNOWN_REQUEST */
159 "Target machine indicates protocol mismatch", /* BADVERSION */
160 "Target machine indicates protocol botch (addr)",/* BADADDR */
161 "Target machine indicates protocol botch (ctl_addr)",/* BADCTLADDR */
162 };
163 #define NANSWERS (sizeof (answers) / sizeof (answers[0]))
164
165 /*
166 * Transmit the invitation and process the response
167 */
168 void
announce_invite(void)169 announce_invite(void)
170 {
171 CTL_RESPONSE response;
172
173 current_state = "Trying to connect to your party's talk daemon";
174 ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
175 remote_id = response.id_num;
176 if (response.answer != SUCCESS)
177 quit(response.answer < NANSWERS ? answers[response.answer] : NULL, 0);
178 /* leave the actual invitation on my talk daemon */
179 ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response);
180 local_id = response.id_num;
181 }
182
183 /*
184 * Tell the daemon to remove your invitation
185 */
186 void
send_delete(void)187 send_delete(void)
188 {
189
190 msg.type = DELETE;
191 /*
192 * This is just a extra clean up, so just send it
193 * and don't wait for an answer
194 */
195 msg.id_num = htonl(remote_id);
196 daemon_addr.sin_addr = his_machine_addr;
197 if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
198 (struct sockaddr *)&daemon_addr,
199 sizeof (daemon_addr)) != sizeof(msg))
200 warn("send_delete (remote)");
201 msg.id_num = htonl(local_id);
202 daemon_addr.sin_addr = my_machine_addr;
203 if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
204 (struct sockaddr *)&daemon_addr,
205 sizeof (daemon_addr)) != sizeof (msg))
206 warn("send_delete (local)");
207 }
208