netkit-ntalk (0.17-15) direct (non packaging) changes

Summary

 talk/Makefile       |    3 +
 talk/convert.c      |   46 +++++++++++++++++++++++++
 talk/ctl_transact.c |   93 +++++++++++++++++++++++++++++++++++++++++++++++++---
 talk/talk.1         |    5 ++
 talk/talk.h         |   48 ++++++++++++++++++++++++++
 talkd/Makefile      |    1 
 talkd/announce.c    |    1 
 talkd/table.c       |    2 -
 talkd/talkd.8       |    7 ++-
 talkd/talkd.c       |   81 ++++++++++++++++++++++++++-------------------
 10 files changed, 244 insertions(+), 43 deletions(-)

    
download this patch

Patch contents

--- netkit-ntalk-0.17.orig/talk/Makefile
+++ netkit-ntalk-0.17/talk/Makefile
@@ -6,8 +6,9 @@
 CFLAGS += -I../include
 
 OBJS = ctl.o ctl_transact.o display.o get_addrs.o get_names.o \
-	init_disp.o invite.o io.o look_up.o msgs.o talk.o
+	init_disp.o invite.o io.o look_up.o msgs.o talk.o convert.o
 
+CFLAGS += -DSUN_HACK # -DBAD_LINUX_HACK
 LIBS += $(LIBCURSES)
 
 talk: $(OBJS)
--- netkit-ntalk-0.17.orig/talk/convert.c
+++ netkit-ntalk-0.17/talk/convert.c
@@ -0,0 +1,46 @@
+/*
+ * This routines handle conversions needed to make standard talk/talkd
+ * compatible with Sun's. SunOS/Solaris use a different protocol than
+ * anyone else.
+ *
+ * What we do here is take SunOS' messages and convert them to standard
+ * ones, so that our talk/talkd can manage them without many changes.
+ *
+ * Juan-Mariano de Goyeneche. jmseyas@dit.upm.es
+ * Mon Aug 10 1998
+ */
+
+#ifdef SUN_HACK
+#include <string.h>
+#include "talk.h"
+
+char personality;
+
+void msg2msg_S(const CTL_MSG* msg, CTL_MSG_S* msg_S)
+{
+	msg_S->type = msg->type;
+	strncpy (msg_S->l_name, msg->l_name, NAME_SIZE_S);
+	msg_S->l_name[NAME_SIZE_S - 1] = '\0';
+	strncpy (msg_S->r_name, msg->r_name, NAME_SIZE_S);
+	msg_S->r_name[NAME_SIZE_S - 1] = '\0';
+	msg_S->pad = 0;
+	msg_S->id_num = msg->id_num;
+	msg_S->pid = msg->pid;
+	strncpy (msg_S->r_tty, msg->r_tty, TTY_SIZE);
+	msg_S->r_tty[TTY_SIZE - 1] = '\0';
+	memcpy(&(msg_S->addr), &(msg->addr), sizeof(msg_S->addr));
+/*	if (*(&(msg_S->addr.sa_family)+1) == (short)0)
+		msg_S->addr.sa_family = 0;*/
+	memcpy(&(msg_S->ctl_addr), &(msg->ctl_addr), sizeof(msg_S->ctl_addr));
+}
+
+void resp_S2resp(const CTL_RESPONSE_S* resp_S, CTL_RESPONSE* resp)
+{
+	resp->vers = TALK_VERSION;
+	resp->type = resp_S->type;
+	resp->answer = resp_S->answer;
+	resp->pad = 0;
+	resp->id_num = resp_S->id_num;
+	memcpy(&(resp->addr), &(resp_S->addr), sizeof(resp->addr));
+}
+#endif
--- netkit-ntalk-0.17.orig/talk/talk.1
+++ netkit-ntalk-0.17/talk/talk.1
@@ -139,7 +139,10 @@
 .Bx 4.2
 uses a different and even more braindead protocol that is completely
 incompatible. Some vendor Unixes (particularly those from Sun) have
-been found to use this old protocol.
+been found to use this old protocol. There's a patch from Juan-Mariano de
+Goyeneche (jmseyas@dit.upm.es) which makes talk/talkd, if compiled with 
+-DSUN_HACK, compatible with SunOS/Solaris' ones. It converts messages from
+one protocol to the other.
 .Pp
 Old versions of
 .Nm talk
--- netkit-ntalk-0.17.orig/talk/talk.h
+++ netkit-ntalk-0.17/talk/talk.h
@@ -40,12 +40,56 @@
 
 #include "prot_talkd.h"
 
+#ifdef SUN_HACK
+/*
+ * Personalities: NORMAL --> Normal behaviour; (almost) everybody.
+ *		  SUNOS  --> The rest: SunOS/Solaris.
+ */
+#define P_NORMAL 1
+#define P_SUNOS  2
+
+/*
+ * Client(SunOS)->server request message format.
+ */
+
+typedef struct {
+        u_char  type;           /* request type */
+#define NAME_SIZE_S       9
+        char    l_name[NAME_SIZE_S];/* caller's name */
+        char    r_name[NAME_SIZE_S];/* callee's name */
+        u_char  pad;
+        u_int32_t id_num;       /* message id */
+        int32_t pid;            /* caller's process id */
+        char    r_tty[TTY_SIZE];/* callee's tty name */
+        struct  osockaddr addr;         /* old (4.3) style */
+        struct  osockaddr ctl_addr;     /* old (4.3) style */
+} CTL_MSG_S;
+
+/*
+ * Server(SunOS)->client response message format.
+ */
+typedef struct {
+        u_char  type;           /* type of request message, see below */
+        u_char  answer;         /* response to request message, see below */
+        u_short  pad;
+        u_long id_num;       /* message id */
+        struct  osockaddr addr; /* address for establishing conversation */
+} CTL_RESPONSE_S;
+#endif
+
+
+
 extern int sockt;
 extern int invitation_waiting;
 
 extern const char *current_state;
 extern int current_line;
 
+#ifdef SUN_HACK
+extern char personality;
+#endif
+
+
 void p_error(const char *string);
 void quit(int);
 void message(const char *mesg);
@@ -63,6 +107,10 @@
 void talk(void);
 void send_delete(void);
 void display(int hiswin, unsigned char *, int);
+#ifdef SUN_HACK
+void msg2msg_S(const CTL_MSG *, CTL_MSG_S *);
+void resp_S2resp(const CTL_RESPONSE_S *, CTL_RESPONSE *);
+#endif
 
 void set_my_edit_chars(int ctrlh, int ctrlu, int ctrlw);
 void set_his_edit_chars(int ctrlh, int ctrlu, int ctrlw);
--- netkit-ntalk-0.17.orig/talk/ctl_transact.c
+++ netkit-ntalk-0.17/talk/ctl_transact.c
@@ -45,6 +45,7 @@
 /* #include <netinet/ip.h> looks like this is not needed (no functions used) */
 #include <string.h>
 #include <errno.h>
+#include <netdb.h>
 #include "talk.h"
 
 #define CTL_WAIT 2	/* time to wait for a response, in seconds */
@@ -69,15 +70,16 @@
 	if (to_local_talkd < 0 || to_remote_talkd < 0) {
 		p_error("Bad socket");
 	}
-
-#ifdef SO_BSDCOMPAT
+/* agi: SO_BSDCOMPAT is defined, but obsolete in current kernels
+#ifdef SO_BSDCOMPAT */
 	/* 
 	 * Linux does some async error return stuff that
 	 * really disagrees with us. So we disable it.
 	 */
-	setsockopt(to_local_talkd, SOL_SOCKET, SO_BSDCOMPAT, &on, sizeof(on));
+/*	setsockopt(to_local_talkd, SOL_SOCKET, SO_BSDCOMPAT, &on, sizeof(on));
 	setsockopt(to_remote_talkd, SOL_SOCKET, SO_BSDCOMPAT, &on, sizeof(on));
 #endif
+*/
 
 	/*
 	 * Explicitly talk to the local daemon over loopback.
@@ -120,20 +122,45 @@
 		p_error("getsockname");
 	}
 	local_addr_for_remote = rem.sin_addr.s_addr;
+
+#ifdef SUN_HACK
+	personality = P_NORMAL;
+#endif
 }
 
 static void
 send_packet(CTL_MSG *msg, int sock)
 {
 	int cc;
+#ifdef SUN_HACK
+	CTL_MSG_S msg_S;
+	const void *packet;
+	size_t len;
+
+	if (personality == P_SUNOS) {
+		msg2msg_S(msg, &msg_S);
+		packet = &msg_S;
+		len = sizeof(msg_S);
+	} else {
+		packet = msg;
+		len = sizeof(*msg);
+	}
+
+	cc = send(sock, packet, len, 0);
+#else
 	cc = send(sock, msg, sizeof(*msg), 0);
+#endif
 	if (cc<0 && errno == EINTR) {
 		return;
 	}
 	else if (cc<0) {
 	    p_error("Error on write to talk daemon");
 	}
+#ifdef SUN_HACK
+	else if (((size_t) cc) != len) {
+#else
 	else if (cc != sizeof(*msg)) {
+#endif
 	    p_error("Short write to talk daemon");
 	}
 }
@@ -170,6 +197,36 @@
 	send_packet(&tmp, sock);
 }
 
+#ifdef SUN_HACK
+static void
+reconnect(void)
+{
+	struct sockaddr_in loc, rem;
+
+	daemon_port = getservbyname("talk", "udp")->s_port;
+
+	memset(&loc, 0, sizeof(loc));
+	loc.sin_family = AF_INET;
+	loc.sin_port = daemon_port;
+	loc.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	if (connect(to_local_talkd, (struct sockaddr *)&loc, sizeof(loc))<0) {
+		p_error("Couldn't connect local control socket");
+	}
+
+	memset(&rem, 0, sizeof(rem));
+	rem.sin_family = AF_INET;
+	rem.sin_port = daemon_port;
+	rem.sin_addr = his_machine_addr;
+
+	if (connect(to_remote_talkd, (struct sockaddr *)&rem, sizeof(rem))<0) {
+		p_error("Couldn't connect remote control socket");
+	}
+
+	personality = P_SUNOS;
+}
+#endif
+
 /*
  * SOCKDGRAM is unreliable, so we must repeat messages if we have
  * not received an acknowledgement within a reasonable amount
@@ -192,6 +249,9 @@
 	do {
 		/* resend message until a response is obtained */
 		do {
+#ifdef SUN_HACK
+again:
+#endif
 			send_packet(mesg, sock);
 			read_mask = ctl_mask;
 			wait.tv_sec = CTL_WAIT;
@@ -209,12 +269,35 @@
 		 * request/acknowledgements being sent)
 		 */
 		do {
-			cc = recv(sock, (char *)rp, sizeof (*rp), 0);
+#ifdef SUN_HACK
+			CTL_RESPONSE_S rp_S;
+
+                        if (personality==P_NORMAL)
+#endif
+				cc = recv(sock, (char *)rp,
+					  sizeof (*rp), 0);
+#ifdef SUN_HACK
+                        else
+ 				cc = recv(sock, (char *)&rp_S,
+ 					  sizeof (rp_S), 0);
+#endif
 			if (cc < 0) {
 				if (errno == EINTR)
-					continue;
+					continue;				
+#ifdef SUN_HACK
+				if (errno == ECONNREFUSED &&
+				    personality == P_NORMAL &&
+				    sock == to_remote_talkd) {
+					reconnect();
+					goto again;
+				}
+#endif
 				p_error("Error on read from talk daemon");
 			}
+#ifdef SUN_HACK
+			if (personality==P_SUNOS) 
+				resp_S2resp(&rp_S, rp);
+#endif
 			read_mask = ctl_mask;
 			/* an immediate poll */
 			timerclear(&wait);
--- netkit-ntalk-0.17.orig/talkd/Makefile
+++ netkit-ntalk-0.17/talkd/Makefile
@@ -4,6 +4,7 @@
 include ../MRULES
 
 CFLAGS += -I../include
+LIBS += -lwrap
 
 OBJS = talkd.o announce.o process.o table.o print.o repairs.o
 
--- netkit-ntalk-0.17.orig/talkd/talkd.c
+++ netkit-ntalk-0.17/talkd/talkd.c
@@ -63,11 +63,13 @@
 #include <string.h>
 #include <netdb.h>
 #include <paths.h>
+#include <tcpd.h>
 #include "prot_talkd.h"
 #include "proto.h"
 
 #define TIMEOUT 30
 #define MAXIDLE 120
+#define MINUDPSRCPORT 1024
 
 #if !defined(MAXHOSTNAMELEN)
 #define	MAXHOSTNAMELEN	64
@@ -75,6 +77,10 @@
 char ourhostname[MAXHOSTNAMELEN];
 
 static time_t lastmsgtime;
+#ifndef __USE_GNU
+static char *program_invocation_short_name;
+#endif
+static int quiet;
 
 static void
 timeout(int ignore)
@@ -163,11 +169,16 @@
 	char theirhost[MAXHOSTNAMELEN];
 	const char *theirip;
 
-	struct hostent *hp;
 	struct sockaddr_in sn;
-	int cc, i, ok;
+	struct sockaddr_in server_sin;
+	int cc;
 	socklen_t addrlen;
+ 	int theirport;
+
+	struct request_info request;
 
+	signal(SIGALRM, timeout);
+	alarm(TIMEOUT);
 	addrlen = sizeof(sn);
 	cc = recvfrom(0, inbuf, sizeof(inbuf), 0,
 		      (struct sockaddr *)&sn, &addrlen);
@@ -194,6 +205,12 @@
 		return;
 	}
 
+ 	theirport = ntohs(sn.sin_port);
+ 	if (theirport < MINUDPSRCPORT) {
+		syslog(LOG_WARNING, "%d: bad port", theirport);
+		return;
+	}
+
 	/* 
 	 * If we get here we have an address we can reply to, although
 	 * it may not be good for much. If possible, reply to it, because
@@ -203,38 +220,32 @@
 	theirip = inet_ntoa(sn.sin_addr);
 	mp = (CTL_MSG *)inbuf;
 
-	/*
-	 * Check they're not being weenies.
-	 * We should look into using libwrap here so hosts.deny works.
-	 * Wrapping talkd with tcpd isn't very useful.
-	 */
-	hp = gethostbyaddr((char *)&sn.sin_addr, sizeof(struct in_addr), 
-			   AF_INET);
-	if (hp == NULL) {
-		syslog(LOG_WARNING, "%s: bad dns", theirip);
-		send_reject_packet(mp, &sn, MACHINE_UNKNOWN, 0);
+	addrlen = sizeof(server_sin);
+	if (getsockname(0, (struct sockaddr *)&server_sin, &addrlen)<0) {
+		syslog(LOG_WARNING, "getsockname: %s", strerror(errno));
 		return;
 	}
-	strncpy(theirhost, hp->h_name, sizeof(theirhost));
-	theirhost[sizeof(theirhost)-1] = 0;
-
-	hp = gethostbyname(theirhost);
-	if (hp == NULL) {
-		syslog(LOG_WARNING, "%s: bad dns", theirip);
+	request_init(&request,
+		     RQ_FILE, 0,
+		     RQ_DAEMON, program_invocation_short_name,
+		     RQ_CLIENT_SIN, &sn,
+		     RQ_SERVER_SIN, &server_sin,
+		     0);
+	sock_methods(&request);
+	if (!hosts_access(&request)) {
+		refuse(&request);
 		send_reject_packet(mp, &sn, MACHINE_UNKNOWN, 0);
 		return;
 	}
-
-	for (i=ok=0; hp->h_addr_list[i] && !ok; i++) {
-		if (!memcmp(hp->h_addr_list[i], &sn.sin_addr, 
-			    sizeof(sn.sin_addr))) ok = 1;
-	}
-	if (!ok) {
-		syslog(LOG_WARNING, "%s: bad dns", theirip);
-		send_reject_packet(mp, &sn, MACHINE_UNKNOWN, 0);
-		return;
+	if (!quiet) {
+		syslog(LOG_INFO, "connect from %s", eval_client(&request));
 	}
 
+	signal(SIGALRM, timeout);
+	alarm(TIMEOUT);
+	strncpy(theirhost, eval_hostinfo(request.client), sizeof(theirhost));
+	theirhost[sizeof(theirhost)-1] = 0;
+
 	/*
 	 * Try to straighten out bad packets.
 	 */
@@ -319,11 +330,16 @@
 	socklen_t sz = sizeof(sn);
 	int do_debug=0, do_badpackets=0, ch;
 
+#ifndef __USE_GNU
+	program_invocation_short_name = argv[0];
+	if (argv[0][0] == '/') {
+		program_invocation_short_name = strrchr(argv[0], '/') + 1;
+	}
+#endif
 	/* make sure we're a daemon */
 	if (getsockname(0, (struct sockaddr *)&sn, &sz)) {
-		const char *msg = strerror(errno);
-		write(2, msg, strlen(msg));
-		exit(1);
+		printf ("must be run from inetd.\n");
+		exit (1);
 	}
 	openlog("talkd", LOG_PID, LOG_DAEMON);
 	if (gethostname(ourhostname, sizeof(ourhostname) - 1) < 0) {
@@ -334,16 +350,15 @@
 		syslog(LOG_ERR, "chdir: %s: %s", _PATH_DEV, strerror(errno));
 		exit(1);
 	}
-	while ((ch = getopt(argc, argv, "dp"))!=-1) {
+	while ((ch = getopt(argc, argv, "dpq"))!=-1) {
 		switch (ch) {
 		    case 'd': do_debug=1; break;
 		    case 'p': do_badpackets=1; break;
+		    case 'q': quiet=1; break;
 		}
 	}
 	set_debug(do_debug, do_badpackets);
 
-	signal(SIGALRM, timeout);
-	alarm(TIMEOUT);
 	for (;;) {
 		do_one_packet();
 	}
--- netkit-ntalk-0.17.orig/talkd/table.c
+++ netkit-ntalk-0.17/talkd/table.c
@@ -46,13 +46,13 @@
  * Consider this a mis-guided attempt at modularity
  */
 #include <sys/param.h>
-#include <sys/time.h>
 #include <sys/socket.h>
 #include <syslog.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <netinet/in.h>
 
 #include "prot_talkd.h"
--- netkit-ntalk-0.17.orig/talkd/talkd.8
+++ netkit-ntalk-0.17/talkd/talkd.8
@@ -39,8 +39,8 @@
 .Nm talkd
 .Nd remote user communication server
 .Sh SYNOPSIS
-.Nm talkd
-.Op Fl dp
+.Nm /usr/sbin/in.talkd
+.Op Fl dpq
 .Sh DESCRIPTION
 .Nm Talkd
 is the server that notifies a user that someone else wants to
@@ -76,6 +76,9 @@
 Packet logging mode; writes copies of malformed packets to
 .Pa /var/log/talkd.packets .
 This is useful for debugging interoperability problems.
+.Pp
+.Op Fl q
+Don't log successful connects.
 .Sh SEE ALSO
 .Xr talk 1 ,
 .Xr write 1
--- netkit-ntalk-0.17.orig/talkd/announce.c
+++ netkit-ntalk-0.17/talkd/announce.c
@@ -49,6 +49,7 @@
 #include <fcntl.h>
 #include <string.h>
 #include <paths.h>
+#include <time.h>
 #include "prot_talkd.h"
 #include "proto.h"