postscreen_endpt.c [plain text]
#include <sys_defs.h>
#include <string.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
#include <msg.h>
#include <myaddrinfo.h>
#include <vstream.h>
#include <inet_proto.h>
#include <mail_params.h>
#include <haproxy_srvr.h>
#include <postscreen.h>
#include <postscreen_haproxy.h>
static INET_PROTO_INFO *proto_info;
static int psc_sockaddr_to_hostaddr(struct sockaddr *addr_storage,
SOCKADDR_SIZE addr_storage_len,
MAI_HOSTADDR_STR *addr_buf,
MAI_SERVPORT_STR *port_buf,
int socktype)
{
int aierr;
if ((aierr = sockaddr_to_hostaddr(addr_storage, addr_storage_len,
addr_buf, port_buf, socktype)) == 0
&& strncasecmp("::ffff:", addr_buf->buf, 7) == 0
&& strchr((char *) proto_info->sa_family_list, AF_INET) != 0)
memmove(addr_buf->buf, addr_buf->buf + 7,
sizeof(addr_buf->buf) - 7);
return (aierr);
}
static void psc_endpt_local_lookup(VSTREAM *smtp_client_stream,
PSC_ENDPT_LOOKUP_FN lookup_done)
{
struct sockaddr_storage addr_storage;
SOCKADDR_SIZE addr_storage_len = sizeof(addr_storage);
int status;
MAI_HOSTADDR_STR smtp_client_addr;
MAI_SERVPORT_STR smtp_client_port;
MAI_HOSTADDR_STR smtp_server_addr;
MAI_SERVPORT_STR smtp_server_port;
int aierr;
if (getpeername(vstream_fileno(smtp_client_stream), (struct sockaddr *)
&addr_storage, &addr_storage_len) < 0) {
msg_warn("getpeername: %m -- dropping this connection");
status = -1;
}
else if ((aierr = psc_sockaddr_to_hostaddr(
(struct sockaddr *) &addr_storage,
addr_storage_len, &smtp_client_addr,
&smtp_client_port, SOCK_STREAM)) != 0) {
msg_warn("cannot convert client address/port to string: %s"
" -- dropping this connection",
MAI_STRERROR(aierr));
status = -1;
}
else if (getsockname(vstream_fileno(smtp_client_stream),
(struct sockaddr *) &addr_storage,
&addr_storage_len) < 0) {
msg_warn("getsockname: %m -- dropping this connection");
status = -1;
}
else if ((aierr = psc_sockaddr_to_hostaddr(
(struct sockaddr *) &addr_storage,
addr_storage_len, &smtp_server_addr,
&smtp_server_port, SOCK_STREAM)) != 0) {
msg_warn("cannot convert server address/port to string: %s"
" -- dropping this connection",
MAI_STRERROR(aierr));
status = -1;
} else {
status = 0;
}
lookup_done(status, smtp_client_stream,
&smtp_client_addr, &smtp_client_port,
&smtp_server_addr, &smtp_server_port);
}
typedef struct {
const char *name;
void (*endpt_lookup) (VSTREAM *, PSC_ENDPT_LOOKUP_FN);
} PSC_ENDPT_LOOKUP_INFO;
static const PSC_ENDPT_LOOKUP_INFO psc_endpt_lookup_info[] = {
NOPROXY_PROTO_NAME, psc_endpt_local_lookup,
HAPROXY_PROTO_NAME, psc_endpt_haproxy_lookup,
0,
};
void psc_endpt_lookup(VSTREAM *smtp_client_stream,
PSC_ENDPT_LOOKUP_FN notify)
{
const PSC_ENDPT_LOOKUP_INFO *pp;
if (proto_info == 0)
proto_info = inet_proto_info();
for (pp = psc_endpt_lookup_info; ; pp++) {
if (pp->name == 0)
msg_fatal("unsupported %s value: %s",
VAR_PSC_UPROXY_PROTO, var_psc_uproxy_proto);
if (strcmp(var_psc_uproxy_proto, pp->name) == 0) {
pp->endpt_lookup(smtp_client_stream, notify);
return;
}
}
}