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>