rev |
line source |
meillo@0
|
1 /* MasqMail
|
meillo@0
|
2 Copyright (C) 1999 Oliver Kurth
|
meillo@0
|
3
|
meillo@0
|
4 This program is free software; you can redistribute it and/or modify
|
meillo@0
|
5 it under the terms of the GNU General Public License as published by
|
meillo@0
|
6 the Free Software Foundation; either version 2 of the License, or
|
meillo@0
|
7 (at your option) any later version.
|
meillo@0
|
8
|
meillo@0
|
9 This program is distributed in the hope that it will be useful,
|
meillo@0
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
meillo@0
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
meillo@0
|
12 GNU General Public License for more details.
|
meillo@0
|
13
|
meillo@0
|
14 You should have received a copy of the GNU General Public License
|
meillo@0
|
15 along with this program; if not, write to the Free Software
|
meillo@0
|
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
meillo@0
|
17 */
|
meillo@0
|
18 #include "masqmail.h"
|
meillo@0
|
19
|
meillo@0
|
20 static
|
meillo@0
|
21 GList *resolve_ip(GList *list, gchar *ip)
|
meillo@0
|
22 {
|
meillo@0
|
23 struct in_addr ia;
|
meillo@0
|
24 if(inet_aton(ip, &ia)){
|
meillo@0
|
25 mxip_addr mxip;
|
meillo@0
|
26
|
meillo@0
|
27 mxip.name = g_strdup(ip);
|
meillo@0
|
28 mxip.pref = 0;
|
meillo@0
|
29 mxip.ip = (guint32) *(guint32 *)(&ia);
|
meillo@0
|
30 list = g_list_append(list, g_memdup(&mxip, sizeof(mxip)));
|
meillo@0
|
31 }
|
meillo@0
|
32 /* logwrite(LOG_ALERT, "invalid address '%s': inet_aton() failed\n", ip);*/
|
meillo@0
|
33 return NULL;
|
meillo@0
|
34 }
|
meillo@0
|
35
|
meillo@0
|
36 mxip_addr *connect_hostlist(int *psockfd, gchar *host, guint port,
|
meillo@0
|
37 GList *addr_list)
|
meillo@0
|
38 {
|
meillo@0
|
39 GList *addr_node;
|
meillo@0
|
40 struct sockaddr_in saddr;
|
meillo@0
|
41
|
meillo@0
|
42 DEBUG(5) debugf("connect_hostlist entered\n");
|
meillo@0
|
43
|
meillo@0
|
44 for(addr_node = g_list_first(addr_list);
|
meillo@0
|
45 addr_node;
|
meillo@0
|
46 addr_node = g_list_next(addr_node)){
|
meillo@0
|
47 mxip_addr *addr = (mxip_addr *)(addr_node->data);
|
meillo@0
|
48
|
meillo@0
|
49 *psockfd = socket(PF_INET, SOCK_STREAM, 0);
|
meillo@0
|
50
|
meillo@0
|
51 memset(&saddr, 0, sizeof(saddr));
|
meillo@0
|
52
|
meillo@0
|
53 saddr.sin_family = AF_INET;
|
meillo@0
|
54 saddr.sin_port = htons(port);
|
meillo@0
|
55
|
meillo@0
|
56 /* clumsy, but makes compiler happy: */
|
meillo@0
|
57 saddr.sin_addr = *(struct in_addr*)(&(addr->ip));
|
meillo@0
|
58 DEBUG(5) debugf("trying ip %s port %d\n", inet_ntoa(saddr.sin_addr), port);
|
meillo@0
|
59 if(connect(*psockfd, (struct sockaddr *)(&saddr), sizeof(saddr)) == 0){
|
meillo@0
|
60 DEBUG(5) debugf("connected to %s\n", inet_ntoa(saddr.sin_addr));
|
meillo@0
|
61 return addr;
|
meillo@0
|
62 }else{
|
meillo@0
|
63 int saved_errno = errno;
|
meillo@0
|
64
|
meillo@0
|
65 close(*psockfd);
|
meillo@0
|
66
|
meillo@0
|
67 logwrite(LOG_WARNING, "connection to %s failed: %s\n",
|
meillo@0
|
68 inet_ntoa(saddr.sin_addr), strerror(errno));
|
meillo@0
|
69
|
meillo@0
|
70 errno = saved_errno;
|
meillo@0
|
71
|
meillo@0
|
72 if((saved_errno != ECONNREFUSED) &&
|
meillo@0
|
73 (saved_errno != ETIMEDOUT) &&
|
meillo@0
|
74 (saved_errno != ENETUNREACH) &&
|
meillo@0
|
75 (saved_errno != EHOSTUNREACH))
|
meillo@0
|
76
|
meillo@0
|
77 return NULL;
|
meillo@0
|
78 }
|
meillo@0
|
79 }
|
meillo@0
|
80 return NULL;
|
meillo@0
|
81 }
|
meillo@0
|
82
|
meillo@0
|
83 /* Given a list of resolver functions, this function
|
meillo@0
|
84 resolve the host and tries to connect to the addresses
|
meillo@0
|
85 returned. If a connection attemp is timed out or refused,
|
meillo@0
|
86 the next address is tried.
|
meillo@0
|
87
|
meillo@0
|
88 TODO: the resolver functions might return duplicate addresses,
|
meillo@0
|
89 if attempt failed for one it should not be tried again.
|
meillo@0
|
90 */
|
meillo@0
|
91
|
meillo@0
|
92 mxip_addr *connect_resolvelist(int *psockfd, gchar *host, guint port,
|
meillo@0
|
93 GList *res_func_list)
|
meillo@0
|
94 {
|
meillo@0
|
95 GList *res_node;
|
meillo@0
|
96 GList *addr_list;
|
meillo@0
|
97
|
meillo@0
|
98 DEBUG(5) debugf("connect_resolvelist entered\n");
|
meillo@0
|
99
|
meillo@0
|
100 h_errno = 0;
|
meillo@0
|
101
|
meillo@0
|
102 if(isdigit(host[0])){
|
meillo@0
|
103 mxip_addr *addr;
|
meillo@0
|
104
|
meillo@0
|
105 addr_list = resolve_ip(NULL, host);
|
meillo@0
|
106 if(addr_list){
|
meillo@0
|
107 addr = connect_hostlist(psockfd, host, port, addr_list);
|
meillo@0
|
108 g_list_free(addr_list);
|
meillo@0
|
109 return addr;
|
meillo@0
|
110 }
|
meillo@0
|
111 /* previous versions complained, until someone tried to use a hostname
|
meillo@0
|
112 out there that begins with a digit. eg. '3dwars.de'. */
|
meillo@0
|
113 }
|
meillo@0
|
114
|
meillo@0
|
115 if(res_func_list == NULL){
|
meillo@0
|
116 logwrite(LOG_ALERT, "res_funcs == NULL !!!\n");
|
meillo@0
|
117 exit(EXIT_FAILURE);
|
meillo@0
|
118 }
|
meillo@0
|
119
|
meillo@0
|
120 foreach(res_func_list, res_node){
|
meillo@0
|
121 resolve_func res_func;
|
meillo@0
|
122 DEBUG(6) debugf("connect_resolvelist 1a\n");
|
meillo@0
|
123 res_func = (resolve_func)(res_node->data);
|
meillo@0
|
124
|
meillo@0
|
125 if(res_func == NULL){
|
meillo@0
|
126 logwrite(LOG_ALERT, "res_func == NULL !!!\n");
|
meillo@0
|
127 exit(EXIT_FAILURE);
|
meillo@0
|
128 }
|
meillo@0
|
129
|
meillo@0
|
130 errno = 0;
|
meillo@0
|
131 if((addr_list = res_func(NULL, host))){
|
meillo@0
|
132
|
meillo@0
|
133 mxip_addr *addr;
|
meillo@0
|
134 if((addr = connect_hostlist(psockfd, host, port, addr_list)))
|
meillo@0
|
135 return addr;
|
meillo@0
|
136
|
meillo@0
|
137 DEBUG(5){
|
meillo@0
|
138 debugf("connect_hostlist failed: %s\n", strerror(errno));
|
meillo@0
|
139 }
|
meillo@0
|
140
|
meillo@0
|
141 g_list_free(addr_list);
|
meillo@0
|
142 }else{
|
meillo@0
|
143 if(!g_list_next(res_node)){
|
meillo@0
|
144 logwrite(LOG_ALERT, "could not resolve %s: %s\n", host, hstrerror(h_errno));
|
meillo@0
|
145 }
|
meillo@0
|
146 }
|
meillo@0
|
147 }
|
meillo@0
|
148 return NULL;
|
meillo@0
|
149
|
meillo@0
|
150 }
|
meillo@0
|
151
|