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>
index | next in thread | raw e-mail
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. ;-)
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199508061603.SAA07779>
