1/*	$NetBSD$	*/
2
3/*++
4/* NAME
5/*	pass_accept 3
6/* SUMMARY
7/*	start UNIX-domain file descriptor listener
8/* SYNOPSIS
9/*	#include <listen.h>
10/*
11/*	int	pass_accept(listen_fd)
12/*	int	listen_fd;
13/*
14/*	int	pass_accept_attr(listen_fd, attr)
15/*	int	listen_fd;
16/*	HTABLE	**attr;
17/* DESCRIPTION
18/*	This module implements a listener that receives one attribute list
19/*	and file descriptor over each a local connection that is made to it.
20/*
21/*	Arguments:
22/* .IP attr
23/*	Pointer to attribute list pointer.  In case of error, or
24/*	no attributes, the attribute list pointer is set to null.
25/* .IP listen_fd
26/*	File descriptor returned by LOCAL_LISTEN().
27/* DIAGNOSTICS
28/*	Warnings: I/O errors, timeout.
29/* LICENSE
30/* .ad
31/* .fi
32/*	The Secure Mailer license must be distributed with this software.
33/* AUTHOR(S)
34/*	Wietse Venema
35/*	IBM T.J. Watson Research
36/*	P.O. Box 704
37/*	Yorktown Heights, NY 10598, USA
38/*--*/
39
40/* System library. */
41
42#include <sys_defs.h>
43#include <errno.h>
44#include <unistd.h>
45
46/* Utility library. */
47
48#include <msg.h>
49#include <listen.h>
50#include <attr.h>
51
52#define PASS_ACCEPT_TMOUT	100
53
54/* pass_accept - accept descriptor */
55
56int     pass_accept(int listen_fd)
57{
58    const char *myname = "pass_accept";
59    int     accept_fd;
60    int     recv_fd = -1;
61
62    accept_fd = LOCAL_ACCEPT(listen_fd);
63    if (accept_fd < 0) {
64	if (errno != EAGAIN)
65	    msg_warn("%s: cannot accept connection: %m", myname);
66	return (-1);
67    } else {
68	if (read_wait(accept_fd, PASS_ACCEPT_TMOUT) < 0)
69	    msg_warn("%s: timeout receiving file descriptor: %m", myname);
70	else if ((recv_fd = LOCAL_RECV_FD(accept_fd)) < 0)
71	    msg_warn("%s: cannot receive file descriptor: %m", myname);
72	if (close(accept_fd) < 0)
73	    msg_warn("%s: close: %m", myname);
74	return (recv_fd);
75    }
76}
77
78/* pass_accept_attr - accept descriptor and attribute list */
79
80int     pass_accept_attr(int listen_fd, HTABLE **attr)
81{
82    const char *myname = "pass_accept_attr";
83    int     accept_fd;
84    int     recv_fd = -1;
85
86    *attr = 0;
87    accept_fd = LOCAL_ACCEPT(listen_fd);
88    if (accept_fd < 0) {
89	if (errno != EAGAIN)
90	    msg_warn("%s: cannot accept connection: %m", myname);
91	return (-1);
92    } else {
93	if (read_wait(accept_fd, PASS_ACCEPT_TMOUT) < 0)
94	    msg_warn("%s: timeout receiving file descriptor: %m", myname);
95	else if ((recv_fd = LOCAL_RECV_FD(accept_fd)) < 0)
96	    msg_warn("%s: cannot receive file descriptor: %m", myname);
97	else if (read_wait(accept_fd, PASS_ACCEPT_TMOUT) < 0
98	     || recv_pass_attr(accept_fd, attr, PASS_ACCEPT_TMOUT, 0) < 0) {
99	    msg_warn("%s: cannot receive connection attributes: %m", myname);
100	    if (close(recv_fd) < 0)
101		msg_warn("%s: close: %m", myname);
102	    recv_fd = -1;
103	}
104	if (close(accept_fd) < 0)
105	    msg_warn("%s: close: %m", myname);
106	return (recv_fd);
107    }
108}
109