--- 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"