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 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 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 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 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