-/* $OpenBSD: kcmd.c,v 1.6 1996/10/18 17:17:09 tholo Exp $ */
+/* $OpenBSD: kcmd.c,v 1.7 1997/04/12 19:54:50 rees Exp $ */
/* $NetBSD: kcmd.c,v 1.2 1995/03/21 07:58:32 cgd Exp $ */
/*
static char Xsccsid[] = "derived from @(#)rcmd.c 5.17 (Berkeley) 6/27/88";
static char sccsid[] = "@(#)kcmd.c 8.2 (Berkeley) 8/19/93";
#else
-static char rcsid[] = "$OpenBSD: kcmd.c,v 1.6 1996/10/18 17:17:09 tholo Exp $";
+static char rcsid[] = "$OpenBSD: kcmd.c,v 1.7 1997/04/12 19:54:50 rees Exp $";
#endif
#endif /* not lint */
#define START_PORT 5120 /* arbitrary */
+int getport __P((int *));
+
int
kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm,
cred, schedule, msg_data, laddr, faddr, authopts)
long oldmask;
struct sockaddr_in sin, from;
char c;
-#ifdef ATHENA_COMPAT
int lport = IPPORT_RESERVED - 1;
-#else
- int lport = START_PORT;
-#endif
struct hostent *hp;
int rc;
char *host_save;
oldmask = sigblock(sigmask(SIGURG));
for (;;) {
- s = rresvport(&lport);
+ s = getport(&lport);
if (s < 0) {
if (errno == EAGAIN)
fprintf(stderr,
lport = 0;
} else {
char num[8];
- int s2 = rresvport(&lport), s3;
+ int s2 = getport(&lport), s3;
int len = sizeof(from);
if (s2 < 0) {
sigsetmask(oldmask);
return (status);
}
+
+int
+getport(alport)
+ int *alport;
+{
+ struct sockaddr_in sin;
+ int s;
+
+ /* First try to get a "reserved" [sic] port, for interoperability with
+ broken klogind (aix, e.g.) */
+
+ s = rresvport(alport);
+ if (s >= 0)
+ return s;
+
+ /* Failed; if EACCES, we're not root, so just get an unreserved port
+ and hope that's good enough */
+
+ if (errno != EACCES)
+ return -1;
+
+ if (*alport < IPPORT_RESERVED)
+ *alport = START_PORT;
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ return (-1);
+ for (;;) {
+ sin.sin_port = htons((u_short)*alport);
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ return (s);
+ if (errno != EADDRINUSE) {
+ (void) close(s);
+ return (-1);
+ }
+ (*alport)--;
+ if (*alport == IPPORT_RESERVED) {
+ (void) close(s);
+ errno = EAGAIN; /* close */
+ return (-1);
+ }
+ }
+}