GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/talk/invite.c Lines: 0 64 0.0 %
Date: 2017-11-13 Branches: 0 22 0.0 %

Line Branch Exec Source
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
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
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
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
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
}