summaryrefslogtreecommitdiff
path: root/libexec/identd
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2008-05-24 02:33:06 +0000
committerBrad Smith <brad@cvs.openbsd.org>2008-05-24 02:33:06 +0000
commit17597ad2afb50133e284a84457ec06bc53022b22 (patch)
treebd4f8843e97f14aea5fd4f4471a5ef28fb79204a /libexec/identd
parentb0f752a0ce0c5ad015409dbc9546ec714c1eed10 (diff)
IPv6 support for standalone mode with assistance from millert@ and deraadt@
Tested by brad@ and sobrado@ ok deraadt@
Diffstat (limited to 'libexec/identd')
-rw-r--r--libexec/identd/identd.818
-rw-r--r--libexec/identd/identd.c170
2 files changed, 121 insertions, 67 deletions
diff --git a/libexec/identd/identd.8 b/libexec/identd/identd.8
index 1d061ed65a1..95f70729442 100644
--- a/libexec/identd/identd.8
+++ b/libexec/identd/identd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: identd.8,v 1.26 2007/09/25 14:21:30 jmc Exp $
+.\" $OpenBSD: identd.8,v 1.27 2008/05/24 02:33:05 brad Exp $
.\"
.\" Copyright (c) 1997, Jason Downs. All rights reserved.
.\"
@@ -27,7 +27,7 @@
.\" Copyright (c) 1992 Peter Eriksson, Lysator, Linkoping University.
.\" This software has been released into the public domain.
.\"
-.Dd $Mdocdate: September 25 2007 $
+.Dd $Mdocdate: May 24 2008 $
.Dt IDENTD 8
.Os
.Sh NAME
@@ -36,7 +36,7 @@
.Sh SYNOPSIS
.Nm identd
.Bk -words
-.Op Fl dehlmNnoUv
+.Op Fl 46dehlmNnoUv
.Op Fl b | i | w
.Op Fl a Ar address
.Op Fl c Ar charset
@@ -58,6 +58,18 @@ process owning the connection.
.Pp
The options are as follows:
.Bl -tag -width Ds
+.It Fl 4
+When
+.Fl b
+is specified, forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+When
+.Fl b
+is specified, forces
+.Nm
+to use IPv6 addresses only.
.It Fl a Ar address
Specify a local IP address in dotted quad format
to bind the listen socket to if running as a stand-alone daemon.
diff --git a/libexec/identd/identd.c b/libexec/identd/identd.c
index 738e7e11b9f..821dfaf1058 100644
--- a/libexec/identd/identd.c
+++ b/libexec/identd/identd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: identd.c,v 1.46 2007/09/26 02:46:29 ray Exp $ */
+/* $OpenBSD: identd.c,v 1.47 2008/05/24 02:33:05 brad Exp $ */
/*
* This program is in the public domain and may be used freely by anyone
@@ -37,6 +37,8 @@
extern char *__progname;
+int af = PF_UNSPEC;
+
int verbose_flag;
int debug_flag;
int syslog_flag;
@@ -65,7 +67,7 @@ void
usage(void)
{
syslog(LOG_ERR,
- "usage: %s [-dehlmNnoUv] [-b | -i | -w] [-a address] [-c charset] "
+ "usage: %s [-46dehlmNnoUv] [-b | -i | -w] [-a address] [-c charset] "
"[-g gid] [-p port] [-t seconds] [-u uid]", __progname);
exit(2);
}
@@ -143,14 +145,14 @@ int
main(int argc, char *argv[])
{
struct sockaddr_storage sa, sa2;
- /* struct sockaddr_in sin;*/
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct in_addr laddr, faddr;
struct in6_addr laddr6, faddr6;
struct passwd *pwd;
struct group *grp;
- int background_flag = 0, timeout = 0, ch;
+ struct pollfd *pfds = NULL;
+ int i, n = 0, background_flag = 0, timeout = 0, ch;
char *portno = "auth";
char *bind_address = NULL;
uid_t set_uid = 0;
@@ -175,8 +177,14 @@ main(int argc, char *argv[])
/*
* Parse the command line arguments
*/
- while ((ch = getopt(argc, argv, "hHbwit:p:a:u:g:c:loenvdmNU")) != -1) {
+ while ((ch = getopt(argc, argv, "46hHbwit:p:a:u:g:c:loenvdmNU")) != -1) {
switch (ch) {
+ case '4':
+ af = AF_INET;
+ break;
+ case '6':
+ af = AF_INET6;
+ break;
case 'h':
token_flag = 1;
break;
@@ -271,54 +279,81 @@ main(int argc, char *argv[])
* Do the special handling needed for the "-b" flag
*/
if (background_flag == 1) {
- struct sockaddr_in addr;
- struct servent *sp;
- int fd;
+ struct addrinfo hints, *res, *res0;
+ int true = 1;
if (daemon(0, 0) != 0)
exit(0);
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd == -1)
- error("main: socket");
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = af;
+ hints.ai_flags = AI_PASSIVE;
+ if (getaddrinfo(bind_address, portno, &hints, &res0) != 0)
+ error("main: getaddrinfo");
+
+ i = 0;
+ for (res = res0; res; res = res->ai_next)
+ i++;
+
+ pfds = calloc(i, sizeof(pfds[0]));
+ if (!pfds) {
+ freeaddrinfo(res0);
+ error("main: calloc");
+ }
+
+ i = 0;
+ for (res = res0; res; res = res->ai_next) {
+ if ((pfds[i].fd = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol)) < 0)
+ continue;
- if (fd != 0)
- dup2(fd, 0);
-
- memset(&addr, 0, sizeof(addr));
-
- addr.sin_len = sizeof(struct sockaddr_in);
- addr.sin_family = AF_INET;
- if (bind_address == NULL)
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- else {
- if (inet_aton(bind_address, &addr.sin_addr) == 0) {
- struct hostent *hp;
-
- hp = gethostbyname(bind_address);
- if (!hp)
- error("no such address (%s) for -a switch",
- bind_address);
- memcpy(&addr.sin_addr, hp->h_addr,
- sizeof(addr.sin_addr));
+ if (setsockopt(pfds[i].fd, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&true, sizeof(true))) {
+ close(pfds[i].fd);
+ continue;
}
- }
- if (isdigit(portno[0]))
- addr.sin_port = htons(atoi(portno));
- else {
- sp = getservbyname(portno, "tcp");
- if (sp == NULL)
- error("main: getservbyname: %s", portno);
- addr.sin_port = sp->s_port;
+#ifdef IPV6_V6ONLY
+ if (res->ai_family == AF_INET6)
+ (void)setsockopt(pfds[i].fd, IPPROTO_IPV6,
+ IPV6_V6ONLY, (void *)&true, sizeof(true));
+#endif
+
+ if (bind(pfds[i].fd, res->ai_addr, res->ai_addrlen)) {
+ close(pfds[i].fd);
+ continue;
+ }
+
+ if (listen(pfds[i].fd, 3)) {
+ close(pfds[i].fd);
+ continue;
+ }
+
+ pfds[i].events = POLLIN;
+ i++;
}
+ freeaddrinfo(res0);
- if (bind(0, (struct sockaddr *) &addr, sizeof(addr)) < 0)
- error("main: bind");
+ if (i == 0)
+ error("main: socket");
- if (listen(0, 3) < 0)
- error("main: listen");
+ n = i;
}
+
+ /*
+ * Do the special handling needed for the "-w" flag
+ */
+ if (background_flag == 2) {
+ pfds = calloc(1, sizeof(pfds[0]));
+ if (!pfds)
+ error("main: calloc");
+
+ pfds[0].fd = 0;
+ pfds[0].events = POLLIN;
+ n = 1;
+ }
+
if (set_gid) {
if (setegid(set_gid) == -1)
error("main: setegid");
@@ -331,12 +366,12 @@ main(int argc, char *argv[])
if (setuid(set_uid) == -1)
error("main: setuid");
}
+
/*
* Do some special handling if the "-b" or "-w" flags are used
*/
if (background_flag) {
- int nfds, fd;
- struct pollfd pfd[1];
+ int fd = 0;
signal(SIGCHLD, sigchld);
@@ -364,25 +399,22 @@ main(int argc, char *argv[])
exit(0);
}
- pfd[0].fd = 0;
- pfd[0].events = POLLIN;
-
if (timeout)
- nfds = poll(pfd, 1, timeout * 1000);
+ i = poll(pfds, n, timeout * 1000);
else
- nfds = poll(pfd, 1, INFTIM);
- } while (nfds < 0 && errno == EINTR);
+ i = poll(pfds, n, INFTIM);
+ } while (i < 0 && errno == EINTR);
/*
* An error occurred in poll? Just die
*/
- if (nfds < 0)
+ if (i < 0)
error("main: poll");
/*
* Timeout limit reached. Exit nicely
*/
- if (nfds == 0)
+ if (i == 0)
exit(0);
/*
@@ -390,18 +422,27 @@ main(int argc, char *argv[])
*/
alarm(0);
- /*
- * Accept the new client
- */
- fd = accept(0, NULL, NULL);
- if (fd == -1)
- error("main: accept. errno = %d", errno);
+ for (i = 0; i < n; i++) {
+ if ((pfds[i].revents & POLLIN) == 0)
+ continue;
+
+ /*
+ * Accept the new client
+ */
+ fd = accept(pfds[i].fd, NULL, NULL);
+ if (fd == -1)
+ error("main: accept. errno = %d", errno);
+
+ /*
+ * Fork a child, parent continues
+ */
+ child_pid = fork();
+ if (child_pid == 0)
+ break;
- /*
- * And fork, then close the fd if we are the parent.
- */
- child_pid = fork();
- } while (child_pid && (close(fd), 1));
+ close(fd);
+ }
+ } while (child_pid != 0);
/*
* We are now in child, the parent has returned to "do" above.
@@ -415,6 +456,7 @@ main(int argc, char *argv[])
if (dup2(fd, 2) == -1)
error("main: dup2: failed fd 2");
}
+
/*
* Get foreign internet address
*/
@@ -455,7 +497,7 @@ main(int argc, char *argv[])
*/
exit(1);
}
- /* are we V4 or V6? */
+ /* are we v4 or v6? */
if (sa2.ss_family == AF_INET6) {
sin6 = (struct sockaddr_in6 *)&sa2;
laddr6 = sin6->sin6_addr;