Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 Aug 1995 18:03:27 +0200 (MET DST)
From:      J Wunsch <j@uriah.heep.sax.de>
To:        freebsd-current@FreeBSD.org (FreeBSD-current users)
Subject:   workaround for talk's address problem
Message-ID:  <199508061603.SAA07779@uriah.heep.sax.de>

next in thread | raw e-mail | index | archive | help
talk(1) has problems with multi-homed hosts.  To negotiate the
connection with the remote peer, it uses the first address as returned
by a call to gethostbyname().  This will cause the connection to hang
for machines where not all interfaces are reachable from the Internet.
This is often the case for the typical dialup user: he's got a SLIP
interface with (e.g.) 111.222.111.33, and an ethernet interface with
192.168.3.4.  The call to gethostbyname() will cause the name server
to return 192.168.3.4 as the first address (since the name server
believes this is the `most local' one), so talk will only be able to
contact hosts inside the (not externally routed) 192.168.3 network.

The correct solution would be asking the routing socket to see which
interface address must be used to get in contact with the remote peer.
Unfortunately, the interface to the routing socket is somewhat ugly to
use and it requires root privileges.  Hence i'm suggesting the
following workaround.  It introduces an option `-a' followed by a
(dotted-quad) address to use for the negotiation.  This address will
be checked against the address list as returned from gethostbyname()
to avoid abusing foreign addresses.

If nobody objects (or promises to implement the routing socket
scenario), i'd going to commit this change.

Index: talk/get_addrs.c
===================================================================
RCS file: /home/cvs/src/usr.bin/talk/get_addrs.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 get_addrs.c
--- 1.1.1.1	1994/05/27 12:32:46
+++ get_addrs.c	1995/08/06 13:38:08
@@ -43,8 +43,9 @@
 #include <stdio.h>
 #include "talk_ctl.h"
 
-get_addrs(my_machine_name, his_machine_name)
+get_addrs(my_machine_name, his_machine_name, my_addr)
 	char *my_machine_name, *his_machine_name;
+	char *my_addr;
 {
 	struct hostent *hp;
 	struct servent *sp;
@@ -57,7 +58,29 @@
 		herror((char *)NULL);
 		exit(-1);
 	}
-	bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length);
+	if(my_addr == 0)
+		bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length);
+	else {
+		int i;
+		for(i = 0; hp->h_addr_list[i]; i++) {
+			bcopy(hp->h_addr_list[i], (char *)&my_machine_addr,
+			      hp->h_length);
+			if(memcmp((char *)&my_machine_addr,
+				  my_addr,
+				  hp->h_length) == 0)
+				break;
+		}
+		if(hp->h_addr_list[i] == 0) {
+			fprintf(stderr,
+				"talk: can't find address %d.%d.%d.%d "
+				"in this host's address list\n",
+				(unsigned char)my_addr[0],
+				(unsigned char)my_addr[1],
+				(unsigned char)my_addr[2],
+				(unsigned char)my_addr[3]);
+			exit(-1);
+		}
+	}
 	/*
 	 * If the callee is on-machine, just copy the
 	 * network address, otherwise do a lookup...
Index: talk/get_names.c
===================================================================
RCS file: /home/cvs/src/usr.bin/talk/get_names.c,v
retrieving revision 1.3
diff -u -r1.3 get_names.c
--- 1.3	1994/10/24 05:42:33
+++ get_names.c	1995/08/06 13:34:06
@@ -39,12 +39,14 @@
 #include <sys/socket.h>
 #include <protocols/talkd.h>
 #include <pwd.h>
+#include <string.h>
+#include <stdlib.h>
 #include "talk.h"
 
 char	*getlogin();
 char	*ttyname();
-char	*rindex();
 extern	CTL_MSG msg;
+static	char *convaddr(char *a);
 
 /*
  * Determine the local and remote user, tty, and machines
@@ -56,10 +58,22 @@
 	char hostname[MAXHOSTNAMELEN];
 	char *his_name, *my_name;
 	char *my_machine_name, *his_machine_name;
-	char *my_tty, *his_tty;
+	char *my_tty, *his_tty, *my_address = 0;
 	register char *cp;
+	int c, errs = 0;
 
-	if (argc < 2 ) {
+	while ((c = getopt(argc, argv, "a:")) != EOF)
+		switch (c) {
+		case 'a':
+			my_address = optarg;
+			break;
+
+		default:
+			errs++;
+		}
+	argc -= optind - 1;
+	argv += optind - 1;
+	if (errs || argc < 2 ) {
 		printf("Usage: talk user [ttyname]\n");
 		exit(-1);
 	}
@@ -101,7 +115,11 @@
 		his_tty = argv[2];	/* tty name is arg 2 */
 	else
 		his_tty = "";
-	get_addrs(my_machine_name, his_machine_name);
+	if (my_address)
+		get_addrs(my_machine_name, his_machine_name,
+			  convaddr(my_address));
+	else
+		get_addrs(my_machine_name, his_machine_name, 0);
 	/*
 	 * Initialize the message template.
 	 */
@@ -115,4 +133,30 @@
 	msg.r_name[NAME_SIZE - 1] = '\0';
 	strncpy(msg.r_tty, his_tty, TTY_SIZE);
 	msg.r_tty[TTY_SIZE - 1] = '\0';
+}
+
+static char *
+convaddr(char *a)
+{
+	char *dot1, *dot2, *dot3;
+	static int addr;
+	
+	/* convert dotted quad into network byte-ordered numerical addr */
+	if((dot1 = strchr(a, '.')) == NULL)
+		return 0;
+	*dot1 = 0;
+	dot1++;
+	if((dot2 = strchr(dot1, '.')) == NULL)
+		return 0;
+	*dot2 = 0;
+	dot2++;
+	if((dot3 = strchr(dot2, '.')) == NULL)
+		return 0;
+	*dot3 = 0;
+	dot3++;
+	addr = (atoi(a) & 0xff) +
+		((atoi(dot1) << 8) & 0xff00) +
+		((atoi(dot2) << 16) & 0xff0000) +
+		((atoi(dot3) << 24) & 0xff000000);
+	return (char *)&addr;
 }
Index: talk/talk.1
===================================================================
RCS file: /home/cvs/src/usr.bin/talk/talk.1,v
retrieving revision 1.2
diff -u -r1.2 talk.1
--- 1.2	1994/10/24 05:42:34
+++ talk.1	1995/08/06 15:26:22
@@ -39,6 +39,7 @@
 .Nd talk to another user
 .Sh SYNOPSIS
 .Nm talk
+.Op Fl a Ar address
 .Ar person
 .Op Ar ttyname
 .Sh DESCRIPTION
@@ -48,6 +49,15 @@
 .Pp
 Options available:
 .Bl -tag -width ttyname
+.It Fl a Ar address
+The address to use for this machine when negotiating the connection to
+a remote host.  Default is to use the first address found
+.Pq see Xr gethostbyname 3
+which might cause problems on multi-homed hosts.  The
+.Ar address
+must be in dotted-quad notation.  It will be checked against the list
+of addresses available for this machine, in order to prevent abusing
+foreign addresses.
 .It Ar person
 If you wish to talk to someone on your own machine, then
 .Ar person
@@ -117,7 +127,8 @@
 .Xr mail 1 ,
 .Xr mesg 1 ,
 .Xr who 1 ,
-.Xr write 1
+.Xr write 1 ,
+.Xr gethostbyname 3 .
 .Sh BUGS
 The version of
 .Xr talk 1


-- 
cheers, J"org

joerg_wunsch@uriah.heep.sax.de -- http://www.sax.de/~joerg/
Never trust an operating system you don't have sources for. ;-)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199508061603.SAA07779>