~ubuntu-branches/ubuntu/wily/dovecot/wily

« back to all changes in this revision

Viewing changes to src/director/main.c

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2015-05-24 15:01:19 UTC
  • mto: (4.1.53 sid)
  • mto: This revision was merged to the branch mainline in revision 102.
  • Revision ID: package-import@ubuntu.com-20150524150119-hsh6cbr1fqseapga
Tags: upstream-2.2.18
ImportĀ upstreamĀ versionĀ 2.2.18

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
#include "lib.h"
4
4
#include "ioloop.h"
5
5
#include "array.h"
 
6
#include "str.h"
6
7
#include "restrict-access.h"
 
8
#include "process-title.h"
7
9
#include "master-interface.h"
8
10
#include "master-service.h"
9
11
#include "master-service-settings.h"
11
13
#include "doveadm-connection.h"
12
14
#include "login-connection.h"
13
15
#include "notify-connection.h"
 
16
#include "user-directory.h"
14
17
#include "director.h"
15
18
#include "director-host.h"
16
19
#include "director-connection.h"
23
26
#define AUTH_SOCKET_PATH "auth-login"
24
27
#define AUTH_USERDB_SOCKET_PATH "auth-userdb"
25
28
 
 
29
enum director_socket_type {
 
30
        DIRECTOR_SOCKET_TYPE_UNKNOWN = 0,
 
31
        DIRECTOR_SOCKET_TYPE_AUTH,
 
32
        DIRECTOR_SOCKET_TYPE_USERDB,
 
33
        DIRECTOR_SOCKET_TYPE_AUTHREPLY,
 
34
        DIRECTOR_SOCKET_TYPE_RING,
 
35
        DIRECTOR_SOCKET_TYPE_DOVEADM
 
36
};
 
37
 
26
38
static struct director *director;
27
39
static struct notify_connection *notify_conn;
 
40
static struct timeout *to_proctitle_refresh;
 
41
static ARRAY(enum director_socket_type) listener_socket_types;
 
42
 
 
43
static void director_refresh_proctitle_timeout(void *context ATTR_UNUSED)
 
44
{
 
45
        static uint64_t prev_requests = 0, prev_input = 0, prev_output;
 
46
        string_t *str;
 
47
 
 
48
        str = t_str_new(64);
 
49
        str_printfa(str, "[%u users", user_directory_count(director->users));
 
50
        str_printfa(str, ", %lu req/s",
 
51
                    (unsigned long)(director->num_requests - prev_requests));
 
52
        str_printfa(str, ", %llu+%llu kB/s",
 
53
                    (unsigned long long)(director->ring_traffic_input - prev_input)/1024,
 
54
                    (unsigned long long)(director->ring_traffic_output - prev_output)/1024);
 
55
        str_append_c(str, ']');
 
56
 
 
57
        prev_requests = director->num_requests;
 
58
        prev_input = director->ring_traffic_input;
 
59
        prev_output = director->ring_traffic_output;
 
60
 
 
61
        process_title_set(str_c(str));
 
62
}
 
63
 
 
64
static enum director_socket_type
 
65
director_socket_type_get_from_name(const char *path)
 
66
{
 
67
        const char *name, *suffix;
 
68
 
 
69
        name = strrchr(path, '/');
 
70
        if (name == NULL)
 
71
                name = path;
 
72
        else
 
73
                name++;
 
74
 
 
75
        suffix = strrchr(name, '-');
 
76
        if (suffix == NULL)
 
77
                suffix = name;
 
78
        else
 
79
                suffix++;
 
80
 
 
81
        if (strcmp(suffix, "auth") == 0)
 
82
                return DIRECTOR_SOCKET_TYPE_AUTH;
 
83
        else if (strcmp(suffix, "userdb") == 0)
 
84
                return DIRECTOR_SOCKET_TYPE_USERDB;
 
85
        else if (strcmp(suffix, "authreply") == 0)
 
86
                return DIRECTOR_SOCKET_TYPE_AUTHREPLY;
 
87
        else if (strcmp(suffix, "ring") == 0)
 
88
                return DIRECTOR_SOCKET_TYPE_RING;
 
89
        else if (strcmp(suffix, "admin") == 0 ||
 
90
                 strcmp(suffix, "doveadm") == 0)
 
91
                return DIRECTOR_SOCKET_TYPE_DOVEADM;
 
92
        else
 
93
                return DIRECTOR_SOCKET_TYPE_UNKNOWN;
 
94
}
 
95
 
 
96
static enum director_socket_type
 
97
listener_get_socket_type_fallback(const struct director_settings *set,
 
98
                                  int listen_fd)
 
99
{
 
100
        unsigned int local_port;
 
101
 
 
102
        if (net_getsockname(listen_fd, NULL, &local_port) == 0 &&
 
103
            local_port != 0) {
 
104
                /* TCP/IP connection */
 
105
                if (local_port == set->director_doveadm_port)
 
106
                        return DIRECTOR_SOCKET_TYPE_DOVEADM;
 
107
                else
 
108
                        return DIRECTOR_SOCKET_TYPE_RING;
 
109
        }
 
110
        return DIRECTOR_SOCKET_TYPE_AUTH;
 
111
}
 
112
 
 
113
static void listener_sockets_init(const struct director_settings *set,
 
114
                                  struct ip_addr *listen_ip_r,
 
115
                                  unsigned int *listen_port_r)
 
116
{
 
117
        const char *name;
 
118
        unsigned int i, socket_count, port;
 
119
        struct ip_addr ip;
 
120
        enum director_socket_type type;
 
121
 
 
122
        *listen_port_r = 0;
 
123
 
 
124
        i_array_init(&listener_socket_types, 8);
 
125
        socket_count = master_service_get_socket_count(master_service);
 
126
        for (i = 0; i < socket_count; i++) {
 
127
                int listen_fd = MASTER_LISTEN_FD_FIRST + i;
 
128
 
 
129
                name = master_service_get_socket_name(master_service, listen_fd);
 
130
                type = director_socket_type_get_from_name(name);
 
131
                if (type == DIRECTOR_SOCKET_TYPE_UNKNOWN) {
 
132
                        /* mainly for backwards compatibility */
 
133
                        type = listener_get_socket_type_fallback(set, listen_fd);
 
134
                }
 
135
                if (type == DIRECTOR_SOCKET_TYPE_RING && *listen_port_r == 0 &&
 
136
                    net_getsockname(listen_fd, &ip, &port) == 0 && port > 0) {
 
137
                        *listen_ip_r = ip;
 
138
                        *listen_port_r = port;
 
139
                }
 
140
                array_idx_set(&listener_socket_types, listen_fd, &type);
 
141
        }
 
142
}
28
143
 
29
144
static int director_client_connected(int fd, const struct ip_addr *ip)
30
145
{
45
160
{
46
161
        struct auth_connection *auth;
47
162
        const char *socket_path;
48
 
        struct ip_addr ip;
49
 
        unsigned int local_port, len;
 
163
        const enum director_socket_type *typep;
50
164
        bool userdb;
51
165
 
52
166
        if (conn->fifo) {
59
173
                return;
60
174
        }
61
175
 
62
 
        if (net_getpeername(conn->fd, &ip, NULL) == 0 &&
63
 
            net_getsockname(conn->fd, NULL, &local_port) == 0 &&
64
 
            (IPADDR_IS_V4(&ip) || IPADDR_IS_V6(&ip))) {
65
 
                /* TCP/IP connection */
66
 
                if (local_port == director->set->director_doveadm_port) {
 
176
        typep = array_idx(&listener_socket_types, conn->listen_fd);
 
177
        switch (*typep) {
 
178
        case DIRECTOR_SOCKET_TYPE_UNKNOWN:
 
179
                i_unreached();
 
180
        case DIRECTOR_SOCKET_TYPE_AUTH:
 
181
        case DIRECTOR_SOCKET_TYPE_USERDB:
 
182
                /* a) userdb connection, probably for lmtp proxy
 
183
                   b) login connection
 
184
                   Both of them are handled exactly the same, except for which
 
185
                   auth socket they connect to. */
 
186
                userdb = *typep == DIRECTOR_SOCKET_TYPE_USERDB;
 
187
                socket_path = userdb ? AUTH_USERDB_SOCKET_PATH :
 
188
                        AUTH_SOCKET_PATH;
 
189
                auth = auth_connection_init(socket_path);
 
190
                if (auth_connection_connect(auth) < 0) {
 
191
                        auth_connection_deinit(&auth);
 
192
                        break;
 
193
                }
 
194
                master_service_client_connection_accept(conn);
 
195
                (void)login_connection_init(director, conn->fd, auth,
 
196
                        userdb ? LOGIN_CONNECTION_TYPE_USERDB :
 
197
                        LOGIN_CONNECTION_TYPE_AUTH);
 
198
                break;
 
199
        case DIRECTOR_SOCKET_TYPE_AUTHREPLY:
 
200
                master_service_client_connection_accept(conn);
 
201
                (void)login_connection_init(director, conn->fd, NULL,
 
202
                        LOGIN_CONNECTION_TYPE_AUTHREPLY);
 
203
                break;
 
204
        case DIRECTOR_SOCKET_TYPE_RING:
 
205
                if (director_client_connected(conn->fd, &conn->remote_ip) == 0)
67
206
                        master_service_client_connection_accept(conn);
68
 
                        (void)doveadm_connection_init(director, conn->fd);
69
 
                } else {
70
 
                        if (director_client_connected(conn->fd, &ip) == 0)
71
 
                                master_service_client_connection_accept(conn);
72
 
                }
73
 
                return;
74
 
        }
75
 
 
76
 
        len = strlen(conn->name);
77
 
        if (len > 6 && strcmp(conn->name + len - 6, "-admin") == 0) {
78
 
                /* doveadm connection */
 
207
                break;
 
208
        case DIRECTOR_SOCKET_TYPE_DOVEADM:
79
209
                master_service_client_connection_accept(conn);
80
210
                (void)doveadm_connection_init(director, conn->fd);
81
 
                return;
82
 
        }
83
 
 
84
 
        /* a) userdb connection, probably for lmtp proxy
85
 
           b) login connection
86
 
           Both of them are handled exactly the same, except for which
87
 
           auth socket they connect to. */
88
 
        userdb = len > 7 && strcmp(conn->name + len - 7, "-userdb") == 0;
89
 
        socket_path = userdb ? AUTH_USERDB_SOCKET_PATH : AUTH_SOCKET_PATH;
90
 
        auth = auth_connection_init(socket_path);
91
 
        if (auth_connection_connect(auth) == 0) {
92
 
                master_service_client_connection_accept(conn);
93
 
                (void)login_connection_init(director, conn->fd, auth, userdb);
94
 
        } else {
95
 
                auth_connection_deinit(&auth);
96
 
        }
97
 
}
98
 
 
99
 
static unsigned int
100
 
find_inet_listener_port(struct ip_addr *ip_r,
101
 
                        const struct director_settings *set)
102
 
{
103
 
        unsigned int i, socket_count, port;
104
 
 
105
 
        socket_count = master_service_get_socket_count(master_service);
106
 
        for (i = 0; i < socket_count; i++) {
107
 
                int fd = MASTER_LISTEN_FD_FIRST + i;
108
 
 
109
 
                if (net_getsockname(fd, ip_r, &port) == 0 && port > 0 &&
110
 
                    port != set->director_doveadm_port)
111
 
                        return port;
112
 
        }
113
 
        return 0;
 
211
                break;
 
212
        }
114
213
}
115
214
 
116
215
static void director_state_changed(struct director *dir)
145
244
        struct ip_addr listen_ip;
146
245
        unsigned int listen_port;
147
246
 
 
247
        if (master_service_settings_get(master_service)->verbose_proctitle) {
 
248
                to_proctitle_refresh =
 
249
                        timeout_add(1000, director_refresh_proctitle_timeout,
 
250
                                    (void *)NULL);
 
251
        }
148
252
        set = master_service_settings_get_others(master_service)[0];
149
253
 
150
 
        listen_port = find_inet_listener_port(&listen_ip, set);
 
254
        listener_sockets_init(set, &listen_ip, &listen_port);
151
255
        if (listen_port == 0 && *set->director_servers != '\0') {
152
256
                i_fatal("No inet_listeners defined for director service "
153
257
                        "(for standalone keep director_servers empty)");
168
272
 
169
273
static void main_deinit(void)
170
274
{
 
275
        if (to_proctitle_refresh != NULL)
 
276
                timeout_remove(&to_proctitle_refresh);
171
277
        if (notify_conn != NULL)
172
278
                notify_connection_deinit(&notify_conn);
173
279
        director_deinit(&director);
174
280
        doveadm_connections_deinit();
175
281
        login_connections_deinit();
176
282
        auth_connections_deinit();
 
283
        array_free(&listener_socket_types);
177
284
}
178
285
 
179
286
int main(int argc, char *argv[])
183
290
                NULL
184
291
        };
185
292
        const enum master_service_flags service_flags =
186
 
                MASTER_SERVICE_FLAG_NO_IDLE_DIE |
187
 
                MASTER_SERVICE_FLAG_UPDATE_PROCTITLE;
 
293
                MASTER_SERVICE_FLAG_NO_IDLE_DIE;
188
294
        unsigned int test_port = 0;
189
295
        const char *error;
190
296
        bool debug = FALSE;