|
1 # This patch comes from Oracle. It fixes issues preventing ftp-proxy |
|
2 # from building and running on Solaris. Especially, we: |
|
3 # - disabled features missing support on Solaris (queuing, rtable..) |
|
4 # where adding such support is not reasonable |
|
5 # - used workarounds to deal with missing pieces on Solaris (missing |
|
6 # structure members in sockaddr, PF not supporting divert-to, |
|
7 # using Solaris-specific random number generator) |
|
8 # |
|
9 # These changes are not going to upstream, they are Solaris-specific. |
|
10 |
|
11 diff -Naur ORIGINAL/Makefile ftp-proxy-OPENBSD_5_5-OPENBSD_5_5.pre-smf/Makefile |
|
12 --- ORIGINAL/Makefile 2006-11-26 03:31:13.000000000 -0800 |
|
13 +++ ftp-proxy-OPENBSD_5_5-OPENBSD_5_5.pre-smf/Makefile 2016-02-10 04:21:21.337202150 -0800 |
|
14 @@ -1,13 +1,29 @@ |
|
15 # $OpenBSD: Makefile,v 1.3 2006/11/26 11:31:13 deraadt Exp $ |
|
16 |
|
17 +CFLAGS+= -m64 -errwarn |
|
18 + |
|
19 PROG= ftp-proxy |
|
20 SRCS= ftp-proxy.c filter.c |
|
21 +OBJS=$(SRCS:.c=.o) |
|
22 MAN= ftp-proxy.8 |
|
23 |
|
24 -CFLAGS+= -I${.CURDIR} |
|
25 -CFLAGS+= -Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \ |
|
26 - -Wno-uninitialized |
|
27 -LDADD+= -levent |
|
28 -DPADD+= ${LIBEVENT} |
|
29 +LDADD+= -levent -luutil |
|
30 +LDFLAGS+= -z nolazyload |
|
31 + |
|
32 +all: $(SRCS) $(PROG) |
|
33 + |
|
34 +install: $(PROG) |
|
35 + $(INSTALL) -d $(PREFIX)/sbin |
|
36 + $(INSTALL) -m 755 $(PROG) $(PREFIX)/sbin |
|
37 + $(INSTALL) -d $(MANDIR)/man8 |
|
38 + $(INSTALL) -m 644 $(MAN) $(MANDIR)/man8 |
|
39 + |
|
40 +$(PROG): $(OBJS) |
|
41 + $(CC) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS) $(LDADD) |
|
42 + |
|
43 +.c.o: |
|
44 + $(CC) $(CFLAGS) -c -o $@ $< |
|
45 |
|
46 -.include <bsd.prog.mk> |
|
47 +clean: |
|
48 + rm -rf *.o |
|
49 + rm -rf $(PROG) |
|
50 diff -Naur ORIGINAL/filter.c ftp-proxy-OPENBSD_5_5-OPENBSD_5_5.pre-smf/filter.c |
|
51 --- ORIGINAL/filter.c 2012-09-18 03:11:53.000000000 -0700 |
|
52 +++ ftp-proxy-OPENBSD_5_5-OPENBSD_5_5.pre-smf/filter.c 2016-02-10 04:24:03.599069704 -0800 |
|
53 @@ -32,6 +32,10 @@ |
|
54 #include <stdio.h> |
|
55 #include <string.h> |
|
56 #include <unistd.h> |
|
57 +#ifdef _SOLARIS_ |
|
58 +/* we need _IOWR */ |
|
59 +#include <sys/ioccom.h> |
|
60 +#endif /* _SOLARIS_ */ |
|
61 |
|
62 #include "filter.h" |
|
63 |
|
64 diff -Naur ORIGINAL/ftp-proxy.8 ftp-proxy-OPENBSD_5_5-OPENBSD_5_5.pre-smf/ftp-proxy.8 |
|
65 --- ORIGINAL/ftp-proxy.8 2012-06-25 04:49:19.000000000 -0700 |
|
66 +++ ftp-proxy-OPENBSD_5_5-OPENBSD_5_5.pre-smf/ftp-proxy.8 2016-02-24 06:31:17.792565815 -0800 |
|
67 @@ -30,17 +30,16 @@ |
|
68 .Op Fl m Ar maxsessions |
|
69 .Op Fl P Ar port |
|
70 .Op Fl p Ar port |
|
71 -.Op Fl q Ar queue |
|
72 .Op Fl R Ar address |
|
73 .Op Fl T Ar tag |
|
74 .Op Fl t Ar timeout |
|
75 .Ek |
|
76 .Sh DESCRIPTION |
|
77 .Nm |
|
78 -is a proxy for the Internet File Transfer Protocol. |
|
79 -FTP control connections should be redirected into the proxy using the |
|
80 -.Xr pf 4 |
|
81 -.Ar divert-to |
|
82 +is a proxy for the Internet File Transfer Protocol making connections |
|
83 +over IPv4 NAT possible. |
|
84 +FTP control connections should be redirected into the proxy using the PF |
|
85 +.Ar rdr-to |
|
86 command, after which the proxy connects to the server on behalf of |
|
87 the client. |
|
88 .Pp |
|
89 @@ -51,22 +50,20 @@ |
|
90 Consequently, all connections from the server to the proxy have |
|
91 their destination address rewritten, so they are redirected to the |
|
92 client. |
|
93 -The proxy uses the |
|
94 -.Xr pf 4 |
|
95 +The proxy uses the PF |
|
96 .Ar anchor |
|
97 facility for this. |
|
98 .Pp |
|
99 Assuming the FTP control connection is from $client to $server, the |
|
100 -proxy connected to the server using the $proxy source address, and |
|
101 -$port is negotiated, then |
|
102 +proxy is connected to the server using the $proxy source address, and |
|
103 +$port is negotiated, the |
|
104 .Nm |
|
105 adds the following rules to the anchor. |
|
106 $server and $orig_server are the same unless |
|
107 .Fl R |
|
108 is used to force a different $server address for all connections. |
|
109 -(These example rules use inet, but the proxy also supports inet6.) |
|
110 .Pp |
|
111 -In case of active mode (PORT or EPRT): |
|
112 +In case of active mode (PORT): |
|
113 .Bd -literal -offset 2n |
|
114 pass in from $server to $proxy port $proxy_port \e |
|
115 rdr-to $client port $port |
|
116 @@ -74,7 +71,7 @@ |
|
117 nat-to $orig_server port $natport |
|
118 .Ed |
|
119 .Pp |
|
120 -In case of passive mode (PASV or EPSV): |
|
121 +In case of passive mode (PASV): |
|
122 .Bd -literal -offset 2n |
|
123 pass in from $client to $orig_server port $proxy_port \e |
|
124 rdr-to $server port $port |
|
125 @@ -83,11 +80,6 @@ |
|
126 .Pp |
|
127 The options are as follows: |
|
128 .Bl -tag -width Ds |
|
129 -.It Fl 6 |
|
130 -IPv6 mode. |
|
131 -The proxy will expect and use IPv6 addresses for all communication. |
|
132 -Only the extended FTP modes EPSV and EPRT are allowed with IPv6. |
|
133 -The proxy is in IPv4 mode by default. |
|
134 .It Fl A |
|
135 Only permit anonymous FTP connections. |
|
136 Either user "ftp" or user "anonymous" is allowed. |
|
137 @@ -96,14 +88,11 @@ |
|
138 connection to a server. |
|
139 .It Fl b Ar address |
|
140 Address where the proxy will listen for redirected control connections. |
|
141 -The default is 127.0.0.1, or ::1 in IPv6 mode. |
|
142 +The default is 127.0.0.1. |
|
143 .It Fl D Ar level |
|
144 Debug level, ranging from 0 to 7. |
|
145 Higher is more verbose. |
|
146 The default is 5. |
|
147 -(These levels correspond to the |
|
148 -.Xr syslog 3 |
|
149 -levels.) |
|
150 .It Fl d |
|
151 Do not daemonize. |
|
152 The process will stay in the foreground, logging to standard error. |
|
153 @@ -120,10 +109,6 @@ |
|
154 .It Fl p Ar port |
|
155 Port where the proxy will listen for redirected connections. |
|
156 The default is port 8021. |
|
157 -.It Fl q Ar queue |
|
158 -Create rules with queue |
|
159 -.Ar queue |
|
160 -appended, so that data connections can be queued. |
|
161 .It Fl R Ar address |
|
162 Fixed server address, also known as reverse mode. |
|
163 The proxy will always connect to the same server, regardless of |
|
164 @@ -142,9 +127,8 @@ |
|
165 keyword can be implemented following the |
|
166 .Nm |
|
167 anchor. |
|
168 -These rules can use special |
|
169 -.Xr pf 4 |
|
170 -features like route-to, reply-to, label, rtable, overload, etc. that |
|
171 +These rules can use special PF |
|
172 +features like route-to, reply-to, label, overload, etc. that |
|
173 .Nm |
|
174 does not implement itself. |
|
175 There must be a matching pass rule after the |
|
176 @@ -159,7 +143,9 @@ |
|
177 .It Fl v |
|
178 Set the 'log' flag on pf rules committed by |
|
179 .Nm . |
|
180 -Use twice to set the 'log all' flag. |
|
181 +Use twice to set the |
|
182 +.Sq log all |
|
183 +flag. |
|
184 The pf rules do not log by default. |
|
185 .El |
|
186 .Sh CONFIGURATION |
|
187 @@ -171,27 +157,23 @@ |
|
188 necessary. |
|
189 .Bd -literal -offset 2n |
|
190 anchor "ftp-proxy/*" |
|
191 -pass in quick inet proto tcp to port ftp divert-to 127.0.0.1 port 8021 |
|
192 +pass in quick inet proto tcp to port ftp rdr-to 127.0.0.1 port 8021 |
|
193 pass out inet proto tcp from (self) to any port ftp |
|
194 .Ed |
|
195 +.Pp |
|
196 +To run |
|
197 +.Nm |
|
198 +in a non-global zone, the |
|
199 +.Bd -literal -offset indent |
|
200 +svc:/network/socket-filter:pf_divert |
|
201 +.Ed |
|
202 +instance must be online in the global zone. |
|
203 .Sh SEE ALSO |
|
204 -.Xr ftp 1 , |
|
205 -.Xr pf 4 , |
|
206 .Xr pf.conf 5 |
|
207 .Sh CAVEATS |
|
208 -.Xr pf 4 |
|
209 -does not allow the ruleset to be modified if the system is running at a |
|
210 -.Xr securelevel 7 |
|
211 -higher than 1. |
|
212 -At that level |
|
213 -.Nm |
|
214 -cannot add rules to the anchors and FTP data connections may get blocked. |
|
215 .Pp |
|
216 Negotiated data connection ports below 1024 are not allowed. |
|
217 .Pp |
|
218 The negotiated IP address for active modes is ignored for security |
|
219 reasons. |
|
220 This makes third party file transfers impossible. |
|
221 -.Pp |
|
222 -.Nm |
|
223 -chroots to "/var/empty" and changes to user "proxy" to drop privileges. |
|
224 diff -Naur ORIGINAL/ftp-proxy.c ftp-proxy-OPENBSD_5_5-OPENBSD_5_5.pre-smf/ftp-proxy.c |
|
225 --- ORIGINAL/ftp-proxy.c 2013-03-15 06:31:27.000000000 -0700 |
|
226 +++ ftp-proxy-OPENBSD_5_5-OPENBSD_5_5.pre-smf/ftp-proxy.c 2016-02-10 04:12:16.600723376 -0800 |
|
227 @@ -38,9 +38,20 @@ |
|
228 #include <stdio.h> |
|
229 #include <stdlib.h> |
|
230 #include <string.h> |
|
231 +#ifdef _SOLARIS_ |
|
232 +#include <strings.h> |
|
233 +#include <sys/types.h> |
|
234 +#include <time.h> |
|
235 +#include <libuutil.h> |
|
236 +#include <sys/random.h> |
|
237 +#include <inttypes.h> |
|
238 +#include <priv.h> |
|
239 +#endif /* _SOLARIS_ */ |
|
240 #include <syslog.h> |
|
241 #include <unistd.h> |
|
242 +#ifndef _SOLARIS_ |
|
243 #include <vis.h> |
|
244 +#endif /* !_SOLARIS_ */ |
|
245 |
|
246 #include "filter.h" |
|
247 |
|
248 @@ -60,6 +71,32 @@ |
|
249 |
|
250 #define sstosa(ss) ((struct sockaddr *)(ss)) |
|
251 |
|
252 +#ifdef _SOLARIS_ |
|
253 +/* |
|
254 + * These constants are used as a range used by pick_proxy_port(). The ftp-proxy |
|
255 + * never binds these ports. They are used only within proxy_reply() and add_rdr() |
|
256 + * to be put into a FTP-protocol message and to construct the rule to be loaded |
|
257 + * into PF, respectively. |
|
258 + * |
|
259 + * OpenBSD adheres to a convention where these port numbers are reserved for |
|
260 + * connections that want to bypass a firewall. Surely, it depends on how the |
|
261 + * administrator configures the firewall, too. Let's stick to that convention |
|
262 + * here. The idea probably is "if the admin uses this convention, these ports |
|
263 + * are not filtered and thus we are not going to clash with current firewall |
|
264 + * rules". |
|
265 + */ |
|
266 +#define IPPORT_HIFIRSTAUTO 49152 |
|
267 +#define IPPORT_HILASTAUTO 65535 |
|
268 + |
|
269 +#define getrtable() 0 |
|
270 + |
|
271 +#ifndef LIST_END |
|
272 +#define LIST_END(x) NULL |
|
273 +#endif /* !LIST_END */ |
|
274 + |
|
275 +#define DIVERT_MODULE_NAME "pf_divertf" |
|
276 +#endif /* _SOLARIS_ */ |
|
277 + |
|
278 enum { CMD_NONE = 0, CMD_PORT, CMD_EPRT, CMD_PASV, CMD_EPSV }; |
|
279 |
|
280 struct session { |
|
281 @@ -115,12 +152,59 @@ |
|
282 |
|
283 struct event listen_ev, pause_accept_ev; |
|
284 struct sockaddr_storage fixed_server_ss, fixed_proxy_ss; |
|
285 +#ifdef _SOLARIS_ |
|
286 +static socklen_t fixed_server_ss_len; |
|
287 +static socklen_t fixed_proxy_ss_len; |
|
288 +#endif /* _SOLARIS_ */ |
|
289 char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port, |
|
290 *qname, *tagname; |
|
291 int anonymous_only, daemonize, id_count, ipv6_mode, loglevel, max_sessions, |
|
292 rfc_mode, session_count, timeout, verbose; |
|
293 extern char *__progname; |
|
294 |
|
295 +#ifdef _SOLARIS_ |
|
296 +/* |
|
297 + * fake_arc4random_uniform() |
|
298 + * This is a fake implementation of arc4random_uniform(). The wrapper |
|
299 + * provides so called uniform calculation of pseudo random number with |
|
300 + * respect to upper bound. |
|
301 + * |
|
302 + * Function calculates random numbers until it finds one outside |
|
303 + * <0, 2^32 % upper_bound) range. Once random number, `rand`, is selected, |
|
304 + * function returns rand % upper_bound. |
|
305 + * |
|
306 + * Arguments: |
|
307 + * upper_bound - random number is picked up in range <0, upper_bound) |
|
308 + * |
|
309 + * Returns: |
|
310 + * random number, uniform with respect to upper bound. |
|
311 + * Returns UINT32_MAX on error. |
|
312 + */ |
|
313 +static u_int32_t |
|
314 +fake_arc4random_uniform(u_int32_t upper_bound) |
|
315 +{ |
|
316 + u_int32_t rand, min; |
|
317 + |
|
318 + if (upper_bound < 2) |
|
319 + return (0); |
|
320 + |
|
321 + /* |
|
322 + * 2**32 % x == (2**32 - x) % x |
|
323 + * (Trick comes from OpenBSD, arc4random_uniform.c) |
|
324 + */ |
|
325 + min = -upper_bound % upper_bound; |
|
326 + for (;;) { |
|
327 + if (getrandom(&rand, sizeof (rand), GRND_NONBLOCK) != |
|
328 + sizeof (rand)) |
|
329 + return (UINT32_MAX); |
|
330 + if (rand >= min) |
|
331 + break; |
|
332 + } |
|
333 + |
|
334 + return (rand % upper_bound); |
|
335 +} |
|
336 +#endif /* _SOLARIS_ */ |
|
337 + |
|
338 void |
|
339 client_error(struct bufferevent *bufev, short what, void *arg) |
|
340 { |
|
341 @@ -220,6 +304,12 @@ |
|
342 return (0); |
|
343 } |
|
344 s->proxy_port = pick_proxy_port(); |
|
345 +#ifdef _SOLARIS_ |
|
346 + if (s->proxy_port == UINT16_MAX) { |
|
347 + logmsg(LOG_CRIT, "pick_proxy_port() failed"); |
|
348 + return (0); |
|
349 + } |
|
350 +#endif /* _SOLARIS_ */ |
|
351 proxy_reply(s->cmd, sstosa(&s->proxy_ss), s->proxy_port); |
|
352 logmsg(LOG_DEBUG, "#%d proxy: %s", s->id, linebuf); |
|
353 } |
|
354 @@ -378,13 +468,30 @@ |
|
355 struct sockaddr *proxy_to_server_sa; |
|
356 struct session *s; |
|
357 socklen_t len; |
|
358 +#ifdef _SOLARIS_ |
|
359 + socklen_t client_sa_len, server_sa_len; |
|
360 + int one = 1; /* parameter for setsockopt */ |
|
361 +#endif /* _SOLARIS_ */ |
|
362 int client_fd, fc, on; |
|
363 - |
|
364 + /* |
|
365 + * We experienced big problems when event_add() was called |
|
366 + * before accepting the incoming connection - for some reason, |
|
367 + * a new event was fired immediately and ftp-proxy was hanged |
|
368 + * trying to accept another client that was not there yet. |
|
369 + * Moving event_add() call a few lines below resolved this |
|
370 + * problem. |
|
371 + */ |
|
372 +#ifndef _SOLARIS_ |
|
373 event_add(&listen_ev, NULL); |
|
374 +#endif /* !_SOLARIS_ */ |
|
375 |
|
376 - if ((event & EV_TIMEOUT)) |
|
377 + if ((event & EV_TIMEOUT)) { |
|
378 +#ifdef _SOLARIS_ |
|
379 + event_add(&listen_ev, NULL); |
|
380 +#endif /* _SOLARIS_ */ |
|
381 /* accept() is no longer paused. */ |
|
382 return; |
|
383 + } |
|
384 |
|
385 /* |
|
386 * We _must_ accept the connection, otherwise libevent will keep |
|
387 @@ -393,6 +500,9 @@ |
|
388 client_sa = sstosa(&tmp_ss); |
|
389 len = sizeof(struct sockaddr_storage); |
|
390 if ((client_fd = accept(listen_fd, client_sa, &len)) < 0) { |
|
391 +#ifdef _SOLARIS_ |
|
392 + event_add(&listen_ev, NULL); |
|
393 +#endif /* _SOLARIS_ */ |
|
394 logmsg(LOG_CRIT, "accept() failed: %s", strerror(errno)); |
|
395 |
|
396 /* |
|
397 @@ -410,6 +520,16 @@ |
|
398 return; |
|
399 } |
|
400 |
|
401 +#ifdef _SOLARIS_ |
|
402 + event_add(&listen_ev, NULL); |
|
403 + |
|
404 + /* |
|
405 + * Struct sockaddr does not contain sa_len field on Solaris, |
|
406 + * we use client_sa_len instead. |
|
407 + */ |
|
408 + client_sa_len = len; |
|
409 +#endif /* _SOLARIS_ */ |
|
410 + |
|
411 /* Refuse connection if the maximum is reached. */ |
|
412 if (session_count >= max_sessions) { |
|
413 logmsg(LOG_ERR, "client limit (%d) reached, refusing " |
|
414 @@ -426,8 +546,11 @@ |
|
415 return; |
|
416 } |
|
417 s->client_fd = client_fd; |
|
418 +#ifdef _SOLARIS_ |
|
419 + memcpy(sstosa(&s->client_ss), client_sa, client_sa_len); |
|
420 +#else /* !_SOLARIS_ */ |
|
421 memcpy(sstosa(&s->client_ss), client_sa, client_sa->sa_len); |
|
422 - |
|
423 +#endif /* _SOLARIS_ */ |
|
424 /* Cast it once, and be done with it. */ |
|
425 client_sa = sstosa(&s->client_ss); |
|
426 server_sa = sstosa(&s->server_ss); |
|
427 @@ -447,6 +570,17 @@ |
|
428 strerror(errno)); |
|
429 goto fail; |
|
430 } |
|
431 +#ifdef _SOLARIS_ |
|
432 + /* |
|
433 + * Struct sockaddr does not contain sa_len field on Solaris, |
|
434 + * we use server_sa_len instead. |
|
435 + */ |
|
436 + server_sa_len = len; |
|
437 +#endif /* _SOLARIS_ */ |
|
438 +/* SO_RTABLE not defined on Solaris */ |
|
439 +#ifdef _SOLARIS_ |
|
440 + s->client_rd = 0; |
|
441 +#else /* !_SOLARIS_ */ |
|
442 len = sizeof(s->client_rd); |
|
443 if (getsockopt(s->client_fd, SOL_SOCKET, SO_RTABLE, &s->client_rd, |
|
444 &len) && errno != ENOPROTOOPT) { |
|
445 @@ -454,10 +588,18 @@ |
|
446 strerror(errno)); |
|
447 goto fail; |
|
448 } |
|
449 +#endif /* _SOLARIS_ */ |
|
450 if (fixed_server) { |
|
451 +#ifdef _SOLARIS_ |
|
452 + memcpy(sstosa(&s->orig_server_ss), server_sa, |
|
453 + server_sa_len); |
|
454 + memcpy(server_sa, fixed_server_sa, fixed_server_ss_len); |
|
455 + server_sa_len = fixed_server_ss_len; /* update the length */ |
|
456 +#else /* !_SOLARIS_ */ |
|
457 memcpy(sstosa(&s->orig_server_ss), server_sa, |
|
458 server_sa->sa_len); |
|
459 memcpy(server_sa, fixed_server_sa, fixed_server_sa->sa_len); |
|
460 +#endif /* _SOLARIS_ */ |
|
461 } |
|
462 |
|
463 /* XXX: check we are not connecting to ourself. */ |
|
464 @@ -471,8 +613,14 @@ |
|
465 strerror(errno)); |
|
466 goto fail; |
|
467 } |
|
468 +#ifdef _SOLARIS_ |
|
469 if (fixed_proxy && bind(s->server_fd, sstosa(&fixed_proxy_ss), |
|
470 - fixed_proxy_ss.ss_len) != 0) { |
|
471 + fixed_proxy_ss_len) != 0) |
|
472 +#else /* !_SOLARIS_ */ |
|
473 + if (fixed_proxy && bind(s->server_fd, sstosa(&fixed_proxy_ss), |
|
474 + fixed_proxy_ss.ss_len) != 0) |
|
475 +#endif /* _SOLARIS_ */ |
|
476 + { |
|
477 logmsg(LOG_CRIT, "#%d cannot bind fixed proxy address: %s", |
|
478 s->id, strerror(errno)); |
|
479 goto fail; |
|
480 @@ -485,8 +633,14 @@ |
|
481 s->id, strerror(errno)); |
|
482 goto fail; |
|
483 } |
|
484 +#ifdef _SOLARIS_ |
|
485 + if (connect(s->server_fd, server_sa, server_sa_len) < 0 && |
|
486 + errno != EINPROGRESS) |
|
487 +#else /* !_SOLARIS_ */ |
|
488 if (connect(s->server_fd, server_sa, server_sa->sa_len) < 0 && |
|
489 - errno != EINPROGRESS) { |
|
490 + errno != EINPROGRESS) |
|
491 +#endif /* _SOLARIS_ */ |
|
492 + { |
|
493 logmsg(LOG_CRIT, "#%d proxy cannot connect to server %s: %s", |
|
494 s->id, sock_ntop(server_sa), strerror(errno)); |
|
495 goto fail; |
|
496 @@ -592,6 +746,9 @@ |
|
497 /* syslog does its own vissing. */ |
|
498 vsyslog(pri, message, ap); |
|
499 else { |
|
500 +#ifdef _SOLARIS_ |
|
501 + vsyslog(pri, message, ap); |
|
502 +#else /* !_SOLARIS_ */ |
|
503 char buf[MAX_LOGLINE]; |
|
504 char visbuf[2 * MAX_LOGLINE]; |
|
505 |
|
506 @@ -599,6 +756,7 @@ |
|
507 vsnprintf(buf, sizeof buf, message, ap); |
|
508 strnvis(visbuf, buf, sizeof visbuf, VIS_CSTYLE | VIS_NL); |
|
509 fprintf(stderr, "%s\n", visbuf); |
|
510 +#endif /* _SOLARIS_ */ |
|
511 } |
|
512 |
|
513 va_end(ap); |
|
514 @@ -636,9 +794,11 @@ |
|
515 |
|
516 while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rT:t:v")) != -1) { |
|
517 switch (ch) { |
|
518 +#ifndef _SOLARIS_ |
|
519 case '6': |
|
520 ipv6_mode = 1; |
|
521 break; |
|
522 +#endif /* !_SOLARIS_ */ |
|
523 case 'A': |
|
524 anonymous_only = 1; |
|
525 break; |
|
526 @@ -668,11 +828,13 @@ |
|
527 case 'p': |
|
528 listen_port = optarg; |
|
529 break; |
|
530 +#ifndef _SOLARIS_ |
|
531 case 'q': |
|
532 if (strlen(optarg) >= PF_QNAME_SIZE) |
|
533 errx(1, "queuename too long"); |
|
534 qname = optarg; |
|
535 break; |
|
536 +#endif /* !_SOLARIS_ */ |
|
537 case 'R': |
|
538 fixed_server = optarg; |
|
539 break; |
|
540 @@ -718,9 +880,16 @@ |
|
541 hints.ai_socktype = SOCK_STREAM; |
|
542 error = getaddrinfo(fixed_proxy, NULL, &hints, &res); |
|
543 if (error) |
|
544 - errx(1, "getaddrinfo fixed proxy address failed: %s", |
|
545 + errx(1, "getaddrinfo fixed proxy address (%s) failed: %s", fixed_proxy, |
|
546 gai_strerror(error)); |
|
547 memcpy(&fixed_proxy_ss, res->ai_addr, res->ai_addrlen); |
|
548 +#ifdef _SOLARIS_ |
|
549 + /* |
|
550 + * struct sockaddr_storage does not have the member |
|
551 + * ss_len on Solaris, thus we use a global variable. |
|
552 + */ |
|
553 + fixed_proxy_ss_len = res->ai_addrlen; |
|
554 +#endif /* _SOLARIS_ */ |
|
555 logmsg(LOG_INFO, "using %s to connect to servers", |
|
556 sock_ntop(sstosa(&fixed_proxy_ss))); |
|
557 freeaddrinfo(res); |
|
558 @@ -736,6 +905,13 @@ |
|
559 errx(1, "getaddrinfo fixed server address failed: %s", |
|
560 gai_strerror(error)); |
|
561 memcpy(&fixed_server_ss, res->ai_addr, res->ai_addrlen); |
|
562 +#ifdef _SOLARIS_ |
|
563 + /* |
|
564 + * struct sockaddr_storage does not have the member |
|
565 + * ss_len on Solaris, thus we use a global variable. |
|
566 + */ |
|
567 + fixed_server_ss_len = res->ai_addrlen; |
|
568 +#endif /* _SOLARIS_ */ |
|
569 logmsg(LOG_INFO, "using fixed server %s", |
|
570 sock_ntop(sstosa(&fixed_server_ss))); |
|
571 freeaddrinfo(res); |
|
572 @@ -752,6 +928,11 @@ |
|
573 gai_strerror(error)); |
|
574 if ((listenfd = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP)) == -1) |
|
575 errx(1, "socket failed"); |
|
576 +#ifdef _SOLARIS_ |
|
577 + if (setsockopt(listenfd, SOL_FILTER, FIL_ATTACH, DIVERT_MODULE_NAME, |
|
578 + (strlen(DIVERT_MODULE_NAME)+1)) != 0) |
|
579 + err(1, "setsockopt failed - unable to attach filter"); |
|
580 +#endif /* _SOLARIS_ */ |
|
581 on = 1; |
|
582 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, |
|
583 sizeof on) != 0) |
|
584 @@ -782,7 +963,11 @@ |
|
585 event_init(); |
|
586 |
|
587 /* Setup signal handler. */ |
|
588 +#ifdef _SOLARIS_ |
|
589 + sigset(SIGPIPE, SIG_IGN); |
|
590 +#else /* !_SOLARIS_ */ |
|
591 signal(SIGPIPE, SIG_IGN); |
|
592 +#endif /* _SOLARIS_ */ |
|
593 signal_set(&ev_sighup, SIGHUP, handle_signal, NULL); |
|
594 signal_set(&ev_sigint, SIGINT, handle_signal, NULL); |
|
595 signal_set(&ev_sigterm, SIGTERM, handle_signal, NULL); |
|
596 @@ -857,12 +1042,25 @@ |
|
597 return (0); |
|
598 } |
|
599 |
|
600 +/* |
|
601 + * On Solaris, fake_arc4random_uniform() can fail. We return UINT16_MAX |
|
602 + * on error. |
|
603 + */ |
|
604 u_int16_t |
|
605 pick_proxy_port(void) |
|
606 { |
|
607 +#ifdef _SOLARIS_ |
|
608 + u_int32_t shift; |
|
609 + |
|
610 + shift = fake_arc4random_uniform(IPPORT_HILASTAUTO - IPPORT_HIFIRSTAUTO); |
|
611 + if (shift == UINT32_MAX) |
|
612 + return UINT16_MAX; |
|
613 + return (IPPORT_HIFIRSTAUTO + shift); |
|
614 +#else /* !_SOLARIS_ */ |
|
615 /* Random should be good enough for avoiding port collisions. */ |
|
616 return (IPPORT_HIFIRSTAUTO + |
|
617 arc4random_uniform(IPPORT_HILASTAUTO - IPPORT_HIFIRSTAUTO)); |
|
618 +#endif /* _SOLARIS_ */ |
|
619 } |
|
620 |
|
621 void |
|
622 @@ -985,6 +1183,12 @@ |
|
623 return (0); |
|
624 } |
|
625 s->proxy_port = pick_proxy_port(); |
|
626 +#ifdef _SOLARIS_ |
|
627 + if (s->proxy_port == UINT16_MAX) { |
|
628 + logmsg(LOG_CRIT, "pick_proxy_port() failed"); |
|
629 + return (0); |
|
630 + } |
|
631 +#endif /* _SOLARIS_ */ |
|
632 logmsg(LOG_INFO, "#%d passive: client to server port %d" |
|
633 " via port %d", s->id, s->port, s->proxy_port); |
|
634 |
|
635 @@ -1126,6 +1330,6 @@ |
|
636 fprintf(stderr, "usage: %s [-6Adrv] [-a address] [-b address]" |
|
637 " [-D level] [-m maxsessions]\n [-P port]" |
|
638 " [-p port] [-q queue] [-R address] [-T tag]\n" |
|
639 - " [-t timeout]\n", __progname); |
|
640 + " [-t timeout]\n", __progname); |
|
641 exit(1); |
|
642 } |