Klaus Demo nginx / 4545046
resolver in smtp proxy module Igor Sysoev 14 years ago
5 changed file(s) with 244 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
8080 ngx_mail_protocol_t *protocol;
8181
8282 ngx_msec_t timeout;
83 ngx_msec_t resolver_timeout;
8384
8485 ngx_flag_t so_keepalive;
8586
8788
8889 u_char *file_name;
8990 ngx_int_t line;
91
92 ngx_resolver_t *resolver;
9093
9194 /* server ctx */
9295 ngx_mail_conf_ctx_t *ctx;
146149 void **main_conf;
147150 void **srv_conf;
148151
152 ngx_resolver_ctx_t *resolver_ctx;
153
149154 ngx_mail_proxy_ctx_t *proxy;
150155
151156 ngx_uint_t mail_state;
170175 ngx_str_t text;
171176
172177 ngx_str_t *addr_text;
178 ngx_str_t host;
173179 ngx_str_t smtp_helo;
174180
175181 ngx_uint_t command;
1919 void *conf);
2020 static char *ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd,
2121 void *conf);
22 static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
23 void *conf);
2224
2325
2426 static ngx_command_t ngx_mail_core_commands[] = {
6365 ngx_conf_set_str_slot,
6466 NGX_MAIL_SRV_CONF_OFFSET,
6567 offsetof(ngx_mail_core_srv_conf_t, server_name),
68 NULL },
69
70 { ngx_string("resolver"),
71 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
72 ngx_mail_core_resolver,
73 NGX_MAIL_SRV_CONF_OFFSET,
74 0,
75 NULL },
76
77 { ngx_string("resolver_timeout"),
78 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
79 ngx_conf_set_msec_slot,
80 NGX_MAIL_SRV_CONF_OFFSET,
81 offsetof(ngx_mail_core_srv_conf_t, resolver_timeout),
6682 NULL },
6783
6884 ngx_null_command
137153 * set by ngx_pcalloc():
138154 *
139155 * cscf->protocol = NULL;
156 * cscf->resolver = NULL;
140157 */
141158
142159 cscf->timeout = NGX_CONF_UNSET_MSEC;
160 cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
143161 cscf->so_keepalive = NGX_CONF_UNSET;
162
163 cscf->file_name = cf->conf_file->file.name.data;
164 cscf->line = cf->conf_file->line;
144165
145166 return cscf;
146167 }
153174 ngx_mail_core_srv_conf_t *conf = child;
154175
155176 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
177 ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout,
178 30000);
156179
157180 ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0);
158181
181204 "unknown mail protocol for server in %s:%ui",
182205 conf->file_name, conf->line);
183206 return NGX_CONF_ERROR;
207 }
208
209 if (conf->resolver == NULL) {
210 conf->resolver = prev->resolver;
184211 }
185212
186213 return NGX_CONF_OK;
236263 cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index];
237264 cscf->ctx = ctx;
238265
239 cscf->file_name = cf->conf_file->file.name.data;
240 cscf->line = cf->conf_file->line;
241
242266 cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
243267
244268 cscfp = ngx_array_push(&cmcf->servers);
388412 }
389413
390414
415 static char *
416 ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
417 {
418 ngx_mail_core_srv_conf_t *cscf = conf;
419
420 ngx_url_t u;
421 ngx_str_t *value;
422
423 value = cf->args->elts;
424
425 ngx_memzero(&u, sizeof(ngx_url_t));
426
427 u.host = value[1];
428 u.port = 53;
429
430 if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
431 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
432 return NGX_CONF_ERROR;
433 }
434
435 cscf->resolver = ngx_resolver_create(&u.addrs[0], cf->cycle->new_log);
436 if (cscf->resolver == NULL) {
437 return NGX_OK;
438 }
439
440 return NGX_CONF_OK;
441 }
442
443
391444 char *
392445 ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
393446 {
527527
528528 s->connection->log->action = "sending XCLIENT to upstream";
529529
530 line.len = sizeof("XCLIENT PROTO=SMTP HELO= ADDR= LOGIN= "
531 "NAME=[UNAVAILABLE]" CRLF) - 1
530 line.len = sizeof("XCLIENT PROTO=SMTP HELO= ADDR= LOGIN= NAME="
531 CRLF) - 1
532532 + s->esmtp + s->smtp_helo.len
533 + s->connection->addr_text.len + s->login.len;
533 + s->connection->addr_text.len + s->login.len + s->host.len;
534534
535535 line.data = ngx_palloc(c->pool, line.len);
536536 if (line.data == NULL) {
541541 if (s->smtp_helo.len) {
542542 line.len = ngx_sprintf(line.data,
543543 "XCLIENT PROTO=%sSMTP HELO=%V ADDR=%V LOGIN=%V "
544 "NAME=[UNAVAILABLE]" CRLF,
544 "NAME=%V" CRLF,
545545 (s->esmtp ? "E" : ""), &s->smtp_helo,
546 &s->connection->addr_text, &s->login)
546 &s->connection->addr_text, &s->login, &s->host)
547547 - line.data;
548548 } else {
549549 line.len = ngx_sprintf(line.data,
550 "XCLIENT PROTO=SMTP ADDR=%V LOGIN=%V "
551 "NAME=[UNAVAILABLE]" CRLF,
552 &s->connection->addr_text, &s->login)
550 "XCLIENT PROTO=SMTP ADDR=%V LOGIN=%V NAME=%V" CRLF,
551 &s->connection->addr_text, &s->login, &s->host)
553552 - line.data;
554553 }
555554
1010 #include <ngx_mail_smtp_module.h>
1111
1212
13 static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
14 static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
15 static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
1316 static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
1417 static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
1518 ngx_connection_t *c);
3942 static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF;
4043
4144
45 static ngx_str_t smtp_unavailable = ngx_string("[UNAVAILABLE]");
46 static ngx_str_t smtp_tempunavail = ngx_string("[TEMPUNAVAIL]");
47
48
4249 void
4350 ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
51 {
52 struct sockaddr_in *sin;
53 ngx_resolver_ctx_t *ctx;
54 ngx_mail_core_srv_conf_t *cscf;
55
56 c->log->action = "in resolving client address";
57
58 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
59
60 ctx = ngx_resolve_start(cscf->resolver, NULL);
61 if (ctx == NULL) {
62 ngx_mail_close_connection(c);
63 return;
64 }
65
66 /* AF_INET only */
67
68 sin = (struct sockaddr_in *) c->sockaddr;
69
70 ctx->addr = sin->sin_addr.s_addr;
71 ctx->handler = ngx_mail_smtp_resolve_addr_handler;
72 ctx->data = s;
73 ctx->timeout = cscf->resolver_timeout;
74
75 if (ngx_resolve_addr(ctx) != NGX_OK) {
76 ngx_mail_close_connection(c);
77 }
78 }
79
80
81 static void
82 ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
83 {
84 ngx_connection_t *c;
85 ngx_mail_session_t *s;
86 ngx_mail_core_srv_conf_t *cscf;
87
88 s = ctx->data;
89 c = s->connection;
90
91 if (ctx->state) {
92 ngx_log_error(NGX_LOG_ERR, c->log, 0,
93 "%V could not be resolved (%i: %s)",
94 &c->addr_text, ctx->state,
95 ngx_resolver_strerror(ctx->state));
96
97 if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
98 s->host = smtp_unavailable;
99
100 } else {
101 s->host = smtp_tempunavail;
102 }
103
104 ngx_resolve_addr_done(ctx);
105
106 ngx_mail_smtp_greeting(s, s->connection);
107
108 return;
109 }
110
111 c->log->action = "in resolving client hostname";
112
113 s->host.data = ngx_pstrdup(c->pool, &ctx->name);
114 if (s->host.data == NULL) {
115 ngx_resolve_addr_done(ctx);
116 ngx_mail_close_connection(c);
117 return;
118 }
119
120 s->host.len = ctx->name.len;
121
122 ngx_resolve_addr_done(ctx);
123
124 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
125 "address resolved: %V", &s->host);
126
127 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
128
129 ctx = ngx_resolve_start(cscf->resolver, NULL);
130 if (ctx == NULL) {
131 ngx_mail_close_connection(c);
132 return;
133 }
134
135 ctx->name = s->host;
136 ctx->type = NGX_RESOLVE_A;
137 ctx->handler = ngx_mail_smtp_resolve_name_handler;
138 ctx->data = s;
139 ctx->timeout = cscf->resolver_timeout;
140
141 if (ngx_resolve_name(ctx) != NGX_OK) {
142 ngx_mail_close_connection(c);
143 }
144 }
145
146
147 static void
148 ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
149 {
150 in_addr_t addr;
151 ngx_uint_t i;
152 ngx_connection_t *c;
153 struct sockaddr_in *sin;
154 ngx_mail_session_t *s;
155
156 s = ctx->data;
157 c = s->connection;
158
159 if (ctx->state) {
160 ngx_log_error(NGX_LOG_ERR, c->log, 0,
161 "%V could not be resolved (%i: %s)",
162 &ctx->name, ctx->state,
163 ngx_resolver_strerror(ctx->state));
164
165 if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
166 s->host = smtp_unavailable;
167
168 } else {
169 s->host = smtp_tempunavail;
170 }
171
172 } else {
173
174 /* AF_INET only */
175
176 sin = (struct sockaddr_in *) c->sockaddr;
177
178 for (i = 0; i < ctx->naddrs; i++) {
179
180 addr = ctx->addrs[i];
181
182 ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,
183 "name was resolved to %ud.%ud.%ud.%ud",
184 (ntohl(addr) >> 24) & 0xff,
185 (ntohl(addr) >> 16) & 0xff,
186 (ntohl(addr) >> 8) & 0xff,
187 ntohl(addr) & 0xff);
188
189 if (addr == sin->sin_addr.s_addr) {
190 goto found;
191 }
192 }
193
194 s->host = smtp_unavailable;
195 }
196
197 found:
198
199 ngx_resolve_name_done(ctx);
200
201 ngx_mail_smtp_greeting(s, c);
202 }
203
204
205 static void
206 ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
44207 {
45208 ngx_msec_t timeout;
46209 ngx_mail_core_srv_conf_t *cscf;
47210 ngx_mail_smtp_srv_conf_t *sscf;
211
212 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
213 "smtp greeting for \"%V\"", &s->host);
48214
49215 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
50216 sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
157157
158158 cscf = ngx_mail_conf_get_module_srv_conf(cf, ngx_mail_core_module);
159159
160 if (cscf->protocol->type == NGX_MAIL_SMTP_PROTOCOL
161 && cscf->resolver == NULL)
162 {
163 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
164 "undefined resolver for server in %s:%ui",
165 cscf->file_name, cscf->line);
166 return NGX_CONF_ERROR;
167 }
168
160169 size = sizeof("220 ESMTP ready" CRLF) - 1 + cscf->server_name.len;
161170
162171 p = ngx_palloc(cf->pool, size);