"Fossies" - the Fresh Open Source Software Archive 
Member "portfwd-0.29/src/host_map.cc" (8 May 2002, 10443 Bytes) of package /linux/privat/old/portfwd-0.29.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*
2 host_map.cc
3
4 $Id: host_map.cc,v 1.15 2002/05/08 03:50:03 evertonm Exp $
5 */
6
7 #include <string.h>
8 #include <syslog.h>
9 #include <errno.h>
10 #include <sys/time.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
16 #include "portfwd.h"
17 #include "host_map.hpp"
18 #include "solve.h"
19
20 void host_map::show() const
21 {
22 iterator<vector<from_addr*>,from_addr*> it(*src_list);
23 it.start();
24 if (it.cont()) {
25 it.get()->show();
26 it.next();
27 }
28 for (; it.cont(); it.next()) {
29 syslog(LOG_INFO, ", ");
30 it.get()->show();
31 }
32
33 syslog(LOG_INFO, " => ");
34
35 iterator<vector<to_addr*>,to_addr*> it2(*dst_list);
36 it2.start();
37 if (it2.cont()) {
38 it2.get()->show();
39 it2.next();
40 }
41 for (; it2.cont(); it2.next()) {
42 syslog(LOG_INFO, ", ");
43 it2.get()->show();
44 }
45 }
46
47 static int make_tcp_outgoing_socket(const struct ip_addr *src, const struct sockaddr_in *cli_sa, unsigned int cli_sa_len)
48 {
49 /*
50 * Open socket for remote host
51 */
52 int rsd = socket(PF_INET, SOCK_STREAM, get_protonumber(P_TCP));
53 if (rsd == -1) {
54 syslog(LOG_ERR, "make_tcp_outgoing_socket: Can't create TCP socket: %m");
55 return -1;
56 }
57 DEBUGFD(syslog(LOG_DEBUG, "make_tcp_outgoing_socket: socket open: FD %d", rsd));
58
59 /*
60 * Bind to user-supplied source address
61 *
62 * NOTE: This overrides transparent proxying.
63 */
64 if (src) {
65
66 #ifdef HAVE_MSG_PROXY
67 if (transparent_proxy)
68 syslog(LOG_WARNING, "User-supplied source-address overriding transparent proxying for TCP socket");
69 #endif
70
71 struct sockaddr_in local_sa;
72 unsigned int local_sa_len = sizeof(local_sa);
73 local_sa.sin_family = PF_INET;
74 local_sa.sin_port = htons(0);
75 local_sa.sin_addr.s_addr = *((unsigned int *) src->addr);
76
77 ONVERBOSE(syslog(LOG_INFO, "make_tcp_outgoing_socket: Binding to local source address: %s:%d", inet_ntoa(local_sa.sin_addr), htons(local_sa.sin_port)));
78
79 /*
80 * Bind local socket to user-supplied source address
81 */
82 if (bind(rsd, (struct sockaddr *) &local_sa, local_sa_len)) {
83 syslog(LOG_ERR, "make_tcp_outgoing_socket: Can't bind TCP socket to local source address: %s:%d: %m", inet_ntoa(local_sa.sin_addr), ntohs(local_sa.sin_port));
84 socket_close(rsd);
85 return -1;
86 }
87
88 }
89
90 #ifndef HAVE_MSG_PROXY
91 ;
92 #else
93
94 else
95
96 /*
97 * Perform transparent proxy
98 *
99 * NOTE: User-supplied source address overrides transparent proxying.
100 */
101 if (transparent_proxy) {
102
103 struct sockaddr_in local_sa;
104 unsigned int local_sa_len = sizeof(local_sa);
105
106 /*
107 * Copy client address
108 */
109 memcpy(&local_sa, cli_sa, cli_sa_len);
110 local_sa.sin_port = htons(0);
111
112 ONVERBOSE(syslog(LOG_INFO, "make_tcp_outgoing_socket: Transparent proxy - Binding to local address: %s:%d", inet_ntoa(local_sa.sin_addr), htons(local_sa.sin_port)));
113
114 /*
115 * Bind local socket to client address
116 */
117 if (bind(rsd, (struct sockaddr *) &local_sa, local_sa_len)) {
118 syslog(LOG_ERR, "make_tcp_outgoing_socket: Can't bind TCP socket to client address: %m: %s:%d", inet_ntoa(local_sa.sin_addr), ntohs(local_sa.sin_port));
119 socket_close(rsd);
120 return -1;
121 }
122
123 } /* else if (transparent_proxy) */
124 #endif /* HAVE_MSG_PROXY */
125
126 return rsd;
127 }
128
129 /*
130 * Returns -1 on failure; 0 on success.
131 */
132 int host_map::pipe(int *sd, const struct sockaddr_in *cli_sa,
133 unsigned int cli_sa_len, const struct ip_addr *ip,
134 int port, const struct ip_addr *src,
135 const struct sockaddr_in *local_cli_sa)
136 {
137 const int tmp_len = 32;
138 char tmp[tmp_len];
139
140 /*
141 * Scan all destination addresses
142 */
143
144 /* Save starting address */
145 int last_dst_index = next_dst_index;
146
147 for (;;) {
148
149 safe_strcpy(tmp, addrtostr(ip), tmp_len);
150
151 /*
152 * Get current destination address
153 */
154 to_addr *dst_addr = dst_list->get_at(next_dst_index);
155
156 const struct ip_addr *dst_ip;
157 int dst_port;
158 if (dst_addr->get_addr(get_protoname(P_TCP), cli_sa, local_cli_sa, &dst_ip, &dst_port)) {
159 ONVERBOSE(syslog(LOG_INFO, "TCP pipe: Could not load next destination address for: %s:%d", tmp, port));
160 return -1;
161 }
162
163 ONVERBOSE2(syslog(LOG_DEBUG, "TCP pipe: trying: %s:%d => %s:%d", tmp, port, addrtostr(dst_ip), dst_port));
164
165 /*
166 * Create outgoing socket
167 */
168 int rsd = make_tcp_outgoing_socket(src, cli_sa, cli_sa_len);
169 if (rsd < 0) {
170 syslog(LOG_ERR, "TCP pipe: Could not create outgoing socket");
171 return -1;
172 }
173
174 /*
175 * Put current destination address in a "sockaddr_in" struct
176 */
177
178 struct sockaddr_in sa;
179 sa.sin_family = PF_INET;
180 sa.sin_port = htons(dst_port);
181 sa.sin_addr.s_addr = *((unsigned int *) dst_ip->addr);
182 memset((char *) sa.sin_zero, 0, sizeof(sa.sin_zero));
183
184 /*
185 * Try current destination address
186 */
187 if (connect(rsd, (struct sockaddr *) &sa, sizeof(sa))) {
188 ONVERBOSE(syslog(LOG_WARNING, "TCP pipe: Can't connect %s:%d to %s:%d: %m", tmp, port, inet_ntoa(sa.sin_addr), dst_port));
189
190 /*
191 * Close the socket, as it can't be reused
192 */
193 close(rsd);
194
195 /*
196 * Switch to next address
197 */
198 next_dst_index = (next_dst_index + 1) % dst_list->get_size();
199
200 /*
201 * If all addresses were tried without success, give up
202 */
203 if (next_dst_index == last_dst_index) {
204 syslog(LOG_ERR, "TCP pipe: Can't forward incoming connection from %s:%d to any destination", tmp, port);
205 return -1;
206 }
207
208 continue;
209 }
210
211 /*
212 * Here we have a good outgoing connection on "rsd"
213 */
214
215 /*
216 * Return outgoing socket
217 */
218 *sd = rsd;
219
220 ONVERBOSE2(syslog(LOG_DEBUG, "TCP pipe: connected: %s:%d => %s:%d", tmp, port, addrtostr(dst_ip), dst_port));
221
222 break;
223 }
224
225 /*
226 * Switch to next destination address
227 * (left ready for the next incoming connection)
228 */
229 next_dst_index = (next_dst_index + 1) % dst_list->get_size();
230
231 return 0;
232 }
233
234 /*
235 * Returns -1 on failure; file descriptor on success.
236 */
237 int host_map::tcp_match(const struct ip_addr *ip, int port) const
238 {
239 iterator<vector<from_addr*>,from_addr*> it(*src_list);
240 for (it.start(); it.cont(); it.next()) {
241 if (it.get()->match(ip, port))
242 return -1;
243 }
244
245 return 0;
246 }
247
248 void host_map::udp_forward(const struct ip_addr *source,
249 const struct sockaddr_in *cli_sa,
250 const struct sockaddr_in *local_cli_sa,
251 const struct ip_addr *ip, int port,
252 const char *buf, int buf_len)
253 {
254 /*
255 * Get next destination address
256 */
257 to_addr *dst_addr = dst_list->get_at(next_dst_index);
258
259 const struct ip_addr *dst_ip;
260 int dst_port;
261 if (dst_addr->get_addr(get_protoname(P_UDP), cli_sa, local_cli_sa, &dst_ip, &dst_port)) {
262
263 const int tmp_len = 32;
264 char tmp[tmp_len];
265 safe_strcpy(tmp, addrtostr(ip), tmp_len);
266
267 ONVERBOSE(syslog(LOG_INFO, "host_map::udp_forward(): Could not load next destination address for: %s:%d", tmp, port));
268
269 return;
270 }
271
272 {
273 const int tmp_len = 32;
274 char tmp[tmp_len];
275
276 ONVERBOSE(safe_strcpy(tmp, addrtostr(ip), tmp_len));
277 ONVERBOSE(syslog(LOG_DEBUG, "host_map::udp_forward(): %s:%d => %s:%d", tmp, port, addrtostr(dst_ip), dst_port));
278 }
279
280 int rsd = socket(PF_INET, SOCK_DGRAM, get_protonumber(P_UDP));
281 if (rsd == -1) {
282 syslog(LOG_ERR, "host_map::udp_forward(): Can't create UDP socket: %m");
283 return;
284 }
285
286 /*
287 * Allow outgoing broadcast datagrams
288 */
289 #ifndef NO_SO_BROADCAST
290 {
291 int one = 1;
292
293 ONVERBOSE2(syslog(LOG_DEBUG, "Setting SO_BROADCAST for outgoing UDP socket"));
294
295 if (setsockopt(rsd, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof(one)))
296 syslog(LOG_ERR, "host_map::udp_forward(): Can't allow broadcast datagrams for outgoing UDP socket: setsockopt(SO_BROADCAST) failed: %m");
297 }
298 #endif /* NO_SO_BROADCAST */
299
300 struct sockaddr_in local_sa;
301
302 /*
303 * Bind to user-supplied source address
304 *
305 * NOTE: This overrides transparent proxying.
306 */
307 if (source) {
308
309 #ifdef HAVE_MSG_PROXY
310 if (transparent_proxy)
311 syslog(LOG_WARNING, "User-supplied source-address overriding transparent proxying for UDP socket");
312 #endif
313
314 local_sa.sin_family = PF_INET;
315 local_sa.sin_port = htons(0);
316 local_sa.sin_addr.s_addr = *((unsigned int *) source->addr);
317
318 ONVERBOSE2(syslog(LOG_ERR, "host_map::udp_forward: \"Binding\" to local source address: %s:%d", inet_ntoa(local_sa.sin_addr), ntohs(local_sa.sin_port)));
319
320 }
321
322 #ifndef HAVE_MSG_PROXY
323 ;
324 #else
325
326 else
327
328 /*
329 * Perform transparent proxy
330 *
331 * NOTE: User-supplied source address overrides transparent proxying.
332 */
333 if (transparent_proxy) {
334
335 unsigned int local_sa_len = sizeof(local_sa);
336
337 /*
338 * Copy client address
339 */
340 memcpy(&local_sa, cli_sa, local_sa_len);
341
342 ONVERBOSE2(syslog(LOG_ERR, "host_map::udp_forward: Transparent proxy - \"Binding\" to local address: %s:%d", inet_ntoa(local_sa.sin_addr), ntohs(local_sa.sin_port)));
343
344 } /* else if (transparent_proxy) */
345
346 #endif /* HAVE_MSG_PROXY */
347
348 /*
349 * Destination address
350 */
351 struct sockaddr_in sa;
352 sa.sin_family = PF_INET;
353 sa.sin_port = htons(dst_port);
354 sa.sin_addr.s_addr = *((unsigned int *) dst_ip->addr);
355 memset((char *) sa.sin_zero, 0, sizeof(sa.sin_zero));
356
357 #ifdef HAVE_MSG_PROXY
358 if (source || transparent_proxy)
359 #else
360 if (source)
361 #endif
362 memcpy((char *) sa.sin_zero, &local_sa, 8);
363
364 #ifdef HAVE_MSG_PROXY
365 int wr = sendto(rsd, buf, buf_len, \
366 ((source || transparent_proxy) ? MSG_PROXY : 0), \
367 (struct sockaddr *) &sa, sizeof(sa));
368 #else
369 int wr = sendto(rsd, buf, buf_len, 0, \
370 (struct sockaddr *) &sa, sizeof(sa));
371 #endif
372
373 if (wr < 0)
374 syslog(LOG_ERR, "forward: sendto() failed: %m");
375 else if (wr < buf_len)
376 syslog(LOG_ERR, "forward: Partial write on sendto: %m");
377
378 if (close(rsd))
379 syslog(LOG_WARNING, "forward: close() on socket failed: %m");
380
381 /*
382 * Switch to next address
383 */
384 next_dst_index = (next_dst_index + 1) % dst_list->get_size();
385 }
386
387 /*
388 * -1 = match; 0 = miss.
389 */
390 int host_map::udp_match(const struct ip_addr *ip, int port, const char *buf, int buf_len) const
391 {
392 iterator<vector<from_addr*>,from_addr*> it(*src_list);
393 for (it.start(); it.cont(); it.next())
394 if (it.get()->match(ip, port))
395 return -1;
396
397 return 0;
398 }
399
400 /* Eof: host_map.cc */