Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site sdcc3.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!godot!harvard!seismo!hao!hplabs!sdcrdcf!sdcsvax!sdcc3!ricardo From: ricardo@sdcc3.UUCP (Rich Antonorsi{zz32ra) Newsgroups: net.bugs.4bsd,net.unix-wizards Subject: bug fixes for talk Message-ID: <2547@sdcc3.UUCP> Date: Wed, 12-Dec-84 16:40:53 EST Article-I.D.: sdcc3.2547 Posted: Wed Dec 12 16:40:53 1984 Date-Received: Sat, 15-Dec-84 02:22:07 EST Distribution: net Organization: U.C. San Diego, Academic Computer Center Lines: 253 Xref: watmath net.bugs.4bsd:1287 net.unix-wizards:11044 Subject: Talk cannot "talk" accross pyramids, suns and vaxes Index: /usr/src/ucb/talk 4.2BSD Description: The talk command does not work between different machines like suns, vaxes and pyramids. This is a complementary fix to David Goldberg's fix <995@sun.uucp>, that he posted on Apr 28 . Repeat-By: Try talk@vax-machine from a sun or a pyramid. Fix: There are two ways of fixing the problem. One of them is to include the changes shown below to all the machines on your network. These changes will allow your machines to : a ) talk to each other, i.e. all altered vaxes will be able to talk to altered suns and altered pyramids. b ) The change is backward compatible, i.e. altered vaxes and pyramids will be able to talk to unaltered machines of the same type ( pyr->pyr , vax->vax ). NOTE : since padding was added it will make talk between altered suns and unaltered suns incompatible. The other one, not shown here, is to make all pyramids and suns transmit the packets in vax order, i.e. swap the bytes before the packets go out. If you want to implement it all you need to do is use the swap routine in this fix and apply it to the packet before a "sendto" is called. Make sure that if the sendto is within a loop, you flag it to avoid repeated swaps ( otherwise it will cause problems ). There are two important things to consider : first, the way the vax does the swapping is as follows: ------------------------- ----------------------- short : | byte 1 | byte 2 | --> | byte 2 | byte 1 | ------------------------- ----------------------- ------------------------------------- long : | byte 1 | byte 2 | byte 3 | byte 4 | ------------------------------------- ------------------------------------- ---- > | byte 4 | byte 3 | byte 2 | byte 1 | ------------------------------------- Secondly : If you have suns, in the structure for the responses ( file = ctl.h , struct CTL_RESPONSE ), one needs to add a short, since suns don't do word alignment. Here are the changes : *** /tmp/,RCSt1000918 Tue Dec 11 13:54:10 1984 --- ctl.h Tue Dec 11 13:53:27 1984 *************** *** 1,4 ! /* $Header: ctl.h,v 1.1 84/12/11 13:51:31 ricardo Exp $ */ /* ctl.h describes the structure that talk and talkd pass back and forth --- 1,4 ----- ! /* $Header: ctl.h,v 1.2 84/12/11 13:52:40 ricardo Exp $ */ /* ctl.h describes the structure that talk and talkd pass back and forth *************** *** 39,44 struct ctl_response { char type; char answer; int id_num; struct sockaddr_in addr; }; --- 39,47 ----- struct ctl_response { char type; char answer; + #ifdef sun + short junk; /* padding to assure word alignment */ + #endif int id_num; struct sockaddr_in addr; }; *** /tmp/,RCSt1000928 Tue Dec 11 13:55:00 1984 --- look_up.c Mon Dec 10 14:21:02 1984 *************** *** 1,4 ! /* $Header: look_up.c,v 1.1 84/12/10 14:10:11 ricardo Exp $ */ #include "talk_ctl.h" --- 1,4 ----- ! /* $Header: look_up.c,v 1.2 84/12/10 14:19:45 ricardo Exp $ */ #include "talk_ctl.h" *************** *** 7,12 check_local() { CTL_RESPONSE response; /* the rest of msg was set up in get_names */ --- 7,13 ----- check_local() { CTL_RESPONSE response; + CTL_RESPONSE swapresponse(); /* the rest of msg was set up in get_names */ *************** *** 26,31 current_state = "Waiting to connect with caller"; while (connect(sockt, &response.addr, sizeof(response.addr)) != 0) { if (errno == ECONNREFUSED) { --- 27,33 ----- current_state = "Waiting to connect with caller"; + response = swapresponse(response); while (connect(sockt, &response.addr, sizeof(response.addr)) != 0) { if (errno == ECONNREFUSED) { *************** *** 75,78 /* there wasn't an invitation waiting for us */ return(0); } } --- 77,101 ----- /* there wasn't an invitation waiting for us */ return(0); } + } + + /* + * heuristic to detect if need to reshuffle CTL_RESPONSE structure + */ + + #define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff) + #define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16)))) + + CTL_RESPONSE + swapresponse(rsp) + CTL_RESPONSE rsp; + { + CTL_RESPONSE swaprsp; + + if (rsp.addr.sin_family != AF_INET) { + swaprsp = rsp; + rsp.addr.sin_family = swapshort(swaprsp.addr.sin_family); + rsp.id_num = swaplong(swaprsp.id_num); + } + return (rsp); } *** /tmp/,RCSt1000923 Tue Dec 11 13:54:36 1984 --- talkd.c Mon Dec 10 14:17:47 1984 *************** *** 1,4 ! /* $Header: talkd.c,v 1.1 84/12/10 10:28:50 ricardo Exp $ */ /* The top level of the daemon, the format is heavily borrowed from rwhod.c. Basically: find out who and where you are; --- 1,4 ----- ! /* $Header: talkd.c,v 1.2 84/12/10 14:16:42 ricardo Exp $ */ /* The top level of the daemon, the format is heavily borrowed from rwhod.c. Basically: find out who and where you are; *************** *** 40,45 struct servent *sp; struct hostent *hp; if ( argc > 1 ) { debug = 1; --- 40,46 ----- struct servent *sp; struct hostent *hp; + CTL_MSG swapmsg(); if ( argc > 1 ) { *************** *** 104,109 if (debug) printf("Request received : \n"); if (debug) print_request(&request); process_request(&request, &response); if (debug) printf("Response sent : \n"); --- 106,112 ----- if (debug) printf("Request received : \n"); if (debug) print_request(&request); + request = swapmsg(request); process_request(&request, &response); if (debug) printf("Response sent : \n"); *************** *** 191,193 } while (val != pid); } } --- 195,223 ----- } while (val != pid); } } + + #define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff) + #define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16)))) + + /* + * heuristic to detect if need to swap bytes + */ + + CTL_MSG + swapmsg(req) + CTL_MSG req; + { + CTL_MSG swapreq; + + if (req.ctl_addr.sin_family != AF_INET) { + swapreq = req; + swapreq.id_num = swaplong(req.id_num); + swapreq.pid = swaplong(req.pid); + swapreq.addr.sin_family = swapshort(req.addr.sin_family); + swapreq.ctl_addr.sin_family = + swapshort(req.ctl_addr.sin_family); + return (swapreq); + } + else + return (req); + }