(mu_tcp_stream_create_with_source_ip,mu_tcp_stream_create_with_source_host): New functions
Showing
2 changed files
with
95 additions
and
29 deletions
... | @@ -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 | } | ... | ... |
-
Please register or sign in to post a comment