Re: Make Passive mode the default for Net::FTP
[p5sagit/p5-mst-13.2.git] / lib / Net / Config.pm
1 # Net::Config.pm
2 #
3 # Copyright (c) 2000 Graham Barr <gbarr@pobox.com>. All rights reserved.
4 # This program is free software; you can redistribute it and/or
5 # modify it under the same terms as Perl itself.
6
7 package Net::Config;
8
9 require Exporter;
10 use vars qw(@ISA @EXPORT %NetConfig $VERSION $CONFIGURE $LIBNET_CFG);
11 use Socket qw(inet_aton inet_ntoa);
12 use strict;
13
14 @EXPORT  = qw(%NetConfig);
15 @ISA     = qw(Net::LocalCfg Exporter);
16 $VERSION = "1.10"; # $Id: //depot/libnet/Net/Config.pm#17 $
17
18 eval { local $SIG{__DIE__}; require Net::LocalCfg };
19
20 %NetConfig = (
21     nntp_hosts => [],
22     snpp_hosts => [],
23     pop3_hosts => [],
24     smtp_hosts => [],
25     ph_hosts => [],
26     daytime_hosts => [],
27     time_hosts => [],
28     inet_domain => undef,
29     ftp_firewall => undef,
30     ftp_ext_passive => 1,
31     ftp_int_passive => 1,
32     test_hosts => 1,
33     test_exist => 1,
34 );
35
36 #
37 # Try to get as much configuration info as possible from InternetConfig
38 #
39 $^O eq 'MacOS' and eval <<TRY_INTERNET_CONFIG;
40 use Mac::InternetConfig;
41
42 {
43 my %nc = (
44     nntp_hosts      => [ \$InternetConfig{ kICNNTPHost() } ],
45     pop3_hosts      => [ \$InternetConfig{ kICMailAccount() } =~ /\@(.*)/ ],
46     smtp_hosts      => [ \$InternetConfig{ kICSMTPHost() } ],
47     ftp_testhost    => \$InternetConfig{ kICFTPHost() } ? \$InternetConfig{ kICFTPHost()} : undef,
48     ph_hosts        => [ \$InternetConfig{ kICPhHost() }   ],
49     ftp_ext_passive => \$InternetConfig{"646F676F\xA5UsePassiveMode"} || 0,
50     ftp_int_passive => \$InternetConfig{"646F676F\xA5UsePassiveMode"} || 0,
51     socks_hosts     => 
52         \$InternetConfig{ kICUseSocks() }    ? [ \$InternetConfig{ kICSocksHost() }    ] : [],
53     ftp_firewall    => 
54         \$InternetConfig{ kICUseFTPProxy() } ? [ \$InternetConfig{ kICFTPProxyHost() } ] : [],
55 );
56 \@NetConfig{keys %nc} = values %nc;
57 }
58 TRY_INTERNET_CONFIG
59
60 my $file = __FILE__;
61 my $ref;
62 $file =~ s/Config.pm/libnet.cfg/;
63 if ( -f $file ) {
64     $ref = eval { local $SIG{__DIE__}; do $file };
65     if (ref($ref) eq 'HASH') {
66         %NetConfig = (%NetConfig, %{ $ref });
67         $LIBNET_CFG = $file;
68     }
69 }
70 if ($< == $> and !$CONFIGURE)  {
71     my $home = eval { local $SIG{__DIE__}; (getpwuid($>))[7] } || $ENV{HOME};
72     $home ||= $ENV{HOMEDRIVE} . ($ENV{HOMEPATH}||'') if defined $ENV{HOMEDRIVE};
73     if (defined $home) {
74         $file = $home . "/.libnetrc";
75         $ref = eval { local $SIG{__DIE__}; do $file } if -f $file;
76         %NetConfig = (%NetConfig, %{ $ref })
77             if ref($ref) eq 'HASH';     
78     }
79 }
80 my ($k,$v);
81 while(($k,$v) = each %NetConfig) {
82         $NetConfig{$k} = [ $v ]
83                 if($k =~ /_hosts$/ and $k ne "test_hosts" and defined($v) and !ref($v));
84 }
85
86 # Take a hostname and determine if it is inside the firewall
87
88 sub requires_firewall {
89     shift; # ignore package
90     my $host = shift;
91
92     return 0 unless defined $NetConfig{'ftp_firewall'};
93
94     $host = inet_aton($host) or return -1;
95     $host = inet_ntoa($host);
96
97     if(exists $NetConfig{'local_netmask'}) {
98         my $quad = unpack("N",pack("C*",split(/\./,$host)));
99         my $list = $NetConfig{'local_netmask'};
100         $list = [$list] unless ref($list);
101         foreach (@$list) {
102             my($net,$bits) = (m#^(\d+\.\d+\.\d+\.\d+)/(\d+)$#) or next;
103             my $mask = ~0 << (32 - $bits);
104             my $addr = unpack("N",pack("C*",split(/\./,$net)));
105
106             return 0 if (($addr & $mask) == ($quad & $mask));
107         }
108         return 1;
109     }
110
111     return 0;
112 }
113
114 use vars qw(*is_external);
115 *is_external = \&requires_firewall;
116
117 1;
118
119 __END__
120
121 =head1 NAME
122
123 Net::Config - Local configuration data for libnet
124
125 =head1 SYNOPSYS
126
127     use Net::Config qw(%NetConfig);
128
129 =head1 DESCRIPTION
130
131 C<Net::Config> holds configuration data for the modules in the libnet
132 distribution. During installation you will be asked for these values.
133
134 The configuration data is held globally in a file in the perl installation
135 tree, but a user may override any of these values by providing their own. This
136 can be done by having a C<.libnetrc> file in their home directory. This file
137 should return a reference to a HASH containing the keys described below.
138 For example
139
140     # .libnetrc
141     {
142         nntp_hosts => [ "my_preferred_host" ],
143         ph_hosts   => [ "my_ph_server" ],
144     }
145     __END__
146
147 =head1 METHODS
148
149 C<Net::Config> defines the following methods. They are methods as they are
150 invoked as class methods. This is because C<Net::Config> inherits from
151 C<Net::LocalCfg> so you can override these methods if you want.
152
153 =over 4
154
155 =item requires_firewall HOST
156
157 Attempts to determine if a given host is outside your firewall. Possible
158 return values are.
159
160   -1  Cannot lookup hostname
161    0  Host is inside firewall (or there is no ftp_firewall entry)
162    1  Host is outside the firewall
163
164 This is done by using hostname lookup and the C<local_netmask> entry in
165 the configuration data.
166
167 =back
168
169 =head1 NetConfig VALUES
170
171 =over 4
172
173 =item nntp_hosts
174
175 =item snpp_hosts
176
177 =item pop3_hosts
178
179 =item smtp_hosts
180
181 =item ph_hosts
182
183 =item daytime_hosts
184
185 =item time_hosts
186
187 Each is a reference to an array of hostnames (in order of preference),
188 which should be used for the given protocol
189
190 =item inet_domain
191
192 Your internet domain name
193
194 =item ftp_firewall
195
196 If you have an FTP proxy firewall (B<NOT> an HTTP or SOCKS firewall)
197 then this value should be set to the firewall hostname. If your firewall
198 does not listen to port 21, then this value should be set to
199 C<"hostname:port"> (eg C<"hostname:99">)
200
201 =item ftp_firewall_type
202
203 There are many different ftp firewall products available. But unfortunately
204 there is no standard for how to traverse a firewall.  The list below shows the
205 sequence of commands that Net::FTP will use
206
207   user        Username for remote host
208   pass        Password for remote host
209   fwuser      Username for firewall
210   fwpass      Password for firewall
211   remote.host The hostname of the remote ftp server
212
213 =over 4
214
215 =item 0
216
217 There is no firewall
218
219 =item 1
220
221      USER user@remote.host
222      PASS pass
223
224 =item 2
225
226      USER fwuser
227      PASS fwpass
228      USER user@remote.host
229      PASS pass
230
231 =item 3
232
233      USER fwuser
234      PASS fwpass
235      SITE remote.site
236      USER user
237      PASS pass
238
239 =item 4
240
241      USER fwuser
242      PASS fwpass
243      OPEN remote.site
244      USER user
245      PASS pass
246
247 =item 5
248
249      USER user@fwuser@remote.site
250      PASS pass@fwpass
251
252 =item 6
253
254      USER fwuser@remote.site
255      PASS fwpass
256      USER user
257      PASS pass
258
259 =item 7
260
261      USER user@remote.host
262      PASS pass
263      AUTH fwuser
264      RESP fwpass
265
266 =back
267
268 =item ftp_ext_passive
269
270 =item ftp_int_passive
271
272 FTP servers can work in passive or active mode. Active mode is when
273 you want to transfer data you have to tell the server the address and
274 port to connect to.  Passive mode is when the server provide the
275 address and port and you establish the connection.
276
277 With some firewalls active mode does not work as the server cannot
278 connect to your machine (because you are behind a firewall) and the firewall
279 does not re-write the command. In this case you should set C<ftp_ext_passive>
280 to a I<true> value.
281
282 Some servers are configured to only work in passive mode. If you have
283 one of these you can force C<Net::FTP> to always transfer in passive
284 mode; when not going via a firewall, by setting C<ftp_int_passive> to
285 a I<true> value.
286
287 =item local_netmask
288
289 A reference to a list of netmask strings in the form C<"134.99.4.0/24">.
290 These are used by the C<requires_firewall> function to determine if a given
291 host is inside or outside your firewall.
292
293 =back
294
295 The following entries are used during installation & testing on the
296 libnet package
297
298 =over 4
299
300 =item test_hosts
301
302 If true then C<make test> may attempt to connect to hosts given in the
303 configuration.
304
305 =item test_exists
306
307 If true then C<Configure> will check each hostname given that it exists
308
309 =back
310
311 =for html <hr>
312
313 I<$Id: //depot/libnet/Net/Config.pm#17 $>
314
315 =cut