~ubuntu-branches/ubuntu/saucy/postfix/saucy

« back to all changes in this revision

Viewing changes to src/util/upass_listen.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2011-02-22 11:20:43 UTC
  • mfrom: (1.1.27 upstream)
  • Revision ID: james.westby@ubuntu.com-20110222112043-c34ht219w3ybrilr
Tags: 2.8.0-2
* a little more lintian cleanup
* Fix missing format strings in smtp-sink.c

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*++
2
 
/* NAME
3
 
/*      upass_listen 3
4
 
/* SUMMARY
5
 
/*      start UNIX-domain file descriptor listener
6
 
/* SYNOPSIS
7
 
/*      #include <listen.h>
8
 
/*
9
 
/*      int     upass_listen(path, backlog, block_mode)
10
 
/*      const char *path;
11
 
/*      int     backlog;
12
 
/*      int     block_mode;
13
 
/*
14
 
/*      int     upass_accept(fd)
15
 
/*      int     fd;
16
 
/* DESCRIPTION
17
 
/*      This module implements a listener that receives one file descriptor
18
 
/*      across each UNIX-domain connection that is made to it.
19
 
/*
20
 
/*      upass_listen() creates a listener endpoint with the specified
21
 
/*      permissions, and returns a file descriptor to be used for accepting
22
 
/*      descriptors.
23
 
/*
24
 
/*      upass_accept() accepts a descriptor.
25
 
/*
26
 
/*      Arguments:
27
 
/* .IP path
28
 
/*      Null-terminated string with connection destination.
29
 
/* .IP backlog
30
 
/*      This argument exists for compatibility and is ignored.
31
 
/* .IP block_mode
32
 
/*      Either NON_BLOCKING or BLOCKING. This does not affect the
33
 
/*      mode of accepted connections.
34
 
/* .IP fd
35
 
/*      File descriptor returned by upass_listen().
36
 
/* DIAGNOSTICS
37
 
/*      Fatal errors: upass_listen() aborts upon any system call failure.
38
 
/*      upass_accept() leaves all error handling up to the caller.
39
 
/* LICENSE
40
 
/* .ad
41
 
/* .fi
42
 
/*      The Secure Mailer license must be distributed with this software.
43
 
/* AUTHOR(S)
44
 
/*      Wietse Venema
45
 
/*      IBM T.J. Watson Research
46
 
/*      P.O. Box 704
47
 
/*      Yorktown Heights, NY 10598, USA
48
 
/*--*/
49
 
 
50
 
/* System library. */
51
 
 
52
 
#include <sys_defs.h>
53
 
#include <sys/socket.h>
54
 
#include <errno.h>
55
 
#include <unistd.h>
56
 
 
57
 
/* Utility library. */
58
 
 
59
 
#include <msg.h>
60
 
#include <sane_accept.h>
61
 
#include <listen.h>
62
 
 
63
 
/* upass_accept - accept descriptor */
64
 
 
65
 
int     upass_accept(int listen_fd)
66
 
{
67
 
    const char *myname = "upass_accept";
68
 
    int     accept_fd;
69
 
    int     recv_fd = -1;
70
 
 
71
 
    accept_fd = sane_accept(listen_fd, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0);
72
 
    if (accept_fd < 0) {
73
 
        if (errno != EAGAIN)
74
 
            msg_warn("%s: accept connection: %m", myname);
75
 
        return (-1);
76
 
    } else {
77
 
        if (read_wait(accept_fd, 100) < 0)
78
 
            msg_warn("%s: timeout receiving file descriptor: %m", myname);
79
 
        else if ((recv_fd = unix_recv_fd(accept_fd)) < 0)
80
 
            msg_warn("%s: cannot receive file descriptor: %m", myname);
81
 
        if (close(accept_fd) < 0)
82
 
            msg_warn("%s: close: %m", myname);
83
 
        return (recv_fd);
84
 
    }
85
 
}
86
 
 
87
 
#if 0
88
 
 
89
 
/* System library. */
90
 
 
91
 
#include <sys_defs.h>
92
 
 
93
 
/* Utility library. */
94
 
 
95
 
#include <msg.h>
96
 
#include <events.h>
97
 
#include <sane_accept.h>
98
 
#include <iostuff.h>
99
 
#include <listen.h>
100
 
 
101
 
 /*
102
 
  * It would be nice if a client could make one UNIX-domain connection to a
103
 
  * Postfix master service, send multiple descriptors, and have each
104
 
  * descriptor handled by the first available child process.
105
 
  * 
106
 
  * Possible solutions:
107
 
  * 
108
 
  * - Either the master process accepts the UNIX-domain connection and forwards
109
 
  * each descriptor sent by the client to the first available child process.
110
 
  * That's what the code below does. Unfortunately, this approach is
111
 
  * inconsistent with the Postfix architecture which tries to eliminate the
112
 
  * master from connection management as much as possible.
113
 
  * 
114
 
  * - Or one child processes accepts the UNIX-domain connection and sends a
115
 
  * shared socketpair half to the client. The other socketpair half is shared
116
 
  * with the master and all the child's siblings. The client then sends its
117
 
  * descriptors over the socketpair, and each descriptor is available to any
118
 
  * child process that is waiting for work.
119
 
  * 
120
 
  * If the second solution did not use a shared socketpair, then all the
121
 
  * client's descriptors would be available only to the child process that
122
 
  * accepted the UNIX-domain connection. That results in poor performance.
123
 
  * 
124
 
  * Unfortunately, having to receive a descriptor before being able to send one
125
 
  * or more descriptors is ugly from the client's point of view.
126
 
  */
127
 
 
128
 
#define upass_accept(fd)        unix_recv_fd(fd)
129
 
 
130
 
/* upass_plumbing - operate the hidden descriptor passing machinery */
131
 
 
132
 
static void upass_plumbing(int unused_event, char *context)
133
 
{
134
 
    const char *myname = "upass_plumbing";
135
 
    UPASS_INFO *info = (UNIX_UPASS_INFO *) context;
136
 
    int     fd;
137
 
 
138
 
    /*
139
 
     * Each time a client connects to the hidden UNIX-domain socket, call
140
 
     * unix_send_fd() to send one half of the hidden socketpair across a
141
 
     * short-lived UNIX-domain connection. Wait until the client closes the
142
 
     * UNIX-domain connection before closing the connection. This wait needs
143
 
     * to be time limited.
144
 
     */
145
 
    fd = sane_accept(info->unixsock, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0);
146
 
    if (fd < 0) {
147
 
        if (errno != EAGAIN)
148
 
            msg_fatal("%s: accept connection: %m", myname);
149
 
    } else {
150
 
        if (unix_send_fd(fd, info->halfpair) < 0)
151
 
            msg_warn("%s: cannot send file descriptor: %m", myname);
152
 
        if (read_wait(fd, 5) < 0)
153
 
            msg_warn("%s: read timeout", myname);
154
 
        if (close(fd) < 0)
155
 
            msg_warn("%s: close: %m", myname);
156
 
    }
157
 
}
158
 
 
159
 
/* upass_listen - set up hidden descriptor passing machinery */
160
 
 
161
 
int     upass_listen(const char *path, int backlog, int blocking, UPASS_INFO **ip)
162
 
{
163
 
    int     pair[2];
164
 
    UPASS_INFO *info;
165
 
 
166
 
    /*
167
 
     * Create a UNIX-domain socket with unix_listen() and create a
168
 
     * socketpair. One socketpair half is returned to the caller. The other
169
 
     * half is part of the hidden machinery, together with the UNIX-domain
170
 
     * socket.
171
 
     */
172
 
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0)
173
 
        msg_fatal("socketpair: %m");
174
 
    info = (UPASS_INFO *) mymalloc(sizeof(*info));
175
 
    info->halfpair = pair[0];
176
 
    info->unixsock = unix_listen(path, backlog, blocking);
177
 
    event_request_read(info->unixsock, upass_plumbing, (char *) info);
178
 
    *ip = info;
179
 
    return (pair[1]);
180
 
}
181
 
 
182
 
/* upass_shutdown - tear down hidden descriptor passing machinery */
183
 
 
184
 
void    upass_shutdown(UPASS_INFO *info)
185
 
{
186
 
    event_disable_readwrite(upass_info->unixsock)
187
 
    if (close(info->unixsock) < 0)
188
 
        msg_warn("%s: close unixsock: %m", myname);
189
 
    if (close(info->halfpair) < 0)
190
 
        msg_warn("%s: close halfpair: %m", myname);
191
 
    myfree((char *) info);
192
 
}
193
 
 
194
 
#endif