masqmail
diff src/connect.c @ 0:08114f7dcc23
this is masqmail-0.2.21 from oliver kurth
author | meillo@marmaro.de |
---|---|
date | Fri, 26 Sep 2008 17:05:23 +0200 |
parents | |
children | 26e34ae9a3e3 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/connect.c Fri Sep 26 17:05:23 2008 +0200 1.3 @@ -0,0 +1,151 @@ 1.4 +/* MasqMail 1.5 + Copyright (C) 1999 Oliver Kurth 1.6 + 1.7 + This program is free software; you can redistribute it and/or modify 1.8 + it under the terms of the GNU General Public License as published by 1.9 + the Free Software Foundation; either version 2 of the License, or 1.10 + (at your option) any later version. 1.11 + 1.12 + This program is distributed in the hope that it will be useful, 1.13 + but WITHOUT ANY WARRANTY; without even the implied warranty of 1.14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.15 + GNU General Public License for more details. 1.16 + 1.17 + You should have received a copy of the GNU General Public License 1.18 + along with this program; if not, write to the Free Software 1.19 + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1.20 +*/ 1.21 +#include "masqmail.h" 1.22 + 1.23 +static 1.24 +GList *resolve_ip(GList *list, gchar *ip) 1.25 +{ 1.26 + struct in_addr ia; 1.27 + if(inet_aton(ip, &ia)){ 1.28 + mxip_addr mxip; 1.29 + 1.30 + mxip.name = g_strdup(ip); 1.31 + mxip.pref = 0; 1.32 + mxip.ip = (guint32) *(guint32 *)(&ia); 1.33 + list = g_list_append(list, g_memdup(&mxip, sizeof(mxip))); 1.34 + } 1.35 + /* logwrite(LOG_ALERT, "invalid address '%s': inet_aton() failed\n", ip);*/ 1.36 + return NULL; 1.37 +} 1.38 + 1.39 +mxip_addr *connect_hostlist(int *psockfd, gchar *host, guint port, 1.40 + GList *addr_list) 1.41 +{ 1.42 + GList *addr_node; 1.43 + struct sockaddr_in saddr; 1.44 + 1.45 + DEBUG(5) debugf("connect_hostlist entered\n"); 1.46 + 1.47 + for(addr_node = g_list_first(addr_list); 1.48 + addr_node; 1.49 + addr_node = g_list_next(addr_node)){ 1.50 + mxip_addr *addr = (mxip_addr *)(addr_node->data); 1.51 + 1.52 + *psockfd = socket(PF_INET, SOCK_STREAM, 0); 1.53 + 1.54 + memset(&saddr, 0, sizeof(saddr)); 1.55 + 1.56 + saddr.sin_family = AF_INET; 1.57 + saddr.sin_port = htons(port); 1.58 + 1.59 + /* clumsy, but makes compiler happy: */ 1.60 + saddr.sin_addr = *(struct in_addr*)(&(addr->ip)); 1.61 + DEBUG(5) debugf("trying ip %s port %d\n", inet_ntoa(saddr.sin_addr), port); 1.62 + if(connect(*psockfd, (struct sockaddr *)(&saddr), sizeof(saddr)) == 0){ 1.63 + DEBUG(5) debugf("connected to %s\n", inet_ntoa(saddr.sin_addr)); 1.64 + return addr; 1.65 + }else{ 1.66 + int saved_errno = errno; 1.67 + 1.68 + close(*psockfd); 1.69 + 1.70 + logwrite(LOG_WARNING, "connection to %s failed: %s\n", 1.71 + inet_ntoa(saddr.sin_addr), strerror(errno)); 1.72 + 1.73 + errno = saved_errno; 1.74 + 1.75 + if((saved_errno != ECONNREFUSED) && 1.76 + (saved_errno != ETIMEDOUT) && 1.77 + (saved_errno != ENETUNREACH) && 1.78 + (saved_errno != EHOSTUNREACH)) 1.79 + 1.80 + return NULL; 1.81 + } 1.82 + } 1.83 + return NULL; 1.84 +} 1.85 + 1.86 +/* Given a list of resolver functions, this function 1.87 + resolve the host and tries to connect to the addresses 1.88 + returned. If a connection attemp is timed out or refused, 1.89 + the next address is tried. 1.90 + 1.91 + TODO: the resolver functions might return duplicate addresses, 1.92 + if attempt failed for one it should not be tried again. 1.93 +*/ 1.94 + 1.95 +mxip_addr *connect_resolvelist(int *psockfd, gchar *host, guint port, 1.96 + GList *res_func_list) 1.97 +{ 1.98 + GList *res_node; 1.99 + GList *addr_list; 1.100 + 1.101 + DEBUG(5) debugf("connect_resolvelist entered\n"); 1.102 + 1.103 + h_errno = 0; 1.104 + 1.105 + if(isdigit(host[0])){ 1.106 + mxip_addr *addr; 1.107 + 1.108 + addr_list = resolve_ip(NULL, host); 1.109 + if(addr_list){ 1.110 + addr = connect_hostlist(psockfd, host, port, addr_list); 1.111 + g_list_free(addr_list); 1.112 + return addr; 1.113 + } 1.114 + /* previous versions complained, until someone tried to use a hostname 1.115 + out there that begins with a digit. eg. '3dwars.de'. */ 1.116 + } 1.117 + 1.118 + if(res_func_list == NULL){ 1.119 + logwrite(LOG_ALERT, "res_funcs == NULL !!!\n"); 1.120 + exit(EXIT_FAILURE); 1.121 + } 1.122 + 1.123 + foreach(res_func_list, res_node){ 1.124 + resolve_func res_func; 1.125 + DEBUG(6) debugf("connect_resolvelist 1a\n"); 1.126 + res_func = (resolve_func)(res_node->data); 1.127 + 1.128 + if(res_func == NULL){ 1.129 + logwrite(LOG_ALERT, "res_func == NULL !!!\n"); 1.130 + exit(EXIT_FAILURE); 1.131 + } 1.132 + 1.133 + errno = 0; 1.134 + if((addr_list = res_func(NULL, host))){ 1.135 + 1.136 + mxip_addr *addr; 1.137 + if((addr = connect_hostlist(psockfd, host, port, addr_list))) 1.138 + return addr; 1.139 + 1.140 + DEBUG(5){ 1.141 + debugf("connect_hostlist failed: %s\n", strerror(errno)); 1.142 + } 1.143 + 1.144 + g_list_free(addr_list); 1.145 + }else{ 1.146 + if(!g_list_next(res_node)){ 1.147 + logwrite(LOG_ALERT, "could not resolve %s: %s\n", host, hstrerror(h_errno)); 1.148 + } 1.149 + } 1.150 + } 1.151 + return NULL; 1.152 + 1.153 +} 1.154 +