|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #!/usr/bin/perl  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Mail::SMTP::Honeypot;  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Notes to curious readers:  | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # This module was cobbled together in a couple of days out of another  | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # project that is neatly partitioned into pieces that have a good  | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # organization. Everything from there was pretty much dumped in this one  | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # file. Sorry 'bout that ;-)  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # I was a lot more interested in having it work quickly than making it neat.  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	Michael  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
15
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
48034
 | 
 use strict;  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1632
 | 
    | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #use diagnostics;  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #use lib qw(blib lib);  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
19
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
8107
 | 
 use Data::Dumper;  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
99467
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
602
 | 
    | 
| 
20
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1391
 | 
 use Net::DNS::Codes qw(  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	T_PTR  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	C_IN  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	BITS_QUERY  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	RD  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	NS_PACKETSZ  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	HFIXEDSZ  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	QUERY  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	NOERROR  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	NXDOMAIN  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	SERVFAIL  | 
| 
31
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
6623
 | 
 );  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12517
 | 
    | 
| 
32
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
892
 | 
 use Net::NBsocket qw(  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	open_udpNB  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	open_listenNB  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	accept_NB  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	inet_aton  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	inet_ntoa  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	sockaddr_in  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	set_so_linger  | 
| 
40
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
5583
 | 
 );  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
190626
 | 
    | 
| 
41
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
898
 | 
 use Net::DNS::ToolKit qw(  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	gethead  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	newhead  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	get_ns  | 
| 
45
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
6696
 | 
 );  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
75900
 | 
    | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #use Net::DNS::ToolKit::Debug qw(  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	print_head  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	print_buf  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #);  | 
| 
50
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
6558
 | 
 use Net::DNS::ToolKit::RR;  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29145
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
247
 | 
    | 
| 
51
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
 use POSIX qw(  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	EINTR  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	EWOULDBLOCK  | 
| 
54
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
49
 | 
 );  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
| 
55
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
643
 | 
 use Proc::PidUtil qw(  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if_run_exit  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	is_running  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	get_script_name  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	make_pidfile  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	zap_pidfile  | 
| 
61
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
9528
 | 
 );  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5815
 | 
    | 
| 
62
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
456
 | 
 use Sys::Hostname::FQDN qw(  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	fqdn  | 
| 
64
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
5806
 | 
 );  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7077
 | 
    | 
| 
65
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3032
 | 
 use Unix::Syslog qw(  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	:macros  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	openlog  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	syslog  | 
| 
69
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
5616
 | 
 );  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15689
 | 
    | 
| 
70
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
51
 | 
 use vars qw($VERSION @EXPORT @ISA);  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67879
 | 
    | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 require Exporter;  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 @ISA = qw(Exporter);  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION = do { my @r = (q$Revision: 0.11 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 @EXPORT = qw(  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	run_honeypot  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # private file scoped variables  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my($me,$threads,$dns,$dnshost,$dnsport,$dnsaddr,$deny,$hostname,$laddr,  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    $port,$delay,$config,$syslog,$verbose,$DNStimeout,$maxthreads,$maxcmds,  | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    $LOG,$DNSfileno,$disconnect,%Commands,$unique,$log_facility,%subref  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $CRLF	= "\r\n";  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my @IDarray        = ('a'..'z','A'..'Z',(0..9));  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Mail::SMTP::Honeypot -- Dummy mail server  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Mail::SMTP::Honeypot;  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   run_honeypot($config)  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 DESCRIPTION  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 B is a perl module that appears to provide all the  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 functionality of a standard SMTP server except that when the targeted  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 command state is detected (default DATA), it terminates the connection with  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 a temporary failure and the response:  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     421 Service not available, closing transmission channel  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The purpose of this module is to provide a spam sink on a tertiary MX host.  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The module daemon is run on an MX host with a very high priority number  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 specified in it's DNS record. i.e.  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   some_mail_domain.com	IN MX 9999 lastmx.servicedomain.com.  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Since many spammers target this mail server in the hope that its  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 configuration and/or security is not as strong or well maintained as the  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 primary mail host for a domain. In the off chance that a real message is  | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sent to the server, the TEMPORARY failure code will simply make the sending  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 host retry later -- probably with the lower priority numbered host.  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Meanwhile, the server target by the spam source has its resources consumed  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 by B.  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Honeypot does not spawn children and holds only a small reference to each  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 thread that it holds to a client, thus consuming minimal resources. It can  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 produce logs useful in analyzing the spam traffic to your site. Using it  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 with a detach in CONN mode is adequate for triggering a companion spam  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 program such as Mail::SpamCannibal while consuming minimum host resources.  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 At our site, we simply run B on the same host as our secondary MX  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 but on a different IP address.  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Honeypot provides various levels of connection and transaction logging that  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 can be set in the configuration.  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 A delay may be inserted between the receipt of each command and the response  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 from the server daemon to slow down the sending client.  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 CONFIGURATION  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Edit the B file to change or set the following:  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $config = {  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # specify the directory for the pid file for this daemon  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [required]  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	piddir		=> '/var/run',  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # deny at command state, one of:  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	CONN EHLO HELO MAIL RCPT DATA  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # defaults to DATA if not specified  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional]  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	deny		=> 'DATA',  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # specify the local domain name, defaults to local hostname.  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # this is probably not what you want if you use virtual IP's  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # and have a real mail client on the same host. so...  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # specify the host 'answerback name' here.  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional]  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	hostname	=> 'my.host.name.com',  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # specify the IP address to bind the listening port  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # defaults to ALL interfaces (INADDR_ANY)  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional]  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	ip_address	=> '1.2.3.4',  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # listen port -- default 25  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # this is useful for debugging purposes  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional]  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	port		=> 25,  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ## NOTE: 	see Concurrent Daemon Operation in the  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ##		documentation for setup where another  | 
| 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ##		mail daemon is running on the same host.  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # specify the response delay after connect or upon  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # receipt of an smtp command from the client  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # NOTE:	if a response is not received  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #		from the client in this time  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #		period, the smptdeny daemon will  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #		issue a 421 response and disconnect  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional] default 10 seconds  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	delay		=> 10,  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # syslog facility, one of:  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	LOG_KERN LOG_USER LOG_MAIL LOG_DAEMON  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	LOG_AUTH LOG_SYSLOG LOG_LPR LOG_NEWS  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	LOG_UUCP LOG_CRON LOG_AUTHPRIV LOG_FTP  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	LOG_LOCAL0 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	LOG_LOCAL4 LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # You should not need to change this  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	log_facility	=> 'LOG_MAIL',  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # syslog log level or (none), one of:  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	STDERR LOG_EMERG LOG_ALERT LOG_CRIT LOG_ERR  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	LOG_WARNING LOG_NOTICE LOG_INFO LOG_DEBUG  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # NOTE: 	the command line -d flag overrides  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #		this and sets the level to STDERR  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional]  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	syslog		=> 'LOG_WARNING',  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # log verbosity  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	0 connect only  | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	1 + To: & From:  | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	2 + bad commands  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	3 + trace execution  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	4 + deep trace with sub names  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional]  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	verbose		=> 0,  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # DNS host, if you do not have a resolver  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # on your host or for debugging  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # default: as returned by your resolver for local dns  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional]  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	dnshost		=> 'use.default',  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # DNS port, useful for debugging  | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional] default 53  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	dnsport		=> 53,  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # timeout for DNS PTR queries  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional] default: use 'delay' above  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	DNStimeout	=> 10,  | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # maximum number of connected clients  | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional] default 100  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	maxthreads	=> 100,  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # maximum number of commands per client  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional] default 100  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	maxcmds		=> 100,  | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # disconnect the remote after this much time  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # [optional] default 300 seconds  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #	disconnect	=> 300,  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   };  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 OPERATION  | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Launch the daemon with the command:  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	rc.honeypot.pl [-d] [start | stop | restart]  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The '-d' flag, this overides the config settings and  | 
| 
263
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 reports logging to STDERR  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 On some systems it may be necessary to wrap a shell script around  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 rc.honeypot.pl if the path for perl is not in scope during boot.  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #!/bin/sh  | 
| 
269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # shell script 'rc.honeypot'  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   /path/to/rc.honeypot.pl $*  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 A sample shell script is included in the distribution as B  | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
276
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 NOTE: suggest you test your configuration as follows...  | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   Set:	verbose	=> 3,  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	delay	=> 5,  | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ./rc.honeypot -d start  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Connect to the daemon from a host not on the same subnet and watch the  | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 output from daemon to verify proper operation.  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Correct the configuration values and ENJOY!  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Standalone Operation  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 For operation on a host where B is the only SMTP  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 daemon, the default configuration will work for most installations.  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Concurrent Daemon Operation  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 To operate B concurrently with another mail daemon on  | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the same host you must do the following:  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B<1)> add a virtual IP address for the daemon to answer.  | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The IP address in the rc.honeypot.pl config section should be left   | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 commented out so that the daemon will bind to INADDR_ANY.  | 
| 
301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 In your startup sequence, execute the following: (example for Linux)  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #/bin/sh  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Edit for your setup.  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   NETMASK="255.255.255.0"	# REPLACE with YOUR netmask!  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   NETWORK="5.6.7.0"		# REPLACE with YOUR network address!  | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   BROADCAST="5.6.7.255"		# REPLACE with YOUR broadcast address  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # assign a virtual IP address  | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   IPADDR="5.6.7.8"  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # assign ethernet device  | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   DEVICE="eth0"			# REPLACE with your external device  | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   LUN="0"  | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Note:	the "real" IP address has no LUN  | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #		virtual IP's are assigned LUN's starting with '0'  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #  | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # i.e.	host IP = 5.6.7.1	eth0  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # virtIP	5.6.7.8		LUN 0	eth0:0  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # virtIP	5.6.7.9		LUN 1	eth0:1  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   IFACE=${DEVICE}:${LUN}  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   /sbin/ifconfig ${IFACE} ${IPADDR} broadcast ${BROADCAST} netmask ${NETMASK}  | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   /sbin/route add ${IPADDR} dev ${IFACE}  | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   echo Configuring $IFACE as $IPADDR  | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B<2)> run the honeypot daemon on an unused port.  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Select a high port number that will not interfere with normail operation of  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the host SMTP daemon or other services on the host.  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   i.e.	in the config section of rc.honeypot.pl  | 
| 
335
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	port	=> 10025,  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item B<3)> add packet filter rules to redirect queries.  | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This example is for IPTABLES on Linux. Similar rules would apply for other  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 filter packages.  | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # allowed chain for TCP connections  | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   iptables -N allowed  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   iptables -A allowed -p tcp --syn -j ACCEPT  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   iptables -A allowed -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   iptables -A allowed -p tcp -j DROP  | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # drop all external packets target on honeypot daemon  | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   iptables -t nat -A PREROUTING -p tcp -s 0/0 --dport 10025 -j DROP  | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   iptables -t nat -A PREROUTING -p tcp -d 5.6.7.8 --dport 25 -j REDIRECT --to-port 10025  | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # alternate DNAT statement  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # iptables -t nat -a PREROUTING -p tcp -d 5.6.7.8 --dport 25 -j DNAT --to 5.6.7.8:10025  | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ## if you are running SpamCannibal, add this rule to capture IP's of connecting hosts  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ## iptables -A INPUT -p tcp -i eth0 --dport 10025 -j QUEUE  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # allow the internal port to connect  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   iptables -A INPUT -p tcp -s 0/0 --dport 10025 -j allowed  | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 EXPORTS  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Only one function is exported by Honeypot.pm. This function is called in the  | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 rc.honeypot.pl.sample script to launch the B daemon.  | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over 4  | 
| 
367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * run_honeypot($config); # with @ARGV  | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Launch the honeypot daemon.  | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   input:	config hash  | 
| 
373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   returns:	nothing (exits)  | 
| 
374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
377
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
378
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
379
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub run_honeypot  {  | 
| 
380
 | 
0
 | 
  
  0
  
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   die "arg 1 of run_honeypot must be a hash\n"  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless ref $_[0] eq 'HASH';  | 
| 
382
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $pidfile = &check_run;	# check for another running daemon  | 
| 
383
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   &check_config;		# verify that config array is correct and populated  | 
| 
384
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   clean_child();  		# double fork a child  | 
| 
385
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   make_pidfile($pidfile,$$)  | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	or die "could not make pidfile '$pidfile' for $$\n";  | 
| 
387
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   init_all();  | 
| 
388
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   syslog_config();  | 
| 
389
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   goto &daemon;  | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub usage {	# tested by hand  | 
| 
393
 | 
0
 | 
  
  0
  
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   $me = $0 unless $me;  | 
| 
394
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   print STDERR $_[0],"\n" if $_[0];  | 
| 
395
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   print STDERR qq|  | 
| 
396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Syntax:	$me start  | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$me stop  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$me restart  | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$me status  | 
| 
400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	-d switch may be added to  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	   redirect logging to STDERR  | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 |;  | 
| 
405
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   exit 1;  | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub kill_job {  | 
| 
409
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($pidfile) = @_;  | 
| 
410
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $pid = is_running($pidfile);  | 
| 
411
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   if ($pid) {  | 
| 
412
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     kill 15, $pid;  | 
| 
413
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $pid = 0;  | 
| 
414
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     sleep 1;  | 
| 
415
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
416
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     print STDERR "$me: not running\n";  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # return true on good number  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub vld_num {		# t => vld_num.t  | 
| 
422
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
  
0
  
 | 
1107
 | 
   my $num = shift;  | 
| 
423
 | 
7
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
45
 | 
   return $num =~ /\d/ && $num !~ /[\D\s]/;  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub bad_config {  | 
| 
427
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($msg) = @_;  | 
| 
428
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   print STDERR 'config: ',$msg,"\n";  | 
| 
429
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   exit 1;  | 
| 
430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=item * $sub_name = who();  | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
434
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #Returns the name of the calling subroutine without the package name.  | 
| 
435
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=cut  | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub who {  | 
| 
439
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
0
  
 | 
63
 | 
   (caller(1))[3] =~ /[^:]+$/;  | 
| 
440
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
   return $& . ': ';  | 
| 
441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
442
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # returns $pidfile if successful or exits  | 
| 
444
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub check_run {  | 
| 
446
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($c) = @_;  | 
| 
447
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
   unless ($c->{piddir} && -d $c->{piddir} && -w $c->{piddir}) {  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
448
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     print STDERR "pid directory not specified or not writable\n";  | 
| 
449
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     exit 0;  | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
451
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $me = get_script_name();  | 
| 
452
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $0 = $me;  | 
| 
453
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     | 
| 
454
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
   usage('missing command argument(s)') if  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
455
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	(grep($_ eq '-d',@ARGV) && @ARGV < 2) ||  | 
| 
456
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	@ARGV < 1;  | 
| 
457
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $pidfile = $c->{piddir} .'/'. $me . '.pid';  | 
| 
458
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   foreach(@ARGV) {  | 
| 
459
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($_ eq 'start') {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
460
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       if_run_exit($c->{piddir},"already running\n");  | 
| 
461
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       last;  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($_ eq 'stop') {  | 
| 
464
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       kill_job($pidfile);  | 
| 
465
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       exit 0;  | 
| 
466
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
467
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($_ eq 'restart') {  | 
| 
468
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       kill_job($pidfile);  | 
| 
469
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       last;  | 
| 
470
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
471
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($_ eq 'status') {  | 
| 
472
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       my $pid = is_running($pidfile);  | 
| 
473
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       if ($pid) {  | 
| 
474
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	print STDERR "$pid $me is running\n";  | 
| 
475
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       } else {  | 
| 
476
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	print STDERR "$me not running\n";  | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
478
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       last;  | 
| 
479
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($_ eq '-d') {  | 
| 
481
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       $c->{syslog} = 'STDERR';  | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
484
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       usage("unknown command argument '$_'\n");  | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
488
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return $pidfile;  | 
| 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### validate and set configuration defaults  | 
| 
492
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub check_config {  | 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # ip-address  | 
| 
495
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
0
  
 | 
546
 | 
   my($c) = @_;;  | 
| 
496
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   if ($c->{ip_address}) {  | 
| 
497
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("bad IP address '$c->{ip_address}'")  | 
| 
498
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $laddr = inet_aton($c->{ip_address});  | 
| 
499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
500
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     $laddr = Socket::INADDR_ANY;  | 
| 
501
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
502
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # port number  | 
| 
503
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   if ($port = $c->{port}) {  | 
| 
504
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("bad port number '$port'")  | 
| 
505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless vld_num($port);  | 
| 
506
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
507
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     $port		= 25;  | 
| 
508
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
509
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # delay  | 
| 
510
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   if ($delay = $c->{delay}) {  | 
| 
511
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid delay '$delay'")  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless vld_num($delay);  | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
514
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     $delay		= 10;  | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # deny  | 
| 
517
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
46
 | 
   if ($deny = $c->{deny}) {  | 
| 
518
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $deny		= uc $deny;  | 
| 
519
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid deny state '$deny'")  | 
| 
520
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $deny =~ /^(?:CONN|EHLO|HELO|MAIL|RCPT|DATA)$/;  | 
| 
521
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $deny = 'HELO|EHLO' if $deny =~ /HELO|EHLO/;  | 
| 
522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
523
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     $deny		= 'DATA';  | 
| 
524
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # hostname  | 
| 
526
 | 
4
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
33
 | 
   $hostname		= $c->{hostname} || fqdn();  | 
| 
527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # syslog  | 
| 
528
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1786
 | 
   if ($log_facility = $c->{log_facility}) {  | 
| 
529
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $log_facility = uc $log_facility;  | 
| 
530
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid log facility '$log_facility'")  | 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $log_facility =~ /^(?:LOG_KERN|LOG_USER|LOG_MAIL|LOG_DAEMON|LOG_AUTH|LOG_SYSLOG|LOG_LPR|LOG_NEWS|LOG_UUCP|LOG_CRON|LOG_AUTHPRIV|LOG_FTP|LOG_LOCAL0|LOG_LOCAL1|LOG_LOCAL2|LOG_LOCAL3|LOG_LOCAL4|LOG_LOCAL5|LOG_LOCAL6|LOG_LOCAL7)$/;  | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
533
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     $log_facility = 'LOG_MAIL';  | 
| 
534
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
535
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
22
 | 
   if ($syslog = $c->{syslog}) {  | 
| 
536
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $syslog = uc $syslog;  | 
| 
537
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid log request '$syslog'")  | 
| 
538
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $syslog =~ /^(?:STDERR|LOG_EMERG|LOG_ALERT|LOG_CRIT|LOG_ERR|LOG_WARNING|LOG_NOTICE|LOG_INFO|LOG_DEBUG)$/;  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
540
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # verbose  | 
| 
541
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
37
 | 
   if ($verbose = $c->{verbose}) {  | 
| 
542
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid verbosity '$verbose'")  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless vld_num($verbose) && $verbose > 0;  | 
| 
544
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ########### DEEP TRACE CODE #############  | 
| 
545
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($verbose > 3) {  | 
| 
546
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       foreach(sort keys %Mail::SMTP::Honeypot::) {  | 
| 
547
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $subref = \&{"Mail::SMTP::Honeypot::$_"};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
548
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$Mail::SMTP::Honeypot::{$_} =~ /[^:]+$/;  | 
| 
549
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$subref{$subref} = $&;  | 
| 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
551
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ########### END DEEP TRACE CODE #############  | 
| 
553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
554
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     $verbose = 0;  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
556
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # dns host  | 
| 
557
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
   if ($_ = $c->{dnshost}) {  | 
| 
558
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid dns hostname '$dnshost'")  | 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless ($dnshost = inet_aton($_));  | 
| 
560
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
561
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
     $dnshost = get_ns();  | 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
563
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # dns port  | 
| 
564
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5370
 | 
   if ($dnsport = $c->{dnsport}) {  | 
| 
565
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid dns port number '$dnsport'")  | 
| 
566
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless vld_num($dnsport);  | 
| 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
568
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     $dnsport = 53;  | 
| 
569
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
570
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   if ($dnshost) {  | 
| 
571
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     $dnsaddr = sockaddr_in($dnsport,$dnshost);  | 
| 
572
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
573
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # DNStimeout  | 
| 
574
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
62
 | 
   if ($DNStimeout = $c->{DNStimeout}) {  | 
| 
575
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid DNS timeout '$DNStimeout'")  | 
| 
576
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless vld_num($DNStimeout) && $DNStimeout >= $delay;  | 
| 
577
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
578
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
     $DNStimeout		= $delay;  | 
| 
579
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
580
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # maxthreads  | 
| 
581
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   if ($maxthreads = $c->{maxthreads}) {  | 
| 
582
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid maximum client count '$maxthreads'")  | 
| 
583
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless vld_num($maxthreads);  | 
| 
584
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
585
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     $maxthreads		= 100;  | 
| 
586
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
587
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # maxcmds  | 
| 
588
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   if ($maxcmds = $c->{maxcmds}) {  | 
| 
589
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid maximum client count '$maxcmds'")  | 
| 
590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless vld_num($maxcmds);  | 
| 
591
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
592
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     $maxcmds		= 100;  | 
| 
593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # disconnect  | 
| 
595
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
   if ($disconnect = $c->{disconnect}) {  | 
| 
596
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     bad_config("invalid maximum client count '$disconnect'")  | 
| 
597
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless vld_num($disconnect);  | 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
599
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     $disconnect		= 300;  | 
| 
600
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
602
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub clean_child() {  | 
| 
604
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my $pid = fork;  | 
| 
605
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   if ($pid) {  | 
| 
606
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     waitpid($pid,0);  | 
| 
607
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     exit 0;  | 
| 
608
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
609
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
610
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   chdir '/';			# allow root dismount  | 
| 
611
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   open STDIN, '/dev/null' or die "Can't dup STDIN to /dev/null: $!";  | 
| 
612
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   open STDOUT, '>/dev/null' or die "Can't dup STDOUT to /dev/null: $!";  | 
| 
613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
614
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   exit 0 if $pid = fork;	# double fork to release instantiating terminal  | 
| 
615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
616
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
617
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _trace {  | 
| 
618
 | 
4
 | 
  
100
  
 | 
 
 | 
  
4
  
 | 
 
 | 
3704
 | 
   return (wantarray) ? (\$threads,\$dns) : \$threads;  | 
| 
619
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
620
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
621
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub init_all() {  | 
| 
622
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   $unique = $$ -1;  | 
| 
623
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $threads	= {};				# thread hash  | 
| 
624
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   die "could not open DNS socket\n"  | 
| 
625
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless ($dns = open_udpNB());  | 
| 
626
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $DNSfileno = fileno($dns);  | 
| 
627
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $threads->{$DNSfileno} = {  | 
| 
628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	sock	=> $dns,  | 
| 
629
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	alarm	=> 0,  | 
| 
630
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	name	=> '4.3.2.1.in-addr.arpa',  | 
| 
631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	read	=> \&dns_rcv  | 
| 
632
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   };  | 
| 
633
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $dns = {};					# dns transaction hash  | 
| 
634
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
635
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
636
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub my_dump {  | 
| 
637
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my %names;  | 
| 
638
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   local *pref = __PACKAGE__ . '::';  | 
| 
639
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   foreach(keys %{*pref}) {  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
640
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $names{'*'.$_} = \&{*pref->{$_}};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
641
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
642
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my @d = (  | 
| 
643
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$threads	=> 'threads',  | 
| 
644
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$dns		=> 'dns',  | 
| 
645
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   );  | 
| 
646
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   for ($_=0;$_<@d;$_+=2) {  | 
| 
647
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $d = new Data::Dumper([$d[$_]],[$d[$_+1]]);  | 
| 
648
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $d->Seen(\%names);  | 
| 
649
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     @_ = split(/\n/,$d->Dump);  | 
| 
650
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach(@_) {  | 
| 
651
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       logit($_ ."\n");  | 
| 
652
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
653
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
654
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
655
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
656
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub daemon {  | 
| 
657
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
   unless ($syslog && $syslog eq 'STDERR') {  | 
| 
658
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     open STDERR, '>/dev/null' or die "Can't dup STDERR to /dev/null: $!";  | 
| 
659
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
660
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
661
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # initialization complete, log start up message  | 
| 
662
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   logit('Initiated...');  | 
| 
663
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
664
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $run = 1;  | 
| 
665
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   local $SIG{TERM} = sub {$run = 0};  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
666
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   local $SIG{USR1} = \&my_dump;  | 
| 
667
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   local $SIG{PIPE} = 'IGNORE';  | 
| 
668
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
669
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $then = time;  | 
| 
670
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $sock = open_listenNB($port,$laddr);  | 
| 
671
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   die "could not open listen socket on port $port\n"  | 
| 
672
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $sock;  | 
| 
673
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $fileno = fileno($sock);  | 
| 
674
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $go_listen = $threads->{$fileno} = {  | 
| 
675
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	sock	=> $sock,  | 
| 
676
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	alarm	=> 0,  | 
| 
677
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	read	=> \&newthread,  | 
| 
678
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	next	=> \&next thing to do  | 
| 
679
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   };  | 
| 
680
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my($rin,$win,$rout,$wout,$delta,$nfound);  | 
| 
681
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   while($run) {  | 
| 
682
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $win = $rin = '';  | 
| 
683
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $threads->{$DNSfileno}->{read} = \&dns_rcv;		# always armed  | 
| 
684
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach(grep(!/\D/,keys %$threads)) {		# each thread key  | 
| 
685
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       vec($rin,$_,1) = 1 if $threads->{$_}->{read};	# set read selects  | 
| 
686
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       vec($win,$_,1) = 1 if $threads->{$_}->{write};	# set write selects  | 
| 
687
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
688
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $go_listen->{read} = \&newthread;			# re-arm listner if it was busy  | 
| 
689
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $nfound = select($rout=$rin,$wout=$win,undef,1);	# tick each second  | 
| 
690
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
691
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($nfound > 0) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
692
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       do_thread($wout,'write') if $wout;  | 
| 
693
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       do_thread($rout,'read') if $rout;  | 
| 
694
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($delta = ($_ = time) - $then) {		# timer = next second or more  | 
| 
696
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       $then = $_;  | 
| 
697
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       my @threads = keys %$threads;  | 
| 
698
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       foreach(@threads) {				# each receive thread  | 
| 
699
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         next unless exists $threads->{$_};  | 
| 
700
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $tptr = $threads->{$_};  | 
| 
701
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	if ($tptr->{alarm} &&  | 
| 
702
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  ($tptr->{alarm} + $delay) < $then) {  | 
| 
703
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	  $tptr->{alarm} = time + $disconnect - $delay;  | 
| 
704
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	  my($logtxt,$go);  | 
| 
705
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	  if ($tptr->{tout}) {  | 
| 
706
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    $go = $tptr->{tout};  | 
| 
707
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    $logtxt = 'tout ';  | 
| 
708
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  } else {  | 
| 
709
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    $go = $tptr->{next};  | 
| 
710
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    $logtxt = 'next ';  | 
| 
711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  }  | 
| 
712
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	  if ($verbose > 3) {			# deep trace  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
713
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    $logtxt = &who ."delay ended for '$_' $logtxt => ".  | 
| 
714
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		(exists $subref{$go}) ? $subref{$go} : 'sub ref not defined';  | 
| 
715
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    logit($logtxt);  | 
| 
716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  }  | 
| 
717
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  elsif ($verbose > 2) {  | 
| 
718
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    logit(&who ."delay ended for '$_'\n");  | 
| 
719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  }  | 
| 
720
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	  $go->($_);  | 
| 
721
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	  if (exists $threads->{$_} && ! $threads->{$_}->{tout}) {  | 
| 
722
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	    $threads->{$_}->{tout} = \&terminate  | 
| 
723
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  }  | 
| 
724
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	  last;  | 
| 
725
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
726
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
727
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       foreach(keys %$dns) {				# each dns thread  | 
| 
728
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	if ($dns->{$_}->{alarm} &&  | 
| 
729
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	  ($dns->{$_}->{alarm} + $delay) < $then) {  | 
| 
730
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	  logit(&who ."dns ended for id $_ for $dns->{$_}->{fileno}\n") unless $verbose < 3;  | 
| 
731
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	  delete $dns->{$_};  | 
| 
732
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	  last;						# only do one per check for efficiancy  | 
| 
733
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
734
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
735
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
736
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
737
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   &close_all;  | 
| 
738
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   logit('Exiting...');  | 
| 
739
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   closelog();  | 
| 
740
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   exit 0;  | 
| 
741
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
742
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
743
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
744
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # execute a thread based on what the select routine returns  | 
| 
745
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # sort used for testing only  | 
| 
746
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
747
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
748
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub do_thread {		# t => do_thread.t  | 
| 
749
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
  
0
  
 | 
42
 | 
   my($vec,$op,$sort) = @_;  | 
| 
750
 | 
10
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
25
 | 
   logit(&who . $op) unless $verbose < 3;			# trace each thread  | 
| 
751
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   my @threads;		# use array in case we decide not to use 'goto' at return of this subr  | 
| 
752
 | 
10
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   if ($sort) {  | 
| 
753
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
     @threads = sort {$a <=> $b} grep(!/\D/,keys %$threads);	# each numeric thread key  | 
| 
 
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
    | 
| 
754
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
755
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
     @threads = grep(!/\D/,keys %$threads);  | 
| 
756
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
757
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
   foreach (@threads) {		# or if re-entering after read with a deleted thread                              | 
| 
758
 | 
38
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
155
 | 
     next unless exists $threads->{$_} && $threads->{$_};	# skip killed threads  | 
| 
759
 | 
33
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
97
 | 
     next unless vec($vec,$_,1);					# skip inactive threads  | 
| 
760
 | 
17
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
53
 | 
     next unless $threads->{$_}->{$op};  | 
| 
761
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     my $go = $threads->{$_}->{$op};  | 
| 
762
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     $threads->{$_}->{$op} = undef;				# clear vector  | 
| 
763
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     next unless ref $go;					# ignore blank vectors  | 
| 
764
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     @_ = ($_);  | 
| 
765
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     if ($verbose > 3) {						# deep trace  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
766
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       my $exsub = (exists $subref{$go}) ? $subref{$go} : 'sub ref not found';  | 
| 
767
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       logit(&who ."exec $op for '$_' => $exsub\n");  | 
| 
768
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
769
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($verbose > 2) {  | 
| 
770
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       logit(&who ."executing $op for '$_'\n") unless $verbose < 3;  | 
| 
771
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
772
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     goto $go;							# do it and return  | 
| 
773
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
774
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
775
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
776
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub writesock {		# t => new_rw_sock.t  | 
| 
777
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
0
  
 | 
9
 | 
   my($fileno) = @_;  | 
| 
778
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   my $tptr = $threads->{$fileno};  | 
| 
779
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   my $bytes = length($tptr->{wargs}) - $tptr->{woff};  | 
| 
780
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   $! = 9;  | 
| 
781
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
109
 | 
   my $wrote = syswrite(	$tptr->{sock},  | 
| 
782
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$tptr->{wargs},  | 
| 
783
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$bytes,  | 
| 
784
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$tptr->{woff},  | 
| 
785
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   	) if fileno($tptr->{sock});			# closed filehandles return false  | 
| 
786
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   my $logtxt = &who . $fileno .' ';  | 
| 
787
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   if (defined $wrote) {  | 
| 
788
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $logtxt .= $wrote;  | 
| 
789
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
790
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   else {  | 
| 
791
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     $logtxt .= 'sock error: '. $!;  | 
| 
792
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
793
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   logit($logtxt) unless $verbose < 3;  | 
| 
794
 | 
2
 | 
  
100
  
 | 
  
 50
  
 | 
 
 | 
 
 | 
21
 | 
   if (defined $wrote) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
795
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     $tptr->{woff} += $wrote;  | 
| 
796
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     if ($tptr->{woff} == $bytes) {			# if complete  | 
| 
797
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
       my $go = $tptr->{next};  | 
| 
798
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
       unless ($verbose < 4) {				# deep trace  | 
| 
799
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $exsub = (exists $subref{$go}) ? $subref{$go} : 'sub ref not found';  | 
| 
800
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	logit(&who ."next => $exsub for '$fileno'\n");  | 
| 
801
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
802
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
       goto $go;						# goto the next link  | 
| 
803
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
804
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif (sockerror($! || 9)) {			# default to bad file descriptor  | 
| 
805
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     goto &removethread;					# remove thread if there was an error  | 
| 
806
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
807
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{write} = \&writesock;				# restore write pointer  | 
| 
808
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
809
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
810
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _readsock {		# t => new_rw_sock.t  | 
| 
811
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
14
 | 
   my($fileno) = @_;  | 
| 
812
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   my $tptr = $threads->{$fileno};  | 
| 
813
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
152
 | 
   my $bytes = sysread(	$tptr->{sock},  | 
| 
814
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$tptr->{rargs},  | 
| 
815
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			2048,				# limit reads, data is mostly limited to 2048  | 
| 
816
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$tptr->{roff}  | 
| 
817
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) if fileno($tptr->{sock});				# closed filehandles return false  | 
| 
818
 | 
3
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
22
 | 
   logit(&who . $fileno .' '. ((defined $bytes) ? $bytes : 'error '. $!))  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
819
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		unless $verbose < 3;			# trace  | 
| 
820
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   return($tptr,$bytes);  | 
| 
821
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
822
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
823
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub readsock {		# t => new_rw_sock.t  | 
| 
824
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
0
  
 | 
15
 | 
   my ($tptr,$bytes) = &_readsock;  | 
| 
825
 | 
3
 | 
  
100
  
 | 
  
 50
  
 | 
 
 | 
 
 | 
123
 | 
   if (defined $bytes) {					# returns undef on error  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
826
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     goto &removethread   | 
| 
827
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $bytes;					# EOF  | 
| 
828
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     $tptr->{alarm} = time;				# renew timeout  | 
| 
829
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     $tptr->{roff} += $bytes;				# bytes read     | 
| 
830
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     my $go = $tptr->{next};  | 
| 
831
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     unless ($verbose < 4) {				# deep trace  | 
| 
832
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       my $exsub = (exists $subref{$go}) ? $subref{$go} : 'sub ref not found';  | 
| 
833
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       logit(&who ."next => $exsub for '$_[0]'\n");  | 
| 
834
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
835
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     goto $go;  | 
| 
836
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif (sockerror($! || 9)) {			# default to bad file descriptor  | 
| 
837
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     goto &removethread;					# detected fatal condition  | 
| 
838
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
839
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # probably never get to here  | 
| 
840
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   $tptr->{read} = \&readsock;				# restore read pointer  | 
| 
841
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
842
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
843
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
844
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # input:        error code  | 
| 
845
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # returns:      true if error, else false  | 
| 
846
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
847
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub sockerror {         # t => sockerror.t  | 
| 
848
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
  
0
  
 | 
805
 | 
   my($err) = @_;  | 
| 
849
 | 
6
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
68
 | 
   return ($err == EINTR ||                      # don't die for interrupts  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
850
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           $err == EWOULDBLOCK)                  # or while waiting  | 
| 
851
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ? 0  | 
| 
852
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         : ($err) ? 1 : 0;  | 
| 
853
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
854
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
855
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # remove a thread, closing the socket  | 
| 
856
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
857
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # input:        threads pointer, fileno  | 
| 
858
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # returns:      nothing  | 
| 
859
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
860
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub removethread {      # t => removethread.t  | 
| 
861
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
0
  
 | 
21
 | 
   my($fileno) = @_;  | 
| 
862
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   logit(&who . $fileno) unless $verbose < 3;  | 
| 
863
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   my $sock = $threads->{$fileno}->{sock};  | 
| 
864
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
   delete $threads->{$fileno};  | 
| 
865
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
349
 | 
   close $sock if $sock;                                 # don't attempt close on non-existent sock  | 
| 
866
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
867
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
868
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub close_all {  | 
| 
869
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   foreach(keys %$threads) {  | 
| 
870
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     removethread($_);  | 
| 
871
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
872
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
873
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
874
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub newthread {		# t => new_rw_sock.t  | 
| 
875
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
0
  
 | 
2026378
 | 
   my($listner) = @_;  | 
| 
876
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
26
 | 
   if ((keys %$threads) > $maxthreads) {  | 
| 
877
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     logit(&who . "thread pool full\n") unless $verbose < 2;  | 
| 
878
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return;  | 
| 
879
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
880
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
   $threads->{$listner}->{read} = \&newthread;           # restore vector  | 
| 
881
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
   my($sock,$netaddr) = accept_NB($threads->{$listner}->{sock});  | 
| 
882
 | 
2
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1294
 | 
   return unless $sock;  | 
| 
883
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   my $ipaddr = inet_ntoa($netaddr);  | 
| 
884
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
   unless ($ipaddr) {  | 
| 
885
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     close $sock;  | 
| 
886
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return;  | 
| 
887
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
888
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   set_so_linger($sock,30);                              # set linger to 30 seconds, just in case  | 
| 
889
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
   my $fileno = fileno($sock);  | 
| 
890
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
   $threads->{$fileno} = {  | 
| 
891
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         alarm   => 1,  | 
| 
892
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	cmdcnt	=> 0,					# number of allowed commands  | 
| 
893
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	conlog	=> 0,					# connection logged  | 
| 
894
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	domain	=> '',					# claims to be this domain  | 
| 
895
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	ipaddr	=> $ipaddr,				# dot quad  | 
| 
896
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	lastc	=> 'CONN',				# last connection state  | 
| 
897
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	name	=> '',					# smtp host name  | 
| 
898
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	next	=> \&sub,				# next sub to exec  | 
| 
899
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	proto	=> 'SMTP',				# protocol  | 
| 
900
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	read	=> \&sub,				# read sub to exec  | 
| 
901
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	rargs	=> '',					# read string  | 
| 
902
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	roff	=> 0,					# length  | 
| 
903
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         sock    => $sock,                               # socket  | 
| 
904
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	write	=> \&sub,				# write sub to exec  | 
| 
905
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	wargs	=> ''.					# string to write  | 
| 
906
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	woff	=> 0,					# offset into write string  | 
| 
907
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   };  | 
| 
908
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   if ($deny eq 'CONN') {  | 
| 
909
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $threads->{$fileno}->{next} = \&terminate;  | 
| 
910
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
911
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     dns_send($fileno,$ipaddr);			# initiate a PTR lookup  | 
| 
912
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     @{$threads->{$fileno}}{qw(  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
    | 
| 
913
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	alarm  | 
| 
914
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	cmdcnt  | 
| 
915
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	cok  | 
| 
916
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	domain  | 
| 
917
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	lastc  | 
| 
918
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	name  | 
| 
919
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	next  | 
| 
920
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	proto  | 
| 
921
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	wargs  | 
| 
922
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     )} = (  | 
| 
923
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	time,					# alarm  | 
| 
924
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	0,					# cmdcnt  | 
| 
925
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	0,					# cok  | 
| 
926
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	'',					# domain  | 
| 
927
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	'CONN',					# lastc  | 
| 
928
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	'',					# name  | 
| 
929
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	\&connOK,				# next  | 
| 
930
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	'SMTP',					# proto  | 
| 
931
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	'220 '. $hostname .' service ready'. $CRLF,  | 
| 
932
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
933
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
934
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
935
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
936
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub connOK {  | 
| 
937
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($fileno) = @_;  | 
| 
938
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $tptr = $threads->{$fileno};  | 
| 
939
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{cok} = 1;				# flag that says this is done  | 
| 
940
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   logit('honeypot connect '. $tptr->{name} .'['. $tptr->{ipaddr} .']');  | 
| 
941
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{woff} = 0;   | 
| 
942
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{next} = \&readSMTP;  | 
| 
943
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{tout} = \&write_delay;  | 
| 
944
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  $tptr->{alarm} = use previous value  | 
| 
945
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
946
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
947
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub terminate {		# t => parseSMTP.t  | 
| 
948
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($fileno) = @_;  | 
| 
949
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $threads->{$fileno}->{wargs} = '421 Service not available, closing transmission channel'. $CRLF;  | 
| 
950
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   logit(&who ."sent terminate for '$fileno'\n") unless $verbose < 3;  | 
| 
951
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   write_rearm($fileno,\&removethread,1);	# immediate terminate  | 
| 
952
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
953
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
954
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # implementation from rfc 2821  | 
| 
955
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
956
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # STATE:                allowed commands  | 
| 
957
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
958
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # initial:      HELO, EHLO, NOOP, HELP, VRFY, RSET, and QUIT  | 
| 
959
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
960
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # HELO/EHLO     MAIL, HELO, EHLO, NOOP, HELP, VRFY, RSET, and QUIT  | 
| 
961
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
962
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # MAIL          RCPT, HELO, EHLO, NOOP, HELP, VRFY, RSET, and QUIT  | 
| 
963
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
964
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # RCPT          RCPT, DATA, EHLO, NOOP, HELP, VRFY, RSET, and QUIT  | 
| 
965
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
966
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # DATA          {data} .  | 
| 
967
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
968
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 %Commands = (  | 
| 
969
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         EHLO    => \&_EHLO,  | 
| 
970
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         HELO    => \&_HELO,  | 
| 
971
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         MAIL    => \&_MAIL,  | 
| 
972
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         RCPT    => \&_RCPT,  | 
| 
973
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         DATA    => \&terminate,  | 
| 
974
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         RSET    => \&_RSET,  | 
| 
975
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         VRFY    => \&_VRFY,  | 
| 
976
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         HELP    => \&_HELP,  | 
| 
977
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         NOOP    => \&_NOOP,  | 
| 
978
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         QUIT    => \&_QUIT,  | 
| 
979
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         SEND    => \¬imp,  | 
| 
980
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         SOML    => \¬imp,  | 
| 
981
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         SAML    => \¬imp,  | 
| 
982
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         EXPN    => \¬imp,  | 
| 
983
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         TURN    => \¬imp,  | 
| 
984
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
985
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
986
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub parseSMTP {		# t => parseSMTP.t  | 
| 
987
 | 
21
 | 
 
 | 
 
 | 
  
21
  
 | 
  
0
  
 | 
605
 | 
   my($fileno) = @_;  | 
| 
988
 | 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
   my $tptr = $threads->{$fileno};  | 
| 
989
 | 
21
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
73
 | 
   goto &terminate if ++$tptr->{cmdcnt} > $maxcmds;  | 
| 
990
 | 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
   my $newc = '';  | 
| 
991
 | 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
   my $smtp_args = '';  | 
| 
992
 | 
21
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
104
 | 
   if ($tptr->{rargs} =~ /^\s*([a-zA-Z]{4})\b/) {  | 
| 
993
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
48
 | 
     $newc = uc $1;  | 
| 
994
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
     $smtp_args = lc $';  | 
| 
995
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
996
 | 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
   my $lastc = $tptr->{lastc};  | 
| 
997
 | 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
   $tptr->{wargs} = '';					# error text  | 
| 
998
 | 
21
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
162
 | 
   unless ($newc) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
999
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     $tptr->{rargs} =~ s/[^[\w .-]//g;  | 
| 
1000
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     $tptr->{wargs} = '500 5.5.1 Command unrecognized "'. $tptr->{rargs} .'"';  | 
| 
1001
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1002
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   elsif (! exists $Commands{$newc}) {  | 
| 
1003
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     $tptr->{wargs} = '500 5.5.1 Command unrecognized "'. $1 .'"';  | 
| 
1004
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1005
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   elsif ($tptr->{roff} > 512) {				# rfc2821 4.5.3.1  | 
| 
1006
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     $tptr->{wargs} = '500 5.5.4 Command line too long';  | 
| 
1007
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1008
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   elsif ($lastc =~ /(?:CONN|HELO|EHLO)/) {  | 
| 
1009
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
25
 | 
     if ($newc eq 'RCPT') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1010
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
       $tptr->{wargs} = '503 5.0.0 Need MAIL before RCPT';  | 
| 
1011
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1012
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($newc eq 'DATA') {  | 
| 
1013
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
       $tptr->{wargs} = '503 5.0.0 Need MAIL command';  | 
| 
1014
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1015
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1016
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   elsif ($lastc eq 'MAIL') {  | 
| 
1017
 | 
8
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
28
 | 
     if ($newc eq 'MAIL') {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1018
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
       $tptr->{wargs} = '503 5.5.0 Sender already specified';  | 
| 
1019
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1020
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($newc eq 'DATA') {  | 
| 
1021
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
       $tptr->{wargs} = '503 5.0.0 Need RCPT before DATA';  | 
| 
1022
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1023
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1024
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   elsif ($lastc eq 'RCPT') {  | 
| 
1025
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     if ($newc eq 'MAIL') {  | 
| 
1026
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       $tptr->{wargs} = '503 5.5.0 Sender already specified';  | 
| 
1027
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }   | 
| 
1028
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1029
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1030
 | 
21
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
58
 | 
   if ($tptr->{wargs}) {							# if there is an error  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1031
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
29
 | 
     logit(&who ."$newc ". $tptr->{wargs}) unless $verbose < 2;		# more log info  | 
| 
1032
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     $tptr->{wargs} .= $CRLF;  | 
| 
1033
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
     write_rearm($fileno,\&readSMTP);					# send error and return to this routine  | 
| 
1034
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif ($newc eq $deny) {  | 
| 
1035
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     $tptr->{alarm} = time;  | 
| 
1036
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     $tptr->{next} = \&terminate;  | 
| 
1037
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     logit(&who .'deny '. $newc . $smtp_args) unless $verbose < 3;  | 
| 
1038
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {								# else  | 
| 
1039
 | 
9
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
21
 | 
     logit(&who . $newc . $smtp_args) unless $verbose < 3;		# trace success  | 
| 
1040
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     $Commands{$newc}->($fileno,$smtp_args,$tptr);			# execute the command  | 
| 
1041
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1042
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1043
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1044
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1045
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # input:	to or from,  | 
| 
1046
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #		string [to/from: garbage junk email@addy.sufx more junk]  | 
| 
1047
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # returns:	(error text on error)  | 
| 
1048
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #		(name,domain) on match  | 
| 
1049
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	or 	(name,{defined+false}) if 'postmaster' by itself  | 
| 
1050
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1051
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub xtract_to_from {	# t => parseSMTP.t  | 
| 
1052
 | 
8
 | 
 
 | 
 
 | 
  
8
  
 | 
  
0
  
 | 
17
 | 
   my $match = lc shift;					# 'to' or 'from' or 'vrfy'  | 
| 
1053
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
   my $string = lc shift;				# input string  | 
| 
1054
 | 
8
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
50
 | 
   my $what = ($string =~ /[^\s:]+/)			# must have some characters  | 
| 
1055
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	? $& : '';  | 
| 
1056
 | 
8
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
32
 | 
   $string = $' || '';					# remainder of string  | 
| 
1057
 | 
8
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
56
 | 
   return ('501 5.5.2 Syntax error in parameters scanning "'. $what .'"'. $CRLF)  | 
| 
1058
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $what eq $match && $string =~ /^:/;	# return error if 'to / from' does not match  | 
| 
1059
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 							# or is not terminated with colon  | 
| 
1060
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   $string = $';						# snip off colon  | 
| 
1061
 | 
8
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
33
 | 
   if ($string =~ /([\w\.-]+)@([\w\-]+\.[\w\.-]+)/) {	# if email addy found  | 
| 
1062
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
     return ('500 5.5.4 User name too long'. $CRLF)  | 
| 
1063
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if length($1) > 64;				# rfc2821 4.3.5.1  | 
| 
1064
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     return ('500 5.5.4 Domain name too long'. $CRLF)  | 
| 
1065
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if length($2) > 255;  | 
| 
1066
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     return ($1,$2);  | 
| 
1067
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1068
 | 
5
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
17
 | 
   return ('postmaster','')  | 
| 
1069
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if $string =~ /^\s*?\s*$/ && $match =~/to|vrfy/;  | 
| 
1070
 | 
5
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
18
 | 
   return ('','')  | 
| 
1071
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if $string =~ /^\s*<\s*>/ && $match =~/from/;	# error message returned to ME  | 
| 
1072
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1073
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # figure what kind or error to report  | 
| 
1074
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   $string =~ s/^\s+//;					# waste leading spaces  | 
| 
1075
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   @_ = split(/\s+/,$string);  | 
| 
1076
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
93
 | 
   return ('555 5.5.4 "'. $_[1] .'" parameter unrecognized'. $CRLF)  | 
| 
1077
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if @_ > 1;					# error if there are unknown parameters  | 
| 
1078
 | 
5
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
29
 | 
   return ('553 5.5.4 Domain name required for address "'. $_[0] .'"'. $CRLF)  | 
| 
1079
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if $_[0];  | 
| 
1080
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return ('501 5.0.0 Argument required'. $CRLF);  | 
| 
1081
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1082
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1083
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1084
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # SMTP commands  | 
| 
1085
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1086
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	HELO & EHLO  | 
| 
1087
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1088
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1089
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _EHLO {		# t => commands.t  | 
| 
1090
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
4
 | 
   push @_, 1;  | 
| 
1091
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   goto &_HELO;  | 
| 
1092
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1093
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1094
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _HELO {		# t => commands.t  | 
| 
1095
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
9
 | 
   my($fileno,$smtp_args,$tptr,$is_EHLO) = @_;  | 
| 
1096
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
   $tptr->{domain} = ($smtp_args =~ /[\w\.-]+/)  | 
| 
1097
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	? $& : 'nobody';  | 
| 
1098
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #      S: 250 hostname ready for {domain}  | 
| 
1099
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # (ehlo)  250 HELP  | 
| 
1100
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
   my $wargs = $hostname . ' ready for '. $tptr->{domain} .' ('. $tptr->{name} .'['. $tptr->{ipaddr} .'])'. $CRLF;  | 
| 
1101
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   if ($is_EHLO) {  | 
| 
1102
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     $tptr->{wargs} =   | 
| 
1103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	'250-'. $wargs .  | 
| 
1104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	'250 HELP'. $CRLF;  | 
| 
1105
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $tptr->{lastc} = 'EHLO';  | 
| 
1106
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $tptr->{proto} = 'ESMTP';  | 
| 
1107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
1108
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   $tptr->{wargs} =   | 
| 
1109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	'250 '. $wargs;  | 
| 
1110
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     $tptr->{lastc} = 'HELO';  | 
| 
1111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1112
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
   write_rearm($fileno,\&readSMTP);  | 
| 
1113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	MAIL  | 
| 
1117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # no attempt is made to verify the sender envelope address since  | 
| 
1119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # it is so easy to forge an address that will validate somewhere  | 
| 
1120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _MAIL {		# t => commands.t  | 
| 
1122
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
124
 | 
   my($fileno,$smtp_args,$tptr) = @_;  | 
| 
1123
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
   my($name,$domain) = xtract_to_from('from',$smtp_args);  | 
| 
1124
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
   unless (defined $domain) {  | 
| 
1125
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     $tptr->{wargs} = $name;		# 'name' contains the error message when 'domain' is undefined  | 
| 
1126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
1127
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     $tptr->{lastc} = 'MAIL';  | 
| 
1128
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     $tptr->{wargs} = '250 2.1.0 OK'. $CRLF;  | 
| 
1129
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     $tptr->{from} = $name .'@'. $domain;  | 
| 
1130
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     $tptr->{msgid} = uniquemsgid();  | 
| 
1131
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     logit($tptr->{msgid}.': from=<'. $tptr->{from} .'>, relay='. $tptr->{domain}.' ('. $tptr->{name} .'['. $tptr->{ipaddr} .'])')  | 
| 
1132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $verbose < 1;  | 
| 
1133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1134
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   write_rearm($fileno,\&readSMTP);  | 
| 
1135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	RCPT && VRFY  | 
| 
1139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _RCPT {		# t => commands.t  | 
| 
1141
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
5
 | 
   push @_, 1;  | 
| 
1142
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   goto &_VRFY;  | 
| 
1143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _VRFY {		# t => commands.t  | 
| 
1146
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
13
 | 
   my($fileno,$smtp_args,$tptr,$is_rcpt) = @_;  | 
| 
1147
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   my($name,$domain);  | 
| 
1148
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   if ($is_rcpt) {  | 
| 
1149
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     ($name,$domain) = xtract_to_from('to',$smtp_args);  | 
| 
1150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
1151
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     ($name,$domain) = xtract_to_from('vrfy','vrfy:'. $smtp_args);  | 
| 
1152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1153
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
   if (defined $domain) {  | 
| 
1154
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     my $to = ($domain) ? $name .'@'. $domain : $name .'@'. $hostname;	# postmaster is by itself without attached domain  | 
| 
1155
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     $tptr->{lastc} = ($is_rcpt) ? 'RCPT' : 'VRFY';  | 
| 
1156
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     $tptr->{wargs} = '250 2.1.5 OK'. $CRLF;  | 
| 
1157
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     $is_rcpt = ($is_rcpt) ? 'rcpt' : 'vrfy';  | 
| 
1158
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     logit($tptr->{msgid}.': '. $is_rcpt .'=<'. $to .'>, relay='. $tptr->{domain}.' ('. $tptr->{name} .'['. $tptr->{ipaddr} .'])')  | 
| 
1159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $verbose < 1;  | 
| 
1160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   else {  | 
| 
1162
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     $tptr->{wargs} = $name;					# this is really the error string from xtract_to_from  | 
| 
1163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1164
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   write_rearm($fileno,\&readSMTP);  | 
| 
1165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	RSET  | 
| 
1169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _RSET {		# t => commands.t  | 
| 
1171
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
2
 | 
   my($fileno,$smtp_args,$tptr) = @_;  | 
| 
1172
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   $tptr->{wargs} = '250 2.0.0 OK'. $CRLF;  | 
| 
1173
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   goto &soft_reset;  | 
| 
1174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	HELP  | 
| 
1178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _HELP {		# t => commands.t  | 
| 
1180
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
4
 | 
   my($fileno,$smtp_args,$tptr) = @_;  | 
| 
1181
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   $tptr->{wargs} =   | 
| 
1182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 '214-2.0.0     Commands supported are'. $CRLF .  | 
| 
1183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 '214-2.0.0    HELO EHLO MAIL RCPT DATA'. $CRLF .  | 
| 
1184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 '214 2.0.0    RSET VRFY HELP NOOP QUIT'. $CRLF;  | 
| 
1185
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   write_rearm($fileno,\&readSMTP);  | 
| 
1186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	NOOP  | 
| 
1190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _NOOP {		# t => commands.t  | 
| 
1192
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
4
 | 
   my($fileno,$smtp_args,$tptr) = @_;  | 
| 
1193
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
   $tptr->{wargs} = '250 2.0.0 OK'. $CRLF;  | 
| 
1194
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   write_rearm($fileno,\&readSMTP);  | 
| 
1195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	QUIT  | 
| 
1199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _QUIT {		# t => commands.t  | 
| 
1201
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
8
 | 
   my($fileno,$smtp_args,$tptr) = @_;  | 
| 
1202
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   $threads->{$fileno}->{wargs} = '221 2.0.0 '. $hostname .' closing connection'. $CRLF;  | 
| 
1203
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   write_rearm($fileno,\&removethread);  | 
| 
1204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	DATA  | 
| 
1208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	this is where we disconnect  | 
| 
1209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ### REPLACED BY TERMINATE  | 
| 
1211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #sub _DATA {  | 
| 
1213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  my($fileno) = @_;  | 
| 
1214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  my $tptr = $threads->{$fileno};  | 
| 
1215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  $tptr->{woff} = 0;   | 
| 
1216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  $tptr->{next} = \&terminate;  | 
| 
1217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  $tptr->{tout} = 0;  | 
| 
1218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  $tptr->{alarm} = time;			# wait 'delay'  | 
| 
1219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #}  | 
| 
1220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #	notimp  | 
| 
1223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub notimp {		# t => parseSMTP.t  | 
| 
1225
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
0
  
 | 
11
 | 
   my($fileno,$smtp_args,$tptr) = @_;  | 
| 
1226
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   $tptr->{wargs} = '502 5.5.1 Command not implemented'. $CRLF;  | 
| 
1227
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
   write_rearm($fileno,\&readSMTP);  | 
| 
1228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub soft_reset {        # t => commands.t  | 
| 
1231
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
0
  
 | 
6
 | 
   my($fileno) = @_;  | 
| 
1232
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
   my $tptr = $threads->{$fileno};  | 
| 
1233
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   my $wargs = $tptr->{wargs};  | 
| 
1234
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
   my $ipaddr = $tptr->{ipaddr};  | 
| 
1235
 | 
2
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
11
 | 
   my $name = $tptr->{name} || '';  | 
| 
1236
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   $tptr = clear_bufs($fileno);  | 
| 
1237
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   $tptr->{lastc} = 'CONN';  | 
| 
1238
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   $tptr->{proto} = 'SMTP';  | 
| 
1239
 | 
2
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
8
 | 
   $tptr->{wargs} = $wargs || '554 5.3.5 unknown mailer error'. $CRLF;  | 
| 
1240
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
   $tptr->{ipaddr} = $ipaddr;  | 
| 
1241
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
   $tptr->{name} = $name;  | 
| 
1242
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   logit(&who . $tptr->{wargs}) unless $verbose < 2;  | 
| 
1243
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   write_rearm($fileno,\&readSMTP);  | 
| 
1244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub readSMTP {  | 
| 
1247
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($fileno) = @_;  | 
| 
1248
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $tptr = $threads->{$fileno};  | 
| 
1249
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{alarm} = time;  | 
| 
1250
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{tout} = \&readRestore;  | 
| 
1251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub readRestore {  | 
| 
1254
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($fileno) = @_;  | 
| 
1255
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $tptr = $threads->{$fileno};  | 
| 
1256
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{read} = \&readsock;  | 
| 
1257
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{roff} = 0;  | 
| 
1258
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{next} = \&parseSMTP;  | 
| 
1259
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{alarm} = time + $disconnect - $delay;		# five minute timeout  | 
| 
1260
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{tout} = \&terminate;  | 
| 
1261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1263
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # return buffers to the 'ehlo,helo' state  | 
| 
1264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # input:        threads, fileno  | 
| 
1266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # returns:      $threads->{$fileno}  | 
| 
1267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub clear_bufs {	# t => commands.t  | 
| 
1269
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
0
  
 | 
38
 | 
   my($fileno) = @_;  | 
| 
1270
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
   my($sock,$domain,$proto) = @{$threads->{$fileno}}{qw(  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
1271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       sock  domain  proto)};  | 
| 
1272
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
   delete $threads->{$fileno};				# clean all buffers in the thread  | 
| 
1273
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
   my $lastc = ($domain)  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ? ($proto eq 'ESMTP') ? 'EHLO' : 'HELO'  | 
| 
1275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         : 'CONN';  | 
| 
1276
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
   my $tptr = $threads->{$fileno} = {};  | 
| 
1277
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
   @{$tptr}{qw(  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
| 
1278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sock  domain  proto  lastc)} =			# restore only those that are needed  | 
| 
1279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ($sock,$domain,$proto,$lastc);  | 
| 
1280
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
   return $tptr;  | 
| 
1281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub write_rearm {	# t => parseSMTP.t  | 
| 
1284
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($fileno,$next,$immediate) = @_;  | 
| 
1285
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $tptr = $threads->{$fileno};  | 
| 
1286
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{woff} = 0;  | 
| 
1287
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{next} = $next;  | 
| 
1288
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   goto &write_delay  | 
| 
1289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if $immediate;  | 
| 
1290
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{tout} = \&write_delay;  | 
| 
1291
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{alarm} = time;				# wait 'delay'  | 
| 
1292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub write_delay {  | 
| 
1295
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($fileno) = @_;  | 
| 
1296
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   my $tptr = $threads->{$fileno};  | 
| 
1297
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{tout} = \&terminate;  | 
| 
1298
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{write} = \&writesock;  | 
| 
1299
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $tptr->{alarm} = time;				# kill thread if we can't write  | 
| 
1300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=item * syslog_config();  | 
| 
1303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #Configure Unix logging.  | 
| 
1305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  NOTE, logging must be initiated by the caller  | 
| 
1307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  input:	none  | 
| 
1309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  output:	none  | 
| 
1310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=cut  | 
| 
1312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub syslog_config {  | 
| 
1314
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   if ($syslog && $syslog ne 'STDERR') {  | 
| 
1315
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     openlog($me, LOG_PID(), eval "$log_facility");  | 
| 
1316
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $LOG = eval "$syslog";				# save LOGlevel for everyone  | 
| 
1317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=item * logit($msg);  | 
| 
1321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #Log a message.  | 
| 
1323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  input:	message string  | 
| 
1325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  output:	none  | 
| 
1326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=cut  | 
| 
1328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub logit {  | 
| 
1330
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   my($msg) = @_;  | 
| 
1331
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return unless $syslog;  | 
| 
1332
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $msg .= "\n";  | 
| 
1333
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   $msg =~ s/[\r\n]+/\n/g;  | 
| 
1334
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   if ($syslog eq 'STDERR') {  | 
| 
1335
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     print STDERR $msg;  | 
| 
1336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   else {  | 
| 
1338
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     syslog($LOG,"%s",$msg);  | 
| 
1339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=item * closelog();  | 
| 
1343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #Close the syslog facility if it has been opened  | 
| 
1345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  input:	none  | 
| 
1347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  returns:	none  | 
| 
1348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=cut  | 
| 
1350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub closelog {  | 
| 
1352
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
   local $^W = 0; # no warnings;  | 
| 
1353
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
   &Unix::Syslog::closelog  | 
| 
1354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	if $syslog && $syslog ne 'STDERR';  | 
| 
1355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_unique {	# t => uniquemsgid.t  | 
| 
1358
 | 
44
 | 
 
 | 
 
 | 
  
44
  
 | 
  
0
  
 | 
905878
 | 
   my($seed) = @_;  | 
| 
1359
 | 
44
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
122
 | 
   $unique = $seed if $seed;  | 
| 
1360
 | 
44
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
91
 | 
   $unique = 1 if ++$unique > 65535;  | 
| 
1361
 | 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
140
 | 
   return $unique;		# return an ascending number or the PID if just invoked  | 
| 
1362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=item * $msgid = uniquemsgid($seed);  | 
| 
1365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #Uses 'time' as a seed (standard) unless specified. Returns an email-safe   | 
| 
1367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #alphanumeric string based on the time (or seed), the pid of the caller and a   | 
| 
1368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #random number. Guaranteed to be unique for multiple daemons with less than  | 
| 
1369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #65k new reqests per second.  | 
| 
1370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  input:        [optional seed] or [default 'time']  | 
| 
1372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  returns:      string of the form: 'bbnPCFUDYctT'  | 
| 
1373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  | 
| 
1374
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #=cut  | 
| 
1375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub uniquemsgid {       # t => uniquemsgid.t  | 
| 
1377
 | 
30
 | 
 
 | 
  
 66
  
 | 
  
30
  
 | 
  
0
  
 | 
2766
 | 
   my $t = shift || time;  | 
| 
1378
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
79
 | 
   my $q = sprintf("%010u",($$ << 16) + get_unique());  | 
| 
1379
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
   my @serial = ();  | 
| 
1380
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
   foreach(0..5) {   | 
| 
1381
 | 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
181
 | 
     my $x = $t % 62;  | 
| 
1382
 | 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
183
 | 
     my $y = $q % 62;  | 
| 
1383
 | 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
308
 | 
     unshift @serial,$IDarray[$x],$IDarray[$y];  | 
| 
1384
 | 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
197
 | 
     $t = int $t/62;  | 
| 
1385
 | 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
259
 | 
     $q = int $q/62;  | 
| 
1386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1387
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
137
 | 
   return join('',@serial);  | 
| 
1388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub dns_send {		# tested by hand  | 
| 
1391
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
   return unless $dnsaddr && $DNSfileno;	# skip if no DNS present  | 
| 
1392
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my($fileno,$ipaddr) = @_;  | 
| 
1393
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $id = get_unique();  | 
| 
1394
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   logit(&who . $ipaddr ." $fileno id $id")  | 
| 
1395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless $verbose < 3;  | 
| 
1396
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my @ip = split(/\./,$ipaddr);  | 
| 
1397
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   @_ = reverse @ip;  | 
| 
1398
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $name =  join('.',@_,'in-addr.arpa');  | 
| 
1399
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $buffer;  | 
| 
1400
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $offset = newhead(\$buffer,  | 
| 
1401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$id,  | 
| 
1402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	BITS_QUERY | RD,		# query, recursion desired  | 
| 
1403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	1,0,0,0,			# one question  | 
| 
1404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   );  | 
| 
1405
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my ($get,$put,$parse) = new Net::DNS::ToolKit::RR;  | 
| 
1406
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $offset = $put->Question(\$buffer,$offset,$name,T_PTR,C_IN);  | 
| 
1407
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return unless $buffer;  | 
| 
1408
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $dns->{$id} = {  | 
| 
1409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	fileno	=> $fileno,  | 
| 
1410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	alarm	=> time,  | 
| 
1411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	name	=> $name,  | 
| 
1412
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   };  | 
| 
1413
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $threads->{$fileno}->{id} = $id;	# mark original thread with this ID  | 
| 
1414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # UDP may not block  | 
| 
1415
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   send(  | 
| 
1416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$threads->{$DNSfileno}->{sock},  | 
| 
1417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$buffer,0,  | 
| 
1418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$dnsaddr);  | 
| 
1419
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub dns_rcv {		# tested by hand  | 
| 
1422
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
 
 | 
   my($fileno) = @_;  | 
| 
1423
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $tptr = $threads->{$fileno};  | 
| 
1424
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $msg;  | 
| 
1425
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $sender = recv($tptr->{sock},$msg,NS_PACKETSZ,0);  | 
| 
1426
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return undef unless $sender;					# no message received  | 
| 
1427
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return undef if length($msg) < HFIXEDSZ;			# short message  | 
| 
1428
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my ($off,$id,$qr,$opcode,$aa,$tc,$rd,$ra,$mbz,$ad,$cd,$rcode,  | 
| 
1429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$qdcount,$ancount,$nscount,$arcount)  | 
| 
1430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	= gethead(\$msg);  | 
| 
1431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return undef unless  | 
| 
1432
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 	$tc == 0 &&  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$qr == 1 &&  | 
| 
1434
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$opcode == QUERY &&  | 
| 
1435
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	($rcode == NOERROR || $rcode == NXDOMAIN || $rcode == SERVFAIL) &&  | 
| 
1436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$qdcount == 1 &&  | 
| 
1437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	exists $dns->{$id};  | 
| 
1438
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $pfno = $dns->{$id}->{fileno};				# originating thread pointer  | 
| 
1439
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $pname = $dns->{$id}->{name};  | 
| 
1440
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   delete $dns->{$id};						# remove dns query thread  | 
| 
1441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return undef  | 
| 
1442
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	unless exists $threads->{$pfno};  | 
| 
1443
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return undef unless length($msg) > HFIXEDSZ;			# no message  | 
| 
1444
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my ($get,$put,$parse) = new Net::DNS::ToolKit::RR;  | 
| 
1445
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my($name,$t,$type,$class,$ttl,$rdl,@rdata);  | 
| 
1446
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ($off,$name,$type,$class) = $get->Question(\$msg,$off);  | 
| 
1447
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   my $lname = lc $name;  | 
| 
1448
 | 
0
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
   if (  $ancount &&  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$rcode == &NOERROR &&  | 
| 
1450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$lname eq $pname &&  | 
| 
1451
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$type == T_PTR &&  | 
| 
1452
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$class == C_IN  | 
| 
1453
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ) {  | 
| 
1454
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     foreach(0..$ancount -1) {  | 
| 
1455
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       ($off,$name,$t,$class,$ttl,$rdl,@rdata) = $get->next(\$msg,$off);  | 
| 
1456
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       last if $t == T_PTR;  | 
| 
1457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1458
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1459
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ($name) = @rdata;  | 
| 
1460
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   if ($name) {  | 
| 
1461
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $threads->{$pfno}->{name} = $name .' ';  | 
| 
1462
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     logit(&who ."$pfno rDNS $rdata[0]") unless $verbose < 3;  | 
| 
1463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
1464
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $threads->{$pfno}->{name} = '';  | 
| 
1465
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     logit(&who ."$pfno rDNS missing") unless $verbose < 3;  | 
| 
1466
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
1467
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   connOK($pfno) unless $threads->{$pfno}->{cok};		# log connection, continue  | 
| 
1468
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1469
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1470
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 COPYRIGHT  | 
| 
1471
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1472
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Copyright 2004 - 2014, Michael Robinton   | 
| 
1473
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1474
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This program is free software; you can redistribute it and/or modify  | 
| 
1475
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 it under the terms of the GNU General Public License (except as noted  | 
| 
1476
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 otherwise in individuals sub modules)  published by  | 
| 
1477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the Free Software Foundation; either version 2 of the License, or   | 
| 
1478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 (at your option) any later version.  | 
| 
1479
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This program is distributed in the hope that it will be useful,  | 
| 
1481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 but WITHOUT ANY WARRANTY; without even the implied warranty of   | 
| 
1482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    | 
| 
1483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 GNU General Public License for more details.  | 
| 
1484
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 You should have received a copy of the GNU General Public License  | 
| 
1486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 along with this program; if not, write to the Free Software  | 
| 
1487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  | 
| 
1488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 AUTHOR  | 
| 
1490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Michael Robinton   | 
| 
1492
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SEE ALSO  | 
| 
1494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L on CPAN or spamcannibal.org  | 
| 
1496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
1498
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  |