Commit e6560c0c e6560c0c40cad32debb05b3678bfb448067ff1b0 by Sergey Poznyakoff

(mu_tcp_stream_create_with_source_ip,mu_tcp_stream_create_with_source_host): New functions

1 parent 1bc1b378
...@@ -48,6 +48,15 @@ extern int mu_temp_file_stream_create (mu_stream_t *stream, const char *dir); ...@@ -48,6 +48,15 @@ extern int mu_temp_file_stream_create (mu_stream_t *stream, const char *dir);
48 48
49 extern int mu_tcp_stream_create (mu_stream_t *stream, const char* host, 49 extern int mu_tcp_stream_create (mu_stream_t *stream, const char* host,
50 int port, int flags); 50 int port, int flags);
51 extern int mu_tcp_stream_create_with_source_ip (mu_stream_t *stream,
52 const char *host, int port,
53 unsigned long source_ip,
54 int flags);
55 extern int mu_tcp_stream_create_with_source_host (mu_stream_t *stream,
56 const char *host, int port,
57 const char *source_host,
58 int flags);
59
51 extern int mu_mapfile_stream_create (mu_stream_t *stream, const char* filename, 60 extern int mu_mapfile_stream_create (mu_stream_t *stream, const char* filename,
52 int flags); 61 int flags);
53 extern int mu_memory_stream_create (mu_stream_t *stream, const char* filename, 62 extern int mu_memory_stream_create (mu_stream_t *stream, const char* filename,
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2004, 2006 Free Software Foundation, Inc.
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public 5 modify it under the terms of the GNU Lesser General Public
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
20 # include <config.h> 20 # include <config.h>
21 #endif 21 #endif
22 22
23 #include <assert.h>
24 #include <errno.h> 23 #include <errno.h>
25 #include <fcntl.h> 24 #include <fcntl.h>
26 #include <netdb.h> 25 #include <netdb.h>
...@@ -46,12 +45,14 @@ ...@@ -46,12 +45,14 @@
46 #define TCP_STATE_CONNECTING 4 45 #define TCP_STATE_CONNECTING 4
47 #define TCP_STATE_CONNECTED 5 46 #define TCP_STATE_CONNECTED 5
48 47
49 struct _tcp_instance { 48 struct _tcp_instance
50 int fd; 49 {
51 char *host; 50 int fd;
52 int port; 51 char *host;
53 int state; 52 int port;
54 unsigned long address; 53 int state;
54 unsigned long address;
55 unsigned long source_addr;
55 }; 56 };
56 57
57 /* On solaris inet_addr() return -1. */ 58 /* On solaris inet_addr() return -1. */
...@@ -78,13 +79,27 @@ _tcp_close (mu_stream_t stream) ...@@ -78,13 +79,27 @@ _tcp_close (mu_stream_t stream)
78 } 79 }
79 80
80 static int 81 static int
82 resolve_hostname (const char *host, unsigned long *ip)
83 {
84 unsigned long address = inet_addr (host);
85 if (address == INADDR_NONE)
86 {
87 struct hostent *phe = gethostbyname (host);
88 if (!phe)
89 return MU_ERR_GETHOSTBYNAME;
90 address = *(((unsigned long **) phe->h_addr_list)[0]);
91 }
92 *ip = address;
93 return 0;
94 }
95
96 static int
81 _tcp_open (mu_stream_t stream) 97 _tcp_open (mu_stream_t stream)
82 { 98 {
83 struct _tcp_instance *tcp = mu_stream_get_owner (stream); 99 struct _tcp_instance *tcp = mu_stream_get_owner (stream);
84 int flgs, ret; 100 int flgs, ret;
85 socklen_t namelen; 101 socklen_t namelen;
86 struct sockaddr_in peer_addr; 102 struct sockaddr_in peer_addr;
87 struct hostent *phe;
88 struct sockaddr_in soc_addr; 103 struct sockaddr_in soc_addr;
89 int flags; 104 int flags;
90 105
...@@ -105,19 +120,33 @@ _tcp_open (mu_stream_t stream) ...@@ -105,19 +120,33 @@ _tcp_open (mu_stream_t stream)
105 fcntl (tcp->fd, F_SETFL, flgs); 120 fcntl (tcp->fd, F_SETFL, flgs);
106 mu_stream_set_flags (stream, MU_STREAM_NONBLOCK); 121 mu_stream_set_flags (stream, MU_STREAM_NONBLOCK);
107 } 122 }
108 tcp->state = TCP_STATE_RESOLVING; 123 if (tcp->source_addr != INADDR_ANY)
109 case TCP_STATE_RESOLVING:
110 assert (tcp->host != NULL && tcp->port > 0);
111 tcp->address = inet_addr (tcp->host);
112 if (tcp->address == INADDR_NONE)
113 { 124 {
114 phe = gethostbyname (tcp->host); 125 struct sockaddr_in s;
115 if (!phe) 126 s.sin_family = AF_INET;
127 s.sin_addr.s_addr = tcp->source_addr;
128 s.sin_port = 0;
129 if (bind (tcp->fd, (struct sockaddr*) &s, sizeof(s)) < 0)
116 { 130 {
117 _tcp_close (stream); 131 int e = errno;
118 return MU_ERR_GETHOSTBYNAME; 132 close (tcp->fd);
133 tcp->fd = -1;
134 return e;
119 } 135 }
120 tcp->address = *(((unsigned long **) phe->h_addr_list)[0]); 136 }
137
138 tcp->state = TCP_STATE_RESOLVING;
139 case TCP_STATE_RESOLVING:
140 if (!(tcp->host != NULL && tcp->port > 0))
141 {
142 _tcp_close (stream);
143 return EINVAL;
144 }
145
146 if ((ret = resolve_hostname (tcp->host, &tcp->address)))
147 {
148 _tcp_close (stream);
149 return ret;
121 } 150 }
122 tcp->state = TCP_STATE_RESOLVE; 151 tcp->state = TCP_STATE_RESOLVE;
123 case TCP_STATE_RESOLVE: 152 case TCP_STATE_RESOLVE:
...@@ -158,7 +187,8 @@ _tcp_open (mu_stream_t stream) ...@@ -158,7 +187,8 @@ _tcp_open (mu_stream_t stream)
158 187
159 188
160 static int 189 static int
161 _tcp_get_transport2 (mu_stream_t stream, mu_transport_t *tr, mu_transport_t *tr2) 190 _tcp_get_transport2 (mu_stream_t stream, mu_transport_t *tr,
191 mu_transport_t *tr2)
162 { 192 {
163 struct _tcp_instance *tcp = mu_stream_get_owner (stream); 193 struct _tcp_instance *tcp = mu_stream_get_owner (stream);
164 194
...@@ -173,7 +203,8 @@ _tcp_get_transport2 (mu_stream_t stream, mu_transport_t *tr, mu_transport_t *tr2 ...@@ -173,7 +203,8 @@ _tcp_get_transport2 (mu_stream_t stream, mu_transport_t *tr, mu_transport_t *tr2
173 } 203 }
174 204
175 static int 205 static int
176 _tcp_read (mu_stream_t stream, char *buf, size_t buf_size, mu_off_t offset, size_t * br) 206 _tcp_read (mu_stream_t stream, char *buf, size_t buf_size,
207 mu_off_t offset, size_t * br)
177 { 208 {
178 struct _tcp_instance *tcp = mu_stream_get_owner (stream); 209 struct _tcp_instance *tcp = mu_stream_get_owner (stream);
179 int bytes; 210 int bytes;
...@@ -192,7 +223,8 @@ _tcp_read (mu_stream_t stream, char *buf, size_t buf_size, mu_off_t offset, size ...@@ -192,7 +223,8 @@ _tcp_read (mu_stream_t stream, char *buf, size_t buf_size, mu_off_t offset, size
192 } 223 }
193 224
194 static int 225 static int
195 _tcp_write (mu_stream_t stream, const char *buf, size_t buf_size, mu_off_t offset, 226 _tcp_write (mu_stream_t stream, const char *buf, size_t buf_size,
227 mu_off_t offset,
196 size_t * bw) 228 size_t * bw)
197 { 229 {
198 struct _tcp_instance *tcp = mu_stream_get_owner (stream); 230 struct _tcp_instance *tcp = mu_stream_get_owner (stream);
...@@ -234,7 +266,10 @@ _tcp_wait (mu_stream_t stream, int *pflags, struct timeval *tvp) ...@@ -234,7 +266,10 @@ _tcp_wait (mu_stream_t stream, int *pflags, struct timeval *tvp)
234 } 266 }
235 267
236 int 268 int
237 mu_tcp_stream_create (mu_stream_t * stream, const char* host, int port, int flags) 269 mu_tcp_stream_create_with_source_ip (mu_stream_t *stream,
270 const char *host, int port,
271 unsigned long source_ip,
272 int flags)
238 { 273 {
239 struct _tcp_instance *tcp; 274 struct _tcp_instance *tcp;
240 int ret; 275 int ret;
...@@ -250,15 +285,15 @@ mu_tcp_stream_create (mu_stream_t * stream, const char* host, int port, int flag ...@@ -250,15 +285,15 @@ mu_tcp_stream_create (mu_stream_t * stream, const char* host, int port, int flag
250 tcp->fd = -1; 285 tcp->fd = -1;
251 tcp->host = strdup (host); 286 tcp->host = strdup (host);
252 if(!tcp->host) 287 if(!tcp->host)
253 { 288 {
254 free (tcp); 289 free (tcp);
255 return ENOMEM; 290 return ENOMEM;
256 } 291 }
257 tcp->port = port; 292 tcp->port = port;
258 tcp->state = TCP_STATE_INIT; 293 tcp->state = TCP_STATE_INIT;
259 294 tcp->source_addr = source_ip;
260 if ((ret = mu_stream_create (stream, 295 if ((ret = mu_stream_create (stream,
261 flags | MU_STREAM_NO_CHECK | MU_STREAM_RDWR, tcp)) != 0) 296 flags | MU_STREAM_NO_CHECK | MU_STREAM_RDWR, tcp)))
262 { 297 {
263 free (tcp->host); 298 free (tcp->host);
264 free (tcp); 299 free (tcp);
...@@ -276,3 +311,25 @@ mu_tcp_stream_create (mu_stream_t * stream, const char* host, int port, int flag ...@@ -276,3 +311,25 @@ mu_tcp_stream_create (mu_stream_t * stream, const char* host, int port, int flag
276 311
277 return 0; 312 return 0;
278 } 313 }
314
315 int
316 mu_tcp_stream_create_with_source_host (mu_stream_t *stream,
317 const char *host, int port,
318 const char *source_host,
319 int flags)
320 {
321 unsigned long source_addr;
322 int ret = resolve_hostname (source_host, &source_addr);
323 if (ret == 0)
324 ret = mu_tcp_stream_create_with_source_ip (stream, host, port,
325 source_addr, flags);
326 return ret;
327 }
328
329 int
330 mu_tcp_stream_create (mu_stream_t *stream, const char *host, int port,
331 int flags)
332 {
333 return mu_tcp_stream_create_with_source_ip (stream, host, port,
334 INADDR_ANY, flags);
335 }
......