mail-host.c revision 09060303d565e15d54e42b4ef722f9d3c26f5336
7b59d02d2a384be9a08087b14defadd214b3c1ddjb/* Copyright (c) 2010-2014 Dovecot authors, see the included COPYING file */
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb#include "lib.h"
7b59d02d2a384be9a08087b14defadd214b3c1ddjb#include "array.h"
7b59d02d2a384be9a08087b14defadd214b3c1ddjb#include "bsearch-insert-pos.h"
7b59d02d2a384be9a08087b14defadd214b3c1ddjb#include "md5.h"
7b59d02d2a384be9a08087b14defadd214b3c1ddjb#include "mail-host.h"
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb#define VHOST_MULTIPLIER 100
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstruct mail_vhost {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb unsigned int hash;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host *host;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb};
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstruct mail_host_list {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb ARRAY_TYPE(mail_host) hosts;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb ARRAY(struct mail_vhost) vhosts;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb bool hosts_unsorted;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb bool consistent_hashing;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb};
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic int
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossmail_host_cmp(struct mail_host *const *h1, struct mail_host *const *h2)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return net_ip_cmp(&(*h1)->ip, &(*h2)->ip);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic int
7b59d02d2a384be9a08087b14defadd214b3c1ddjbmail_vhost_cmp(const struct mail_vhost *h1, const struct mail_vhost *h2)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (h1->hash < h2->hash)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb else if (h1->hash > h2->hash)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return 1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb /* hash collision. not ideal, but we'll need to keep the order
7b59d02d2a384be9a08087b14defadd214b3c1ddjb consistent across directors so compare the IPs next. */
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return net_ip_cmp(&h1->host->ip, &h2->host->ip);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic int
7b59d02d2a384be9a08087b14defadd214b3c1ddjbmail_vhost_hash_cmp(const unsigned int *hash, const struct mail_vhost *vhost)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (vhost->hash < *hash)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return 1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb else if (vhost->hash > *hash)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb else
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return 0;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
91d7f85e02991954d1e1bd44673df567ad8dcc87Gordon Rossstatic void mail_vhost_add(struct mail_host_list *list, struct mail_host *host)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_vhost *vhost;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct md5_context md5_ctx, md5_ctx2;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb unsigned char md5[MD5_RESULTLEN];
7b59d02d2a384be9a08087b14defadd214b3c1ddjb const char *ip_str;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb char num_str[MAX_INT_STRLEN];
7b59d02d2a384be9a08087b14defadd214b3c1ddjb unsigned int i, j;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb ip_str = net_ip2addr(&host->ip);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb md5_init(&md5_ctx);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb md5_update(&md5_ctx, ip_str, strlen(ip_str));
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb for (i = 0; i < host->vhost_count; i++) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb md5_ctx2 = md5_ctx;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_snprintf(num_str, sizeof(num_str), "-%u", i);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb md5_update(&md5_ctx2, num_str, strlen(num_str));
7b59d02d2a384be9a08087b14defadd214b3c1ddjb md5_final(&md5_ctx2, md5);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb vhost = array_append_space(&list->vhosts);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb vhost->host = host;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb for (j = 0; j < sizeof(vhost->hash); j++)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb vhost->hash = (vhost->hash << CHAR_BIT) | md5[j];
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic void mail_hosts_sort_ring(struct mail_host_list *list)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host *const *hostp;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb /* rebuild vhosts */
8d7e41661dc4633488e93b13363137523ce59977jose borrego array_clear(&list->vhosts);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb array_foreach(&list->hosts, hostp)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb mail_vhost_add(list, *hostp);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb array_sort(&list->vhosts, mail_vhost_cmp);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb list->hosts_unsorted = FALSE;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic void mail_hosts_sort_direct(struct mail_host_list *list)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_vhost *vhost;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host *const *hostp;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb unsigned int i;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb array_sort(&list->hosts, mail_host_cmp);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb /* rebuild vhosts */
7b59d02d2a384be9a08087b14defadd214b3c1ddjb array_clear(&list->vhosts);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb array_foreach(&list->hosts, hostp) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb for (i = 0; i < (*hostp)->vhost_count; i++) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb vhost = array_append_space(&list->vhosts);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb vhost->host = *hostp;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb list->hosts_unsorted = FALSE;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic void mail_hosts_sort(struct mail_host_list *list)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (list->consistent_hashing)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb mail_hosts_sort_ring(list);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb else
7b59d02d2a384be9a08087b14defadd214b3c1ddjb mail_hosts_sort_direct(list);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstruct mail_host *
7b59d02d2a384be9a08087b14defadd214b3c1ddjbmail_host_add_ip(struct mail_host_list *list, const struct ip_addr *ip,
7b59d02d2a384be9a08087b14defadd214b3c1ddjb const char *tag)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host *host;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_assert(tag != NULL);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb host = i_new(struct mail_host, 1);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb host->vhost_count = VHOST_MULTIPLIER;
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego host->ip = *ip;
8d7e41661dc4633488e93b13363137523ce59977jose borrego host->tag = i_strdup(tag);
8d7e41661dc4633488e93b13363137523ce59977jose borrego array_append(&list->hosts, &host, 1);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego list->hosts_unsorted = TRUE;
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego return host;
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic int
7b59d02d2a384be9a08087b14defadd214b3c1ddjbmail_host_add(struct mail_host_list *list, const char *host, const char *tag)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct ip_addr *ips;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb unsigned int i, ips_count;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (net_gethostbyname(host, &ips, &ips_count) < 0) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_error("Unknown mail host: %s", host);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb for (i = 0; i < ips_count; i++)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb (void)mail_host_add_ip(list, &ips[i], tag);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return 0;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic int
7b59d02d2a384be9a08087b14defadd214b3c1ddjbmail_hosts_add_range(struct mail_host_list *list,
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct ip_addr ip1, struct ip_addr ip2, const char *tag)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb uint32_t *ip1_arr, *ip2_arr;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb uint32_t i1, i2;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb unsigned int i, j, max_bits, last_bits;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (ip1.family != ip2.family) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_error("IP address family mismatch: %s vs %s",
7b59d02d2a384be9a08087b14defadd214b3c1ddjb net_ip2addr(&ip1), net_ip2addr(&ip2));
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (net_ip_cmp(&ip1, &ip2) > 0) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_error("IP addresses reversed: %s-%s",
7b59d02d2a384be9a08087b14defadd214b3c1ddjb net_ip2addr(&ip1), net_ip2addr(&ip2));
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (IPADDR_IS_V4(&ip1)) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb ip1_arr = &ip1.u.ip4.s_addr;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb ip2_arr = &ip2.u.ip4.s_addr;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb max_bits = 32;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb last_bits = 8;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb } else {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb#ifndef HAVE_IPV6
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_error("IPv6 not supported");
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb#else
7b59d02d2a384be9a08087b14defadd214b3c1ddjb ip1_arr = (void *)&ip1.u.ip6;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb ip2_arr = (void *)&ip2.u.ip6;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb max_bits = 128;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb last_bits = 16;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb#endif
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb /* make sure initial bits match */
7b59d02d2a384be9a08087b14defadd214b3c1ddjb for (i = 0; i < (max_bits-last_bits)/32; i++) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (ip1_arr[i] != ip2_arr[i]) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_error("IP address range too large: %s-%s",
7b59d02d2a384be9a08087b14defadd214b3c1ddjb net_ip2addr(&ip1), net_ip2addr(&ip2));
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i1 = htonl(ip1_arr[i]);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i2 = htonl(ip2_arr[i]);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb for (j = last_bits; j < 32; j++) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if ((i1 & (1U << j)) != (i2 & (1U << j))) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_error("IP address range too large: %s-%s",
7b59d02d2a384be9a08087b14defadd214b3c1ddjb net_ip2addr(&ip1), net_ip2addr(&ip2));
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb /* create hosts from the final bits */
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States do {
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States ip1_arr[i] = ntohl(i1);
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States (void)mail_host_add_ip(list, &ip1, tag);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i1++;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb } while (ip1_arr[i] != ip2_arr[i]);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return 0;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States
7b59d02d2a384be9a08087b14defadd214b3c1ddjbint mail_hosts_parse_and_add(struct mail_host_list *list,
7b59d02d2a384be9a08087b14defadd214b3c1ddjb const char *hosts_string)
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb int ret = 0;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb T_BEGIN {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb const char *const *tmp, *p, *host1, *host2;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct ip_addr ip1, ip2;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb tmp = t_strsplit_spaces(hosts_string, " ");
7b59d02d2a384be9a08087b14defadd214b3c1ddjb for (; *tmp != NULL; tmp++) {
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States const char *tag, *value = *tmp;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb p = strchr(value, '@');
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (p == NULL)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb tag = "";
7b59d02d2a384be9a08087b14defadd214b3c1ddjb else {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb value = t_strdup_until(value, p++);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb tag = p;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb p = strchr(value, '-');
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (p != NULL) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb /* see if this is ip1-ip2 range */
7b59d02d2a384be9a08087b14defadd214b3c1ddjb host1 = t_strdup_until(value, p);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb host2 = p + 1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (net_addr2ip(host1, &ip1) == 0 &&
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States net_addr2ip(host2, &ip2) == 0) {
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States if (mail_hosts_add_range(list, ip1, ip2,
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States tag) < 0)
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States ret = -1;
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States continue;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (mail_host_add(list, value, tag) < 0)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb ret = -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb } T_END;
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (array_count(&list->hosts) == 0) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (ret < 0)
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States i_error("No valid servers specified");
7b59d02d2a384be9a08087b14defadd214b3c1ddjb else
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_error("Empty server list");
7b59d02d2a384be9a08087b14defadd214b3c1ddjb ret = -1;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return ret;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbvoid mail_host_set_tag(struct mail_host *host, const char *tag)
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States{
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States i_assert(tag != NULL);
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States i_free(host->tag);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb host->tag = i_strdup(tag);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbvoid mail_host_set_vhost_count(struct mail_host_list *list,
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host *host, unsigned int vhost_count)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb host->vhost_count = vhost_count;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb list->hosts_unsorted = TRUE;
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic void mail_host_free(struct mail_host *host)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_free(host->tag);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_free(host);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbvoid mail_host_remove(struct mail_host_list *list, struct mail_host *host)
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright{
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright struct mail_host *const *hosts;
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright unsigned int i, count;
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright hosts = array_get(&list->hosts, &count);
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright for (i = 0; i < count; i++) {
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright if (hosts[i] == host) {
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright array_delete(&list->hosts, i, 1);
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright break;
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright }
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright }
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright mail_host_free(host);
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright list->hosts_unsorted = TRUE;
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright}
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wrightstruct mail_host *
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wrightmail_host_lookup(struct mail_host_list *list, const struct ip_addr *ip)
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright{
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright struct mail_host *const *hostp;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (list->hosts_unsorted)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb mail_hosts_sort(list);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb array_foreach(&list->hosts, hostp) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (net_ip_compare(&(*hostp)->ip, ip))
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return *hostp;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return NULL;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic struct mail_host *
7b59d02d2a384be9a08087b14defadd214b3c1ddjbmail_host_get_by_hash_ring(struct mail_host_list *list, unsigned int hash,
7b59d02d2a384be9a08087b14defadd214b3c1ddjb const char *tag)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host *host;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb const struct mail_vhost *vhosts;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb unsigned int i, count, idx;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb vhosts = array_get(&list->vhosts, &count);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb array_bsearch_insert_pos(&list->vhosts, &hash,
7b59d02d2a384be9a08087b14defadd214b3c1ddjb mail_vhost_hash_cmp, &idx);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_assert(idx <= count);
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States if (idx == count) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (count == 0)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return NULL;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb idx = 0;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb for (i = 0; i < count; i++) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb host = vhosts[(idx + i) % count].host;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (strcmp(host->tag, tag) == 0)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return host;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return NULL;
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic struct mail_host *
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United Statesmail_host_get_by_hash_direct(struct mail_host_list *list, unsigned int hash,
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States const char *tag)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host *host;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright const struct mail_vhost *vhosts;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright unsigned int i, count;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States vhosts = array_get(&list->vhosts, &count);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (count == 0)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return NULL;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb for (i = 0; i < count; i++) {
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States host = vhosts[(hash + i) % count].host;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (strcmp(host->tag, tag) == 0)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return host;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return NULL;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstruct mail_host *
7b59d02d2a384be9a08087b14defadd214b3c1ddjbmail_host_get_by_hash(struct mail_host_list *list, unsigned int hash,
7b59d02d2a384be9a08087b14defadd214b3c1ddjb const char *tag)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States if (list->hosts_unsorted)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb mail_hosts_sort(list);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (list->consistent_hashing)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return mail_host_get_by_hash_ring(list, hash, tag);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb else
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return mail_host_get_by_hash_direct(list, hash, tag);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbbool mail_hosts_have_usable(struct mail_host_list *list)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (list->hosts_unsorted)
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States mail_hosts_sort(list);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return array_count(&list->vhosts) > 0;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States
7b59d02d2a384be9a08087b14defadd214b3c1ddjbconst ARRAY_TYPE(mail_host) *mail_hosts_get(struct mail_host_list *list)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb if (list->hosts_unsorted)
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States mail_hosts_sort(list);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return &list->hosts;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstruct mail_host_list *mail_hosts_init(bool consistent_hashing)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host_list *list;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb list = i_new(struct mail_host_list, 1);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb list->consistent_hashing = consistent_hashing;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_array_init(&list->hosts, 16);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_array_init(&list->vhosts, 16*VHOST_MULTIPLIER);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return list;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbvoid mail_hosts_deinit(struct mail_host_list **_list)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host_list *list = *_list;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host **hostp;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb *_list = NULL;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
8d7e41661dc4633488e93b13363137523ce59977jose borrego array_foreach_modifiable(&list->hosts, hostp)
8d7e41661dc4633488e93b13363137523ce59977jose borrego mail_host_free(*hostp);
8d7e41661dc4633488e93b13363137523ce59977jose borrego array_free(&list->hosts);
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States array_free(&list->vhosts);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb i_free(list);
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States}
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstatic struct mail_host *mail_host_dup(const struct mail_host *src)
7b59d02d2a384be9a08087b14defadd214b3c1ddjb{
7b59d02d2a384be9a08087b14defadd214b3c1ddjb struct mail_host *dest;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjb dest = i_new(struct mail_host, 1);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb *dest = *src;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb dest->tag = i_strdup(src->tag);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return dest;
9fb67ea305c66b6a297583b9b0db6796b0dfe497afshin salek ardakani - Sun Microsystems - Irvine United States}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb
7b59d02d2a384be9a08087b14defadd214b3c1ddjbstruct mail_host_list *mail_hosts_dup(const struct mail_host_list *src)
8d7e41661dc4633488e93b13363137523ce59977jose borrego{
8d7e41661dc4633488e93b13363137523ce59977jose borrego struct mail_host_list *dest;
8d7e41661dc4633488e93b13363137523ce59977jose borrego struct mail_host *const *hostp, *dest_host;
8d7e41661dc4633488e93b13363137523ce59977jose borrego
8d7e41661dc4633488e93b13363137523ce59977jose borrego dest = mail_hosts_init(src->consistent_hashing);
8d7e41661dc4633488e93b13363137523ce59977jose borrego array_foreach(&src->hosts, hostp) {
7b59d02d2a384be9a08087b14defadd214b3c1ddjb dest_host = mail_host_dup(*hostp);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb array_append(&dest->hosts, &dest_host, 1);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb }
7b59d02d2a384be9a08087b14defadd214b3c1ddjb mail_hosts_sort(dest);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb return dest;
7b59d02d2a384be9a08087b14defadd214b3c1ddjb}
7b59d02d2a384be9a08087b14defadd214b3c1ddjb