[net.bugs.4bsd] bug fixes for talk

ricardo@sdcc3.UUCP (Rich Antonorsi{zz32ra) (12/13/84)

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);
+ } 

chris@umcp-cs.UUCP (Chris Torek) (12/14/84)

AARRGH!

*Why* must 90% of the people who "fix" talk use Vax byte order?  Talk
uses UDP; UDP is an *Internet* protocol; there is a *STANDARD* for this
kind of stuff!  Try using ntohl/htonl and ntohs/htons to use *standard
network* byte order.  Then your program will work on *any* new 4.2 Unix
machines, no matter what their internal integer formats are.

(Of course it's not really the fault of people "fixing" talk, it's
the fault of whoever wrote talk wrong in the first place....)
-- 
(This line accidently left nonblank.)

In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland

muller@sdcc3.UUCP (Keith Muller) (12/16/84)

> AARRGH!
> 
> *Why* must 90% of the people who "fix" talk use Vax byte order?  Talk
> uses UDP; UDP is an *Internet* protocol; there is a *STANDARD* for this
> kind of stuff!  Try using ntohl/htonl and ntohs/htons to use *standard
> network* byte order.  Then your program will work on *any* new 4.2 Unix
> machines, no matter what their internal integer formats are.
> 
> (Of course it's not really the fault of people "fixing" talk, it's
> the fault of whoever wrote talk wrong in the first place....)
> -- 
> (This line accidently left nonblank.)
> 
> In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690
> UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
> CSNet:	chris@umcp-cs		ARPA:	chris@maryland


If you look at the posted fix, it clearly stated that it allows unaltered
machines to "talk" to altered machines. A lot of places have machines on
a common ethernet which for adminstrative reasons (you might not have the
source or control over all the machines on your network) cannot be fixed.
Changing some of the machines to network order would break the functionality
of talk.  His fix *DOES NOT* convert to vax order, but detects what order
the packet is in when recieved and converts it if necessary for local
machine usage.

Since the author works for me, I know when he stated:

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

That he made a typo on the line: "transmit in vax order" he really meant
to say "transmit in network order ". The current version he has does use
network order.

	Keith Muller
	UCSD Academic Computer Center

chris@umcp-cs.UUCP (Chris Torek) (12/17/84)

Oh.  Sorry....  I guess I flamed at the wrong person.  (I still stand
by my flame at the author of "talk", though.)
-- 
(This line accidently left nonblank.)

In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland