NetBSD Problem Report #46703
From darrenr@netbsd.org Sat Jul 14 09:49:24 2012
Return-Path: <darrenr@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
by www.NetBSD.org (Postfix) with ESMTP id 7E04863B85F
for <gnats-bugs@gnats.NetBSD.org>; Sat, 14 Jul 2012 09:49:24 +0000 (UTC)
Message-Id: <20120714094924.7023814A5B8@mail.netbsd.org>
Date: Sat, 14 Jul 2012 09:49:24 +0000 (UTC)
From: darrenr@netbsd.org
Reply-To: darrenr@netbsd.org
To: gnats-bugs@gnats.NetBSD.org
Subject: BSD r-commands use wrong source address for stderr
X-Send-Pr-Version: 3.95
>Number: 46703
>Category: bin
>Synopsis: BSD r-commands use wrong source address for stderr
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: bin-bug-people
>State: closed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Jul 14 09:50:00 +0000 2012
>Closed-Date: Sat Jul 14 15:17:27 +0000 2012
>Last-Modified: Sat Jul 14 15:17:27 +0000 2012
>Originator: Darren Reed
>Release: NetBSD 5.99.59
>Organization:
NetBSD
>Environment:
>Description:
The BSD r-commands, rsh, rlogin ,etc, do not use the same IP address
for the outgoing connection for stderr as the local server when running
ona a host with address aliases.
To explain this with an example...
Server A has IP addresses 1.2.3.4 and 1.3.4.5
Client B does "rsh 1.3.4.5 who"
Server A accepts the connection on port 514 for 1.3.4.5 and initiates a
connection back to Client B using IP address 1.2.3.4.
The outgoing connection should use the same IP address as was made for
the incoming TCP connection.
>How-To-Repeat:
>Fix:
--- usr/src/lib/libc/net/rcmd.c.DIST 2011-06-01 02:31:58.000000000 +0200
+++ usr/src/lib/libc/net/rcmd.c 2012-07-14 13:04:06.000000000 +0200
@@ -503,6 +503,12 @@
int
rresvport_af(int *alport, int family)
{
+ return rresvport_af_addr(alport, family, NULL);
+}
+
+int
+rresvport_af_addr(int *alport, int family, void *addr)
+{
struct sockaddr_storage ss;
struct sockaddr *sa;
socklen_t salen;
@@ -519,6 +525,9 @@
sa->sa_len =
#endif
salen = sizeof(struct sockaddr_in);
+ if (addr)
+ ((struct sockaddr_in *)(void *)sa)->sin_addr =
+ ((struct sockaddr_in *)addr)->sin_addr;
portp = &((struct sockaddr_in *)(void *)sa)->sin_port;
break;
#ifdef INET6
@@ -527,6 +536,9 @@
sa->sa_len =
#endif
salen = sizeof(struct sockaddr_in6);
+ if (addr)
+ ((struct sockaddr_in6 *)(void *)sa)->sin6_addr =
+ ((struct sockaddr_in6 *)addr)->sin6_addr;
portp = &((struct sockaddr_in6 *)(void *)sa)->sin6_port;
break;
#endif
--- usr/src/include/unistd.h.DIST 2011-11-05 12:07:00.000000000 +0100
+++ usr/src/include/unistd.h 2012-07-14 13:04:34.000000000 +0200
@@ -371,6 +371,7 @@
int rcmd_af(char **, int, const char *,
const char *, const char *, int *, int);
int rresvport_af(int *, int);
+int rresvport_af_addr(int *, int, void *);
int iruserok_sa(const void *, int, int, const char *, const char *);
#endif
--- usr/src/libexec/rshd/rshd.c.DIST 2011-10-31 04:44:29.000000000 +0100
+++ usr/src/libexec/rshd/rshd.c 2012-07-14 13:10:44.000000000 +0200
@@ -137,7 +137,7 @@
static int log_success; /* If TRUE, log all successful accesses */
static int sent_null;
-__dead static void doit(struct sockaddr *);
+__dead static void doit(struct sockaddr *, struct sockaddr *);
__dead static void rshd_errx(int, const char *, ...) __printflike(2, 3);
static void getstr(char *, int, const char *);
static int local_domain(char *);
@@ -155,7 +155,9 @@
struct linger linger;
int ch, on = 1;
socklen_t fromlen;
+ socklen_t locallen;
struct sockaddr_storage from;
+ struct sockaddr_storage local;
struct protoent *proto;
openlog("rshd", LOG_PID, LOG_DAEMON);
@@ -185,10 +187,16 @@
argv += optind;
fromlen = sizeof(from); /* xxx */
+ locallen = sizeof(local); /* xxx */
if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) {
syslog(LOG_ERR, "getpeername: %m");
return EXIT_FAILURE;
}
+ if (getsockname(STDIN_FILENO, (struct sockaddr *)&local,
+ &locallen) < 0) {
+ syslog(LOG_ERR, "getsockname: %m");
+ return EXIT_FAILURE;
+ }
#if 0
if (((struct sockaddr *)&from)->sa_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr) &&
@@ -232,13 +240,13 @@
proto = getprotobyname("tcp");
(void)setsockopt(STDIN_FILENO, proto->p_proto, TCP_NODELAY, &on,
sizeof(on));
- doit((struct sockaddr *)&from);
+ doit((struct sockaddr *)&from, (struct sockaddr *)&local);
}
extern char **environ;
static void
-doit(struct sockaddr *fromp)
+doit(struct sockaddr *fromp, struct sockaddr *localp)
{
struct passwd *pwd, pwres;
in_port_t port;
@@ -356,7 +364,7 @@
(void) alarm(0);
if (port != 0) {
int lport = IPPORT_RESERVED - 1;
- s = rresvport_af(&lport, af);
+ s = rresvport_af_addr(&lport, af, localp);
if (s < 0) {
syslog(LOG_ERR, "can't get stderr port: %m");
exit(EXIT_FAILURE);
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed
State-Changed-By: darrenr@NetBSD.org
State-Changed-When: Sat, 14 Jul 2012 15:17:27 +0000
State-Changed-Why:
change committed
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.