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