Annotation of src/usr.bin/talk/invite.c, Revision 1.16
1.16 ! mestre 1: /* $OpenBSD: invite.c,v 1.15 2013/03/11 17:40:11 deraadt 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:
1.16 ! mestre 33: #include <sys/socket.h>
1.5 pjanzen 34: #include <arpa/inet.h>
1.16 ! mestre 35:
! 36: #include <err.h>
! 37: #include <errno.h>
1.4 pjanzen 38: #include <netdb.h>
1.1 deraadt 39: #include <setjmp.h>
1.5 pjanzen 40: #include <unistd.h>
1.16 ! mestre 41:
! 42: #include "talk.h"
1.1 deraadt 43: #include "talk_ctl.h"
44:
1.4 pjanzen 45: #define STRING_LENGTH 158
46:
1.1 deraadt 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
1.6 millert 50: * him
1.1 deraadt 51: */
52:
53: /*
54: * The msg.id's for the invitations
55: * on the local and remote machines.
1.6 millert 56: * These are used to delete the
1.1 deraadt 57: * invitations.
58: */
59: int local_id, remote_id;
60: jmp_buf invitebuf;
61:
1.5 pjanzen 62: void
1.10 deraadt 63: invite_remote(void)
1.1 deraadt 64: {
1.5 pjanzen 65: int new_sockt;
1.1 deraadt 66: struct itimerval itimer;
67: CTL_RESPONSE response;
1.4 pjanzen 68: struct sockaddr rp;
1.12 tedu 69: socklen_t rplen = sizeof(struct sockaddr);
1.4 pjanzen 70: struct hostent *rphost;
71: char rname[STRING_LENGTH];
1.1 deraadt 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)
1.7 millert 77: quit("Error on attempt to listen for caller", 1);
1.1 deraadt 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,
1.4 pjanzen 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().
1.1 deraadt 94: */
95: end_msgs();
96: setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
97: message("Waiting for your party to respond");
98: signal(SIGALRM, re_invite);
99: (void) setjmp(invitebuf);
1.12 tedu 100: while ((new_sockt = accept(sockt, &rp, &rplen)) == -1) {
1.15 deraadt 101: if (errno == EINTR || errno == EWOULDBLOCK ||
102: errno == ECONNABORTED)
1.1 deraadt 103: continue;
1.7 millert 104: quit("Unable to connect with your party", 1);
1.1 deraadt 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;
1.4 pjanzen 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: }
1.1 deraadt 137: }
138:
139: /*
1.13 krw 140: * Routine called on interrupt to re-invite the callee
1.1 deraadt 141: */
142: void
1.10 deraadt 143: re_invite(int dummy)
1.1 deraadt 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: };
1.5 pjanzen 163: #define NANSWERS (sizeof (answers) / sizeof (answers[0]))
1.1 deraadt 164:
165: /*
166: * Transmit the invitation and process the response
167: */
1.5 pjanzen 168: void
1.10 deraadt 169: announce_invite(void)
1.1 deraadt 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;
1.7 millert 176: if (response.answer != SUCCESS)
177: quit(response.answer < NANSWERS ? answers[response.answer] : NULL, 0);
1.1 deraadt 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: */
1.5 pjanzen 186: void
1.10 deraadt 187: send_delete(void)
1.1 deraadt 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))
1.6 millert 200: warn("send_delete (remote)");
1.1 deraadt 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))
1.6 millert 206: warn("send_delete (local)");
1.1 deraadt 207: }