1 /*-
2 * Copyright (c) 1983, 1985
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 /* from "@(#)look_up.c 5.1 (Berkeley) 6/6/85"; */
9
10 #ifndef lint
11 static char sccsid[] = "@(#)look_up.c 6.5 (Berkeley) 04/29/95";
12 #endif not lint
13
14 #include "talk_ctl.h"
15 #include <machine/endian.h>
16 #include <string.h>
17 #include <unistd.h>
18
19 int look_for_invite __P((CTL_RESPONSE *));
20 void swapresponse __P((CTL_RESPONSE *));
21
22 /*
23 * See if the local daemon has a invitation for us
24 */
25 int
check_local()26 check_local()
27 {
28 CTL_RESPONSE response;
29
30 /* the rest of msg was set up in get_names */
31 msg.ctl_addr = ctl_addr;
32 /* must be initiating a talk */
33 if (!look_for_invite(&response))
34 return (0);
35 /*
36 * There was an invitation waiting for us,
37 * so connect with the other (hopefully waiting) party
38 */
39 current_state = "Waiting to connect with caller";
40 again:
41 swapresponse(&response);
42 response.addr.sin_family = AF_INET;
43 if (connect(sockt,
44 (struct sockaddr *)&response.addr, sizeof(response.addr)) != -1)
45 return (1);
46 if (errno == EINTR)
47 goto again;
48 if (errno == ECONNREFUSED) {
49 /*
50 * The caller gave up, but his invitation somehow
51 * was not cleared. Clear it and initiate an
52 * invitation. (We know there are no newer invitations,
53 * the talkd works LIFO.)
54 */
55 ctl_transact(his_machine_addr, msg, DELETE, &response);
56 close(sockt);
57 open_sockt();
58 return (0);
59 }
60 p_error("Unable to connect with initiator");
61 /*NOTREACHED*/
62 }
63
64 /*
65 * Look for an invitation on 'machine'
66 */
67 int
look_for_invite(response)68 look_for_invite(response)
69 CTL_RESPONSE *response;
70 {
71
72 current_state = "Checking for invitation on caller's machine";
73 ctl_transact(his_machine_addr, msg, LOOK_UP, response);
74 /* the switch is for later options, such as multiple invitations */
75 switch (response->answer) {
76
77 case SUCCESS:
78 msg.id_num = response->id_num;
79 return (1);
80
81 default :
82 /* there wasn't an invitation waiting for us */
83 return (0);
84 }
85 }
86
87 /*
88 * heuristic to detect if need to reshuffle CTL_RESPONSE structure
89 */
90
91 #define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff)
92 #define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16))))
93
94 #if BYTE_ORDER == BIG_ENDIAN
95 struct ctl_response_vax {
96 char type;
97 char answer;
98 short junk;
99 int id_num;
100 struct sockaddr_in addr;
101 };
102
103 void
swapresponse(rsp)104 swapresponse(rsp)
105 CTL_RESPONSE *rsp;
106 {
107 struct ctl_response_vax swaprsp;
108
109 if (rsp->addr.sin_family != AF_INET) {
110 bcopy(rsp, &swaprsp, sizeof(CTL_RESPONSE));
111 swaprsp.addr.sin_family = swapshort(swaprsp.addr.sin_family);
112 if (swaprsp.addr.sin_family == AF_INET) {
113 rsp->addr = swaprsp.addr;
114 rsp->type = swaprsp.type;
115 rsp->answer = swaprsp.answer;
116 rsp->id_num = swaplong(swaprsp.id_num);
117 }
118 }
119 }
120 #endif
121
122 #if BYTE_ORDER == LITTLE_ENDIAN
123 struct ctl_response_sun {
124 char type;
125 char answer;
126 unsigned short id_num2;
127 unsigned short id_num1;
128 short sin_family;
129 short sin_port;
130 short sin_addr2;
131 short sin_addr1;
132 };
133
134 void
swapresponse(rsp)135 swapresponse(rsp)
136 CTL_RESPONSE *rsp;
137 {
138 struct ctl_response_sun swaprsp;
139
140 if (rsp->addr.sin_family != AF_INET) {
141 bcopy(rsp, &swaprsp, sizeof(struct ctl_response_sun));
142 if (swaprsp.sin_family == swapshort(AF_INET)) {
143 rsp->type = swaprsp.type;
144 rsp->answer = swaprsp.answer;
145 rsp->id_num = swapshort(swaprsp.id_num1)
146 | (swapshort(swaprsp.id_num2) << 16);
147 rsp->addr.sin_family = swapshort(swaprsp.sin_family);
148 rsp->addr.sin_port = swaprsp.sin_port;
149 rsp->addr.sin_addr.s_addr =
150 swaprsp.sin_addr2 | (swaprsp.sin_addr1 << 16);
151 }
152 }
153 }
154 #endif
155