Linux sagir-us1.hostever.us 5.14.0-570.51.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Oct 8 09:41:34 EDT 2025 x86_64
LiteSpeed
Server IP : 104.247.108.91 & Your IP : 216.73.216.26
Domains : 74 Domain
User : georgeto
Terminal
Auto Root
Create File
Create Folder
Localroot Suggester
Backdoor Destroyer
Readme
/
usr /
local /
apps /
lib /
imap /
c-client /
Delete
Unzip
Name
Size
Permission
Date
Action
ARCHIVE
258
B
-rw-r--r--
2023-01-11 06:22
CCTYPE
3
B
-rw-r--r--
2023-01-11 06:22
CFLAGS
74
B
-rw-r--r--
2023-01-11 06:22
LDFLAGS
118
B
-rw-r--r--
2023-01-11 06:22
Makefile
31.74
KB
-rw-r--r--
2023-01-11 06:22
Makefile.gss
1.28
KB
-rw-r--r--
2023-01-11 06:22
OSCFLAGS
535
B
-rw-r--r--
2023-01-11 06:22
OSTYPE
4
B
-rw-r--r--
2023-01-11 06:22
SPECIALS
1
B
-rw-r--r--
2023-01-11 06:22
auth_ext.c
2.88
KB
-rw-r--r--
2023-01-11 06:22
auth_gss.c
14.25
KB
-rw-r--r--
2023-01-11 06:22
auth_log.c
3.42
KB
-rw-r--r--
2023-01-11 06:22
auth_md5.c
16.71
KB
-rw-r--r--
2023-01-11 06:22
auth_pla.c
4.32
KB
-rw-r--r--
2023-01-11 06:22
auths.c
88
B
-rw-r--r--
2023-01-11 06:22
big5.c
111.09
KB
-rw-r--r--
2023-01-11 06:22
c-client.a
3.91
MB
-rw-r--r--
2023-01-11 06:22
c-client.h
1.65
KB
-rw-r--r--
2023-01-11 06:22
ckp_1st.c
1.48
KB
-rw-r--r--
2023-01-11 06:22
ckp_2nd.c
888
B
-rw-r--r--
2023-01-11 06:22
ckp_3rd.c
816
B
-rw-r--r--
2023-01-11 06:22
ckp_a41.c
1.41
KB
-rw-r--r--
2023-01-11 06:22
ckp_afs.c
1.84
KB
-rw-r--r--
2023-01-11 06:22
ckp_bsi.c
1.38
KB
-rw-r--r--
2023-01-11 06:22
ckp_cyg.c
1.75
KB
-rw-r--r--
2023-01-11 06:22
ckp_dce.c
2.56
KB
-rw-r--r--
2023-01-11 06:22
ckp_gss.c
3.01
KB
-rw-r--r--
2023-01-11 06:22
ckp_nul.c
1.04
KB
-rw-r--r--
2023-01-11 06:22
ckp_os4.c
2.11
KB
-rw-r--r--
2023-01-11 06:22
ckp_pam.c
3.99
KB
-rw-r--r--
2023-01-11 06:22
ckp_pmb.c
3.82
KB
-rw-r--r--
2023-01-11 06:22
ckp_psx.c
3.6
KB
-rw-r--r--
2023-01-11 06:22
ckp_sce.c
1.58
KB
-rw-r--r--
2023-01-11 06:22
ckp_sec.c
1.54
KB
-rw-r--r--
2023-01-11 06:22
ckp_ssn.c
1.58
KB
-rw-r--r--
2023-01-11 06:22
ckp_std.c
1.16
KB
-rw-r--r--
2023-01-11 06:22
ckp_sv4.c
3.17
KB
-rw-r--r--
2023-01-11 06:22
ckp_svo.c
3.11
KB
-rw-r--r--
2023-01-11 06:22
ckp_ult.c
1.07
KB
-rw-r--r--
2023-01-11 06:22
cns11643.c
505.24
KB
-rw-r--r--
2023-01-11 06:22
crexcl.c
2.44
KB
-rw-r--r--
2023-01-11 06:22
crx_nfs.c
2.44
KB
-rw-r--r--
2023-01-11 06:22
crx_std.c
1.21
KB
-rw-r--r--
2023-01-11 06:22
decomtab.c
163.37
KB
-rw-r--r--
2023-01-11 06:22
drivers
989
B
-rwxr-xr-x
2023-01-11 06:22
dummy.c
24.66
KB
-rw-r--r--
2023-01-11 06:22
dummy.h
1.49
KB
-rw-r--r--
2023-01-11 06:22
dummy.o
84.54
KB
-rw-r--r--
2023-01-11 06:22
env.h
1.47
KB
-rw-r--r--
2023-01-11 06:22
env_unix.c
61.15
KB
-rw-r--r--
2023-01-11 06:22
env_unix.h
2.86
KB
-rw-r--r--
2023-01-11 06:22
fdstring.c
2.76
KB
-rw-r--r--
2023-01-11 06:22
fdstring.h
1.05
KB
-rw-r--r--
2023-01-11 06:22
fdstring.o
7.73
KB
-rw-r--r--
2023-01-11 06:22
flockcyg.c
2.99
KB
-rw-r--r--
2023-01-11 06:22
flockcyg.h
1.34
KB
-rw-r--r--
2023-01-11 06:22
flocklnx.c
2.27
KB
-rw-r--r--
2023-01-11 06:22
flocksim.c
28.21
KB
-rw-r--r--
2023-01-11 06:22
flocksim.h
4.29
KB
-rw-r--r--
2023-01-11 06:22
flstring.c
2.37
KB
-rw-r--r--
2023-01-11 06:22
flstring.h
799
B
-rw-r--r--
2023-01-11 06:22
flstring.o
8.38
KB
-rw-r--r--
2023-01-11 06:22
fs.h
905
B
-rw-r--r--
2023-01-11 06:22
fs_unix.c
1.84
KB
-rw-r--r--
2023-01-11 06:22
fsync.c
910
B
-rw-r--r--
2023-01-11 06:22
ftl.h
825
B
-rw-r--r--
2023-01-11 06:22
ftl_unix.c
1002
B
-rw-r--r--
2023-01-11 06:22
gb_12345.c
64.81
KB
-rw-r--r--
2023-01-11 06:22
gb_2312.c
179.47
KB
-rw-r--r--
2023-01-11 06:22
gethstid.c
975
B
-rw-r--r--
2023-01-11 06:22
getspnam.c
1.55
KB
-rw-r--r--
2023-01-11 06:22
gr_wait.c
1.27
KB
-rw-r--r--
2023-01-11 06:22
gr_wait4.c
1.06
KB
-rw-r--r--
2023-01-11 06:22
gr_waitp.c
1.06
KB
-rw-r--r--
2023-01-11 06:22
ibm.c
16.66
KB
-rw-r--r--
2023-01-11 06:22
imap4r1.c
193.18
KB
-rw-r--r--
2023-01-11 06:22
imap4r1.h
8.01
KB
-rw-r--r--
2023-01-11 06:22
imap4r1.o
440.85
KB
-rw-r--r--
2023-01-11 06:22
ip4_unix.c
5.13
KB
-rw-r--r--
2023-01-11 06:22
ip6_unix.c
8.54
KB
-rw-r--r--
2023-01-11 06:22
ip_unix.c
5.13
KB
-rw-r--r--
2023-01-11 06:22
ipo_unix.c
5.04
KB
-rw-r--r--
2023-01-11 06:22
iso_8859.c
13.88
KB
-rw-r--r--
2023-01-11 06:22
jis_0208.c
62.77
KB
-rw-r--r--
2023-01-11 06:22
jis_0212.c
55.8
KB
-rw-r--r--
2023-01-11 06:22
kerb_mit.c
3
KB
-rw-r--r--
2023-01-11 06:22
koi8_r.c
1.76
KB
-rw-r--r--
2023-01-11 06:22
koi8_u.c
1.77
KB
-rw-r--r--
2023-01-11 06:22
ksc_5601.c
178.16
KB
-rw-r--r--
2023-01-11 06:22
linkage.c
1.2
KB
-rw-r--r--
2023-01-11 06:22
linkage.h
510
B
-rw-r--r--
2023-01-11 06:22
log_bsi.c
1.54
KB
-rw-r--r--
2023-01-11 06:22
log_cyg.c
1.24
KB
-rw-r--r--
2023-01-11 06:22
log_old.c
1.01
KB
-rw-r--r--
2023-01-11 06:22
log_os4.c
1.62
KB
-rw-r--r--
2023-01-11 06:22
log_sec.c
1.14
KB
-rw-r--r--
2023-01-11 06:22
log_std.c
1.12
KB
-rw-r--r--
2023-01-11 06:22
log_sv4.c
1.1
KB
-rw-r--r--
2023-01-11 06:22
mail.c
201.99
KB
-rw-r--r--
2023-01-11 06:22
mail.h
66.8
KB
-rw-r--r--
2023-01-11 06:22
mail.o
426.63
KB
-rw-r--r--
2023-01-11 06:22
mbx.c
61.93
KB
-rw-r--r--
2023-01-11 06:22
mbx.o
153.46
KB
-rw-r--r--
2023-01-11 06:22
memmove.c
993
B
-rw-r--r--
2023-01-11 06:22
memmove2.c
1.32
KB
-rw-r--r--
2023-01-11 06:22
memset.c
1010
B
-rw-r--r--
2023-01-11 06:22
mh.c
39.67
KB
-rw-r--r--
2023-01-11 06:22
mh.o
118.7
KB
-rw-r--r--
2023-01-11 06:22
misc.c
13.34
KB
-rw-r--r--
2023-01-11 06:22
misc.h
3.27
KB
-rw-r--r--
2023-01-11 06:22
misc.o
26.76
KB
-rw-r--r--
2023-01-11 06:22
mix.c
92.52
KB
-rw-r--r--
2023-01-11 06:22
mix.o
237.31
KB
-rw-r--r--
2023-01-11 06:22
mkauths
1.18
KB
-rwxr-xr-x
2023-01-11 06:22
mmdf.c
89.34
KB
-rw-r--r--
2023-01-11 06:22
mmdf.o
179.64
KB
-rw-r--r--
2023-01-11 06:22
mtx.c
45.09
KB
-rw-r--r--
2023-01-11 06:22
mtx.o
120.16
KB
-rw-r--r--
2023-01-11 06:22
mx.c
39.05
KB
-rw-r--r--
2023-01-11 06:22
mx.o
117.3
KB
-rw-r--r--
2023-01-11 06:22
netmsg.c
2.88
KB
-rw-r--r--
2023-01-11 06:22
netmsg.h
987
B
-rw-r--r--
2023-01-11 06:22
netmsg.o
13.83
KB
-rw-r--r--
2023-01-11 06:22
news.c
21.78
KB
-rw-r--r--
2023-01-11 06:22
news.o
70.97
KB
-rw-r--r--
2023-01-11 06:22
newsrc.c
16.67
KB
-rw-r--r--
2023-01-11 06:22
newsrc.h
1.45
KB
-rw-r--r--
2023-01-11 06:22
newsrc.o
59.16
KB
-rw-r--r--
2023-01-11 06:22
nl.h
939
B
-rw-r--r--
2023-01-11 06:22
nl_unix.c
2.56
KB
-rw-r--r--
2023-01-11 06:22
nntp.c
74.66
KB
-rw-r--r--
2023-01-11 06:22
nntp.h
1.58
KB
-rw-r--r--
2023-01-11 06:22
nntp.o
177.67
KB
-rw-r--r--
2023-01-11 06:22
opendir.c
1.94
KB
-rw-r--r--
2023-01-11 06:22
os_a32.c
1.44
KB
-rw-r--r--
2023-01-11 06:22
os_a32.h
1.2
KB
-rw-r--r--
2023-01-11 06:22
os_a41.c
1.53
KB
-rw-r--r--
2023-01-11 06:22
os_a41.h
1.2
KB
-rw-r--r--
2023-01-11 06:22
os_a52.c
1.57
KB
-rw-r--r--
2023-01-11 06:22
os_a52.h
1.27
KB
-rw-r--r--
2023-01-11 06:22
os_aix.c
1.5
KB
-rw-r--r--
2023-01-11 06:22
os_aix.h
1.1
KB
-rw-r--r--
2023-01-11 06:22
os_aos.c
1.5
KB
-rw-r--r--
2023-01-11 06:22
os_aos.h
1.26
KB
-rw-r--r--
2023-01-11 06:22
os_art.c
2.13
KB
-rw-r--r--
2023-01-11 06:22
os_art.h
2.01
KB
-rw-r--r--
2023-01-11 06:22
os_asv.c
1.7
KB
-rw-r--r--
2023-01-11 06:22
os_asv.h
1.91
KB
-rw-r--r--
2023-01-11 06:22
os_aux.c
1.51
KB
-rw-r--r--
2023-01-11 06:22
os_aux.h
1.18
KB
-rw-r--r--
2023-01-11 06:22
os_bsd.c
1.5
KB
-rw-r--r--
2023-01-11 06:22
os_bsd.h
1.33
KB
-rw-r--r--
2023-01-11 06:22
os_bsf.c
1.33
KB
-rw-r--r--
2023-01-11 06:22
os_bsf.h
1.05
KB
-rw-r--r--
2023-01-11 06:22
os_bsi.c
1.33
KB
-rw-r--r--
2023-01-11 06:22
os_bsi.h
1.03
KB
-rw-r--r--
2023-01-11 06:22
os_cvx.c
1.38
KB
-rw-r--r--
2023-01-11 06:22
os_cvx.h
1.09
KB
-rw-r--r--
2023-01-11 06:22
os_cyg.c
1.61
KB
-rw-r--r--
2023-01-11 06:22
os_cyg.h
1.6
KB
-rw-r--r--
2023-01-11 06:22
os_d-g.c
1.32
KB
-rw-r--r--
2023-01-11 06:22
os_d-g.h
1.35
KB
-rw-r--r--
2023-01-11 06:22
os_do4.c
1.4
KB
-rw-r--r--
2023-01-11 06:22
os_do4.h
1.23
KB
-rw-r--r--
2023-01-11 06:22
os_drs.c
1.39
KB
-rw-r--r--
2023-01-11 06:22
os_drs.h
1.42
KB
-rw-r--r--
2023-01-11 06:22
os_dyn.c
1.53
KB
-rw-r--r--
2023-01-11 06:22
os_dyn.h
1.5
KB
-rw-r--r--
2023-01-11 06:22
os_hpp.c
1.89
KB
-rw-r--r--
2023-01-11 06:22
os_hpp.h
1.36
KB
-rw-r--r--
2023-01-11 06:22
os_isc.c
1.65
KB
-rw-r--r--
2023-01-11 06:22
os_isc.h
1.68
KB
-rw-r--r--
2023-01-11 06:22
os_lnx.c
1.35
KB
-rw-r--r--
2023-01-11 06:22
os_lnx.h
1.45
KB
-rw-r--r--
2023-01-11 06:22
os_lyn.c
1.32
KB
-rw-r--r--
2023-01-11 06:22
os_lyn.h
1.03
KB
-rw-r--r--
2023-01-11 06:22
os_mct.c
1.29
KB
-rw-r--r--
2023-01-11 06:22
os_mct.h
1.05
KB
-rw-r--r--
2023-01-11 06:22
os_mnt.c
1.3
KB
-rw-r--r--
2023-01-11 06:22
os_mnt.h
1.18
KB
-rw-r--r--
2023-01-11 06:22
os_nto.c
1.84
KB
-rw-r--r--
2023-01-11 06:22
os_nto.h
1.64
KB
-rw-r--r--
2023-01-11 06:22
os_nxt.c
1.32
KB
-rw-r--r--
2023-01-11 06:22
os_nxt.h
1.18
KB
-rw-r--r--
2023-01-11 06:22
os_os4.c
1.38
KB
-rw-r--r--
2023-01-11 06:22
os_os4.h
1.17
KB
-rw-r--r--
2023-01-11 06:22
os_osf.c
1.35
KB
-rw-r--r--
2023-01-11 06:22
os_osf.h
1.17
KB
-rw-r--r--
2023-01-11 06:22
os_osx.c
1.33
KB
-rw-r--r--
2023-01-11 06:22
os_osx.h
1.26
KB
-rw-r--r--
2023-01-11 06:22
os_ptx.c
2.88
KB
-rw-r--r--
2023-01-11 06:22
os_ptx.h
1.7
KB
-rw-r--r--
2023-01-11 06:22
os_pyr.c
1.49
KB
-rw-r--r--
2023-01-11 06:22
os_pyr.h
1.42
KB
-rw-r--r--
2023-01-11 06:22
os_qnx.c
1.87
KB
-rw-r--r--
2023-01-11 06:22
os_qnx.h
1.42
KB
-rw-r--r--
2023-01-11 06:22
os_s40.c
1.58
KB
-rw-r--r--
2023-01-11 06:22
os_s40.h
957
B
-rw-r--r--
2023-01-11 06:22
os_sc5.c
1.56
KB
-rw-r--r--
2023-01-11 06:22
os_sc5.h
1.72
KB
-rw-r--r--
2023-01-11 06:22
os_sco.c
1.62
KB
-rw-r--r--
2023-01-11 06:22
os_sco.h
1.76
KB
-rw-r--r--
2023-01-11 06:22
os_sgi.c
1.38
KB
-rw-r--r--
2023-01-11 06:22
os_sgi.h
1.36
KB
-rw-r--r--
2023-01-11 06:22
os_shp.c
1.94
KB
-rw-r--r--
2023-01-11 06:22
os_shp.h
1.36
KB
-rw-r--r--
2023-01-11 06:22
os_slx.c
1.43
KB
-rw-r--r--
2023-01-11 06:22
os_slx.h
1.45
KB
-rw-r--r--
2023-01-11 06:22
os_sol.c
1.67
KB
-rw-r--r--
2023-01-11 06:22
os_soln.h
1.93
KB
-rw-r--r--
2023-01-11 06:22
os_solo.h
1.9
KB
-rw-r--r--
2023-01-11 06:22
os_sos.c
1.39
KB
-rw-r--r--
2023-01-11 06:22
os_sos.h
1.17
KB
-rw-r--r--
2023-01-11 06:22
os_sua.c
1.33
KB
-rw-r--r--
2023-01-11 06:22
os_sua.h
1.16
KB
-rw-r--r--
2023-01-11 06:22
os_sun.c
1.58
KB
-rw-r--r--
2023-01-11 06:22
os_sun.h
1.28
KB
-rw-r--r--
2023-01-11 06:22
os_sv2.c
2.82
KB
-rw-r--r--
2023-01-11 06:22
os_sv2.h
2.91
KB
-rw-r--r--
2023-01-11 06:22
os_sv4.c
1.6
KB
-rw-r--r--
2023-01-11 06:22
os_sv4.h
1.79
KB
-rw-r--r--
2023-01-11 06:22
os_ult.c
1.27
KB
-rw-r--r--
2023-01-11 06:22
os_ult.h
1.01
KB
-rw-r--r--
2023-01-11 06:22
os_vu2.c
2.01
KB
-rw-r--r--
2023-01-11 06:22
os_vu2.h
2.34
KB
-rw-r--r--
2023-01-11 06:22
osdep.c
32.49
KB
-rw-r--r--
2023-01-11 06:22
osdep.h
1.45
KB
-rw-r--r--
2023-01-11 06:22
osdep.o
415.75
KB
-rw-r--r--
2023-01-11 06:22
osdepbas.c
1.43
KB
-rw-r--r--
2023-01-11 06:22
osdepckp.c
3.6
KB
-rw-r--r--
2023-01-11 06:22
osdeplog.c
1.12
KB
-rw-r--r--
2023-01-11 06:22
osdepssl.c
26.33
KB
-rw-r--r--
2023-01-11 06:22
phile.c
16.28
KB
-rw-r--r--
2023-01-11 06:22
phile.o
55.77
KB
-rw-r--r--
2023-01-11 06:22
pmatch.c
2.77
KB
-rw-r--r--
2023-01-11 06:22
pop3.c
34.08
KB
-rw-r--r--
2023-01-11 06:22
pop3.o
100.79
KB
-rw-r--r--
2023-01-11 06:22
pseudo.c
1.24
KB
-rw-r--r--
2023-01-11 06:22
pseudo.h
838
B
-rw-r--r--
2023-01-11 06:22
pseudo.o
3.34
KB
-rw-r--r--
2023-01-11 06:22
rename.c
1.12
KB
-rw-r--r--
2023-01-11 06:22
rfc822.c
78.98
KB
-rw-r--r--
2023-01-11 06:22
rfc822.h
5.29
KB
-rw-r--r--
2023-01-11 06:22
rfc822.o
168.47
KB
-rw-r--r--
2023-01-11 06:22
scandir.c
2.61
KB
-rw-r--r--
2023-01-11 06:22
setpgrp.c
946
B
-rw-r--r--
2023-01-11 06:22
sig_bsd.c
954
B
-rw-r--r--
2023-01-11 06:22
sig_psx.c
1.3
KB
-rw-r--r--
2023-01-11 06:22
sig_sv4.c
955
B
-rw-r--r--
2023-01-11 06:22
siglocal.c
1.3
KB
-rw-r--r--
2023-01-11 06:22
siglocal.o
6.8
KB
-rw-r--r--
2023-01-11 06:22
smanager.c
3.54
KB
-rw-r--r--
2023-01-11 06:22
smanager.o
15.91
KB
-rw-r--r--
2023-01-11 06:22
smtp.c
26.33
KB
-rw-r--r--
2023-01-11 06:22
smtp.h
2.48
KB
-rw-r--r--
2023-01-11 06:22
smtp.o
79.52
KB
-rw-r--r--
2023-01-11 06:22
ssl_none.c
2.57
KB
-rw-r--r--
2023-01-11 06:22
ssl_unix.c
26.33
KB
-rw-r--r--
2023-01-11 06:22
sslio.h
2.25
KB
-rw-r--r--
2023-01-11 06:22
sslstdio.c
4.15
KB
-rw-r--r--
2023-01-11 06:22
strerror.c
981
B
-rw-r--r--
2023-01-11 06:22
strpbrk.c
1.1
KB
-rw-r--r--
2023-01-11 06:22
strstr.c
1.27
KB
-rw-r--r--
2023-01-11 06:22
strtok.c
2.02
KB
-rw-r--r--
2023-01-11 06:22
strtoul.c
2.33
KB
-rw-r--r--
2023-01-11 06:22
tcp.h
1.73
KB
-rw-r--r--
2023-01-11 06:22
tcp_unix.c
31.52
KB
-rw-r--r--
2023-01-11 06:22
tcp_unix.h
1.2
KB
-rw-r--r--
2023-01-11 06:22
tenex.c
48.69
KB
-rw-r--r--
2023-01-11 06:22
tenex.o
126.43
KB
-rw-r--r--
2023-01-11 06:22
tis_620.c
1.91
KB
-rw-r--r--
2023-01-11 06:22
tmap.c
84.45
KB
-rw-r--r--
2023-01-11 06:22
truncate.c
1.06
KB
-rw-r--r--
2023-01-11 06:22
tz_bsd.c
989
B
-rw-r--r--
2023-01-11 06:22
tz_nul.c
887
B
-rw-r--r--
2023-01-11 06:22
tz_sv4.c
1.02
KB
-rw-r--r--
2023-01-11 06:22
unix.c
92.97
KB
-rw-r--r--
2023-01-11 06:22
unix.h
6.55
KB
-rw-r--r--
2023-01-11 06:22
unix.o
203.15
KB
-rw-r--r--
2023-01-11 06:22
utf8.c
84
KB
-rw-r--r--
2023-01-11 06:22
utf8.h
22.43
KB
-rw-r--r--
2023-01-11 06:22
utf8.o
531.61
KB
-rw-r--r--
2023-01-11 06:22
utf8aux.c
14.12
KB
-rw-r--r--
2023-01-11 06:22
utf8aux.h
1.49
KB
-rw-r--r--
2023-01-11 06:22
utf8aux.o
30.01
KB
-rw-r--r--
2023-01-11 06:22
utime.c
1.22
KB
-rw-r--r--
2023-01-11 06:22
viscii.c
2.8
KB
-rw-r--r--
2023-01-11 06:22
widths.c
265.05
KB
-rw-r--r--
2023-01-11 06:22
windows.c
10.77
KB
-rw-r--r--
2023-01-11 06:22
write.c
1.74
KB
-rw-r--r--
2023-01-11 06:22
Save
Rename
/* ======================================================================== * Copyright 1988-2008 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * * ======================================================================== */ /* * Program: UNIX TCP/IP routines * * Author: Mark Crispin * Networks and Distributed Computing * Computing & Communications * University of Washington * Administration Building, AG-44 * Seattle, WA 98195 * Internet: MRC@CAC.Washington.EDU * * Date: 1 August 1988 * Last Edited: 13 January 2008 */ #include "ip_unix.c" #undef write /* don't use redefined write() */ static tcptimeout_t tmoh = NIL; /* TCP timeout handler routine */ static long ttmo_open = 0; /* TCP timeouts, in seconds */ static long ttmo_read = 0; static long ttmo_write = 0; static long rshtimeout = 15; /* rsh timeout */ static char *rshcommand = NIL; /* rsh command */ static char *rshpath = NIL; /* rsh path */ static long sshtimeout = 15; /* ssh timeout */ static char *sshcommand = NIL; /* ssh command */ static char *sshpath = NIL; /* ssh path */ static long allowreversedns = T;/* allow reverse DNS lookup */ static long tcpdebug = NIL; /* extra TCP debugging telemetry */ static char *myClientAddr = NIL;/* client IP address */ static char *myClientHost = NIL;/* client DNS name */ static long myClientPort = -1; /* client port number */ static char *myServerAddr = NIL;/* server IP address */ static char *myServerHost = NIL;/* server DNS name */ static long myServerPort = -1; /* server port number */ extern long maxposint; /* get this from write.c */ /* Local function prototypes */ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, char *tmp,int *ctr,char *hst); static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size, long *contd); long tcp_abort (TCPSTREAM *stream); char *tcp_name (struct sockaddr *sadr,long flag); char *tcp_name_valid (char *s); /* TCP/IP manipulate parameters * Accepts: function code * function-dependent value * Returns: function-dependent return value */ void *tcp_parameters (long function,void *value) { void *ret = NIL; switch ((int) function) { case SET_TIMEOUT: tmoh = (tcptimeout_t) value; case GET_TIMEOUT: ret = (void *) tmoh; break; case SET_OPENTIMEOUT: ttmo_open = (long) value; case GET_OPENTIMEOUT: ret = (void *) ttmo_open; break; case SET_READTIMEOUT: ttmo_read = (long) value; case GET_READTIMEOUT: ret = (void *) ttmo_read; break; case SET_WRITETIMEOUT: ttmo_write = (long) value; case GET_WRITETIMEOUT: ret = (void *) ttmo_write; break; case SET_ALLOWREVERSEDNS: allowreversedns = (long) value; case GET_ALLOWREVERSEDNS: ret = (void *) allowreversedns; break; case SET_TCPDEBUG: tcpdebug = (long) value; case GET_TCPDEBUG: ret = (void *) tcpdebug; break; case SET_RSHTIMEOUT: rshtimeout = (long) value; case GET_RSHTIMEOUT: ret = (void *) rshtimeout; break; case SET_RSHCOMMAND: if (rshcommand) fs_give ((void **) &rshcommand); rshcommand = cpystr ((char *) value); case GET_RSHCOMMAND: ret = (void *) rshcommand; break; case SET_RSHPATH: if (rshpath) fs_give ((void **) &rshpath); rshpath = cpystr ((char *) value); case GET_RSHPATH: ret = (void *) rshpath; break; case SET_SSHTIMEOUT: sshtimeout = (long) value; case GET_SSHTIMEOUT: ret = (void *) sshtimeout; break; case SET_SSHCOMMAND: if (sshcommand) fs_give ((void **) &sshcommand); sshcommand = cpystr ((char *) value); case GET_SSHCOMMAND: ret = (void *) sshcommand; break; case SET_SSHPATH: if (sshpath) fs_give ((void **) &sshpath); sshpath = cpystr ((char *) value); case GET_SSHPATH: ret = (void *) sshpath; break; } return ret; } /* TCP/IP open * Accepts: host name * contact service name * contact port number and optional silent flag * Returns: TCP/IP stream if success else NIL */ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port) { TCPSTREAM *stream = NIL; int family; int sock = -1; int ctr = 0; int silent = (port & NET_SILENT) ? T : NIL; int *ctrp = (port & NET_NOOPENTIMEOUT) ? NIL : &ctr; char *s,*hostname,tmp[MAILTMPLEN]; void *adr; size_t adrlen; struct servent *sv = NIL; blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); void *data,*next; port &= 0xffff; /* erase flags */ /* lookup service */ if (service && (sv = getservbyname (service,"tcp"))) port = ntohs (sv->s_port); /* The domain literal form is used (rather than simply the dotted decimal as with other Unix programs) because it has to be a valid "host name" in mailsystem terminology. */ /* look like domain literal? */ if (host[0] == '[' && host[(strlen (host))-1] == ']') { strcpy (tmp,host+1); /* yes, copy number part */ tmp[(strlen (tmp))-1] = '\0'; if (adr = ip_stringtoaddr (tmp,&adrlen,&family)) { (*bn) (BLOCK_TCPOPEN,NIL); /* get an open socket for this system */ sock = tcp_socket_open (family,adr,adrlen,port,tmp,ctrp,hostname = host); (*bn) (BLOCK_NONE,NIL); fs_give ((void **) &adr); } else sprintf (tmp,"Bad format domain-literal: %.80s",host); } else { /* lookup host name */ if (tcpdebug) { sprintf (tmp,"DNS resolution %.80s",host); mm_log (tmp,TCPDEBUG); } (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); if (!(s = ip_nametoaddr (host,&adrlen,&family,&hostname,&next))) sprintf (tmp,"No such host as %.80s",host); (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); if (s) { /* DNS resolution won? */ if (tcpdebug) mm_log ("DNS resolution done",TCPDEBUG); do { (*bn) (BLOCK_TCPOPEN,NIL); if (((sock = tcp_socket_open (family,s,adrlen,port,tmp,ctrp, hostname)) < 0) && (s = ip_nametoaddr (NIL,&adrlen,&family,&hostname,&next)) && !silent) mm_log (tmp,WARN); (*bn) (BLOCK_NONE,NIL); } while ((sock < 0) && s);/* repeat until success or no more addreses */ } } if (sock >= 0) { /* won */ stream = (TCPSTREAM *) memset (fs_get (sizeof (TCPSTREAM)),0, sizeof (TCPSTREAM)); stream->port = port; /* port number */ /* init sockets */ stream->tcpsi = stream->tcpso = sock; /* stash in the snuck-in byte */ if (stream->ictr = ctr) *(stream->iptr = stream->ibuf) = tmp[0]; /* copy official host name */ stream->host = cpystr (hostname); if (tcpdebug) mm_log ("Stream open and ready for read",TCPDEBUG); } else if (!silent) mm_log (tmp,ERROR); return stream; /* return success */ } /* Open a TCP socket * Accepts: protocol family * address to connect to * address length * port * scratch buffer * pointer to "first byte read in" storage or NIL * host name for error message * Returns: socket if success, else -1 with error string in scratch buffer */ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port, char *tmp,int *ctr,char *hst) { int i,ti,sock,flgs,tmo; struct pollfd pfd; size_t len; time_t now; struct protoent *pt = getprotobyname ("tcp"); struct sockaddr *sadr = ip_sockaddr (family,adr,adrlen,port,&len); blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); /* fetid Solaris */ void *data = (*bn) (BLOCK_SENSITIVE,NIL); sprintf (tmp,"Trying IP address [%s]",ip_sockaddrtostring (sadr)); mm_log (tmp,NIL); /* make a socket */ if ((sock = socket (sadr->sa_family,SOCK_STREAM,pt ? pt->p_proto : 0)) < 0) { sprintf (tmp,"Unable to create TCP socket: %s",strerror (errno)); (*bn) (BLOCK_NONSENSITIVE,data); } else { /* get current socket flags */ flgs = fcntl (sock,F_GETFL,0); /* set non-blocking if want open timeout */ if (ctr) fcntl (sock,F_SETFL,flgs | FNDELAY); /* open connection */ while ((i = connect (sock,sadr,len)) < 0 && (errno == EINTR)); (*bn) (BLOCK_NONSENSITIVE,data); if (i < 0) switch (errno) { /* failed? */ case EAGAIN: /* DG brain damage */ case EINPROGRESS: /* what we expect to happen */ case EALREADY: /* or another form of it */ case EISCONN: /* restart after interrupt? */ case EADDRINUSE: /* restart after interrupt? */ break; /* well, not really, it was interrupted */ default: sprintf (tmp,"Can't connect to %.80s,%u: %s",hst,(unsigned int) port, strerror (errno)); close (sock); /* flush socket */ sock = -1; } if ((sock >= 0) && ctr) { /* want open timeout? */ now = time (0); /* open timeout */ ti = ttmo_open ? now + ttmo_open : 0; pfd.fd = sock; pfd.events = POLLIN | POLLOUT; do { /* block under timeout */ tmo = ti ? ti - now : 0; i = poll (&pfd, 1, ti ? tmo * 1000 : -1); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); if (i > 0) { /* success, make sure really connected */ /* restore blocking status */ fcntl (sock,F_SETFL,flgs); /* This used to be a zero-byte read(), but that crashes Solaris */ /* get socket status */ if(pfd.revents & POLLIN) while (((i = *ctr = read (sock,tmp,1)) < 0) && (errno == EINTR)); } if (i <= 0) { /* timeout or error? */ i = i ? errno : ETIMEDOUT;/* determine error code */ close (sock); /* flush socket */ sock = -1; errno = i; /* return error code */ sprintf (tmp,"Connection failed to %.80s,%lu: %s",hst, (unsigned long) port,strerror (errno)); } } } fs_give ((void **) &sadr); return sock; /* return the socket */ } /* TCP/IP authenticated open * Accepts: host name * service name * returned user name buffer * Returns: TCP/IP stream if success else NIL */ #define MAXARGV 20 TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf) { TCPSTREAM *stream = NIL; void *adr; char host[MAILTMPLEN],tmp[MAILTMPLEN],*path,*argv[MAXARGV+1],*r; int i,ti,pipei[2],pipeo[2]; size_t len; time_t now; struct timeval tmo; fd_set fds,efds; blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); #ifdef SSHPATH /* ssh path defined yet? */ if (!sshpath) sshpath = cpystr (SSHPATH); #endif #ifdef RSHPATH /* rsh path defined yet? */ if (!rshpath) rshpath = cpystr (RSHPATH); #endif if (*service == '*') { /* want ssh? */ /* return immediately if ssh disabled */ if (!(sshpath && (ti = sshtimeout))) return NIL; /* ssh command prototype defined yet? */ if (!sshcommand) sshcommand = cpystr ("%s %s -l %s exec /etc/r%sd"); } /* want rsh? */ else if (rshpath && (ti = rshtimeout)) { /* rsh command prototype defined yet? */ if (!rshcommand) rshcommand = cpystr ("%s %s -l %s exec /etc/r%sd"); } else return NIL; /* rsh disabled */ /* look like domain literal? */ if (mb->host[0] == '[' && mb->host[i = (strlen (mb->host))-1] == ']') { strcpy (host,mb->host+1); /* yes, copy without brackets */ host[i-1] = '\0'; /* validate domain literal */ if (adr = ip_stringtoaddr (host,&len,&i)) fs_give ((void **) &adr); else { sprintf (tmp,"Bad format domain-literal: %.80s",host); mm_log (tmp,ERROR); return NIL; } } else strcpy (host,tcp_canonical (mb->host)); if (*service == '*') /* build ssh command */ sprintf (tmp,sshcommand,sshpath,host, mb->user[0] ? mb->user : myusername (),service + 1); else sprintf (tmp,rshcommand,rshpath,host, mb->user[0] ? mb->user : myusername (),service); if (tcpdebug) { char msg[MAILTMPLEN]; sprintf (msg,"Trying %.100s",tmp); mm_log (msg,TCPDEBUG); } /* parse command into argv */ for (i = 1,path = argv[0] = strtok_r (tmp," ",&r); (i < MAXARGV) && (argv[i] = strtok_r (NIL," ",&r)); i++); argv[i] = NIL; /* make sure argv tied off */ /* make command pipes */ if (pipe (pipei) < 0) return NIL; if ((pipei[0] >= FD_SETSIZE) || (pipei[1] >= FD_SETSIZE) || (pipe (pipeo) < 0)) { close (pipei[0]); close (pipei[1]); return NIL; } (*bn) (BLOCK_TCPOPEN,NIL); /* quell alarm up here for NeXT */ if ((pipeo[0] >= FD_SETSIZE) || (pipeo[1] >= FD_SETSIZE) || ((i = fork ()) < 0)) { /* make inferior process */ close (pipei[0]); close (pipei[1]); close (pipeo[0]); close (pipeo[1]); (*bn) (BLOCK_NONE,NIL); return NIL; } if (!i) { /* if child */ alarm (0); /* never have alarms in children */ if (!fork ()) { /* make grandchild so it's inherited by init */ int cf; /* don't alter parent vars in case vfork() */ int maxfd = max (20,max (max(pipei[0],pipei[1]),max(pipeo[0],pipeo[1]))); dup2 (pipei[1],1); /* parent's input is my output */ dup2 (pipei[1],2); /* parent's input is my error output too */ dup2 (pipeo[0],0); /* parent's output is my input */ /* close all unnecessary descriptors */ for (cf = 3; cf <= maxfd; cf++) close (cf); setpgrp (0,getpid ()); /* be our own process group */ _exit (execv (path,argv));/* now run it */ } _exit (1); /* child is done */ } grim_pid_reap (i,NIL); /* reap child; grandchild now owned by init */ close (pipei[1]); /* close child's side of the pipes */ close (pipeo[0]); /* create TCP/IP stream */ stream = (TCPSTREAM *) memset (fs_get (sizeof (TCPSTREAM)),0, sizeof (TCPSTREAM)); /* copy remote host name from argument */ stream->remotehost = cpystr (stream->host = cpystr (host)); stream->tcpsi = pipei[0]; /* init sockets */ stream->tcpso = pipeo[1]; stream->ictr = 0; /* init input counter */ stream->port = 0xffffffff; /* no port number */ ti += now = time (0); /* open timeout */ tmo.tv_usec = 0; /* initialize usec timeout */ FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ FD_SET (stream->tcpsi,&fds); /* set bit in selection vector */ FD_SET (stream->tcpsi,&efds); /* set bit in error selection vector */ FD_SET (stream->tcpso,&efds); /* set bit in error selection vector */ do { /* block under timeout */ tmo.tv_sec = ti - now; i = select (max (stream->tcpsi,stream->tcpso)+1,&fds,NIL,&efds,&tmo); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); if (i <= 0) { /* timeout or error? */ sprintf (tmp,i ? "error in %s to IMAP server" : "%s to IMAP server timed out",(*service == '*') ? "ssh" : "rsh"); mm_log (tmp,WARN); tcp_close (stream); /* punt stream */ stream = NIL; } (*bn) (BLOCK_NONE,NIL); /* return user name */ strcpy (usrbuf,mb->user[0] ? mb->user : myusername ()); return stream; /* return success */ } /* TCP receive line * Accepts: TCP stream * Returns: text line string or NIL if failure */ char *tcp_getline (TCPSTREAM *stream) { unsigned long n,contd; char *ret = tcp_getline_work (stream,&n,&contd); if (ret && contd) { /* got a line needing continuation? */ STRINGLIST *stl = mail_newstringlist (); STRINGLIST *stc = stl; do { /* collect additional lines */ stc->text.data = (unsigned char *) ret; stc->text.size = n; stc = stc->next = mail_newstringlist (); ret = tcp_getline_work (stream,&n,&contd); } while (ret && contd); if (ret) { /* stash final part of line on list */ stc->text.data = (unsigned char *) ret; stc->text.size = n; /* determine how large a buffer we need */ for (n = 0, stc = stl; stc; stc = stc->next) n += stc->text.size; ret = fs_get (n + 1); /* copy parts into buffer */ for (n = 0, stc = stl; stc; n += stc->text.size, stc = stc->next) memcpy (ret + n,stc->text.data,stc->text.size); ret[n] = '\0'; } mail_free_stringlist (&stl);/* either way, done with list */ } return ret; } /* TCP receive line or partial line * Accepts: TCP stream * pointer to return size * pointer to return continuation flag * Returns: text line string, size and continuation flag, or NIL if failure */ static char *tcp_getline_work (TCPSTREAM *stream,unsigned long *size, long *contd) { unsigned long n; char *s,*ret,c,d; *contd = NIL; /* assume no continuation */ /* make sure have data */ if (!tcp_getdata (stream)) return NIL; for (s = stream->iptr, n = 0, c = '\0'; stream->ictr--; n++, c = d) { d = *stream->iptr++; /* slurp another character */ if ((c == '\015') && (d == '\012')) { ret = (char *) fs_get (n--); memcpy (ret,s,*size = n); /* copy into a free storage string */ ret[n] = '\0'; /* tie off string with null */ return ret; } } /* copy partial string from buffer */ memcpy ((ret = (char *) fs_get (n)),s,*size = n); /* get more data from the net */ if (!tcp_getdata (stream)) fs_give ((void **) &ret); /* special case of newline broken by buffer */ else if ((c == '\015') && (*stream->iptr == '\012')) { stream->iptr++; /* eat the line feed */ stream->ictr--; ret[*size = --n] = '\0'; /* tie off string with null */ } else *contd = LONGT; /* continuation needed */ return ret; } /* TCP/IP receive buffer * Accepts: TCP/IP stream * size in bytes * buffer to read into * Returns: T if success, NIL otherwise */ long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s) { unsigned long n; /* make sure socket still alive */ if (stream->tcpsi < 0) return NIL; /* can transfer bytes from buffer? */ if (n = min (size,stream->ictr)) { memcpy (s,stream->iptr,n); /* yes, slurp as much as we can from it */ s += n; /* update pointer */ stream->iptr +=n; size -= n; /* update # of bytes to do */ stream->ictr -=n; } if (size) { int i, tmo; struct pollfd pfd; time_t t = time (0); blocknotify_t bn=(blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); (*bn) (BLOCK_TCPREAD,NIL); while (size > 0) { /* until request satisfied */ time_t tl = time (0); time_t now = tl; time_t ti = ttmo_read ? now + ttmo_read : 0; if (tcpdebug) mm_log ("Reading TCP buffer",TCPDEBUG); pfd.events = POLLIN; pfd.fd = stream->tcpsi; errno = NIL; /* initially no error */ do { /* block under timeout */ tmo = ti ? ti - now : 0; i = poll (&pfd, 1, ti ? tmo * 1000 : -1); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); if (i) { /* non-timeout result from select? */ if (i > 0) /* read what we can */ while (((i = read (stream->tcpsi,s,(int) min (maxposint,size))) < 0) && (errno == EINTR)); if (i <= 0) { /* error seen? */ if (tcpdebug) { char tmp[MAILTMPLEN]; if (i) sprintf (s = tmp,"TCP buffer read I/O error %d",errno); else s = "TCP buffer read end of file"; mm_log (s,TCPDEBUG); } return tcp_abort (stream); } s += i; /* success, point at new place to write */ size -= i; /* reduce byte count */ if (tcpdebug) mm_log ("Successfully read TCP buffer",TCPDEBUG); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { if (tcpdebug) mm_log ("TCP buffer read timeout",TCPDEBUG); return tcp_abort (stream); } } (*bn) (BLOCK_NONE,NIL); } *s = '\0'; /* tie off string */ return LONGT; } /* TCP/IP receive data * Accepts: TCP/IP stream * Returns: T if success, NIL otherwise */ long tcp_getdata (TCPSTREAM *stream) { int i, tmo; struct pollfd pfd; time_t t = time (0); blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); if (stream->tcpsi < 0) return NIL; (*bn) (BLOCK_TCPREAD,NIL); while (stream->ictr < 1) { /* if nothing in the buffer */ time_t tl = time (0); /* start of request */ time_t now = tl; time_t ti = ttmo_read ? now + ttmo_read : 0; if (tcpdebug) mm_log ("Reading TCP data",TCPDEBUG); pfd.fd = stream->tcpsi; pfd.events = POLLIN; errno = NIL; /* initially no error */ do { /* block under timeout */ tmo = ti ? ti - now : 0; i = poll (&pfd, 1, ti ? tmo * 1000 : -1); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); if (i) { /* non-timeout result from select? */ /* read what we can */ if (i > 0) while (((i = read (stream->tcpsi,stream->ibuf,BUFLEN)) < 0) && (errno == EINTR)); if (i <= 0) { /* error seen? */ if (tcpdebug) { char *s,tmp[MAILTMPLEN]; if (i) sprintf (s = tmp,"TCP data read I/O error %d",errno); else s = "TCP data read end of file"; mm_log (s,TCPDEBUG); } return tcp_abort (stream); } stream->ictr = i; /* success, set new count and pointer */ stream->iptr = stream->ibuf; if (tcpdebug) mm_log ("Successfully read TCP data",TCPDEBUG); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { if (tcpdebug) mm_log ("TCP data read timeout",TCPDEBUG); return tcp_abort (stream);/* error or timeout no-continue */ } } (*bn) (BLOCK_NONE,NIL); return T; } /* TCP/IP send string as record * Accepts: TCP/IP stream * string pointer * Returns: T if success else NIL */ long tcp_soutr (TCPSTREAM *stream,char *string) { return tcp_sout (stream,string,(unsigned long) strlen (string)); } /* TCP/IP send string * Accepts: TCP/IP stream * string pointer * byte count * Returns: T if success else NIL */ long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size) { int i, tmo; struct pollfd pfd; time_t t = time (0); blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); if (stream->tcpso < 0) return NIL; (*bn) (BLOCK_TCPWRITE,NIL); while (size > 0) { /* until request satisfied */ time_t tl = time (0); /* start of request */ time_t now = tl; time_t ti = ttmo_write ? now + ttmo_write : 0; if (tcpdebug) mm_log ("Writing to TCP",TCPDEBUG); pfd.fd = stream->tcpso; pfd.events = POLLOUT; errno = NIL; /* block and write */ do { /* block under timeout */ tmo = ti ? ti - now : 0; i = poll (&pfd, 1, ti ? tmo * 1000 : -1); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); if (i) { /* non-timeout result from select? */ /* write what we can */ if (i > 0) while (((i = write (stream->tcpso,string,size)) < 0) && (errno == EINTR)); if (i <= 0) { /* error seen? */ if (tcpdebug) { char tmp[MAILTMPLEN]; sprintf (tmp,"TCP write I/O error %d",errno); mm_log (tmp,TCPDEBUG); } return tcp_abort (stream); } string += i; /* how much we sent */ size -= i; /* count this size */ if (tcpdebug) mm_log ("successfully wrote to TCP",TCPDEBUG); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { if (tcpdebug) mm_log ("TCP write timeout",TCPDEBUG); return tcp_abort (stream); } } (*bn) (BLOCK_NONE,NIL); return T; /* all done */ } /* TCP/IP close * Accepts: TCP/IP stream */ void tcp_close (TCPSTREAM *stream) { tcp_abort (stream); /* nuke the stream */ /* flush host names */ if (stream->host) fs_give ((void **) &stream->host); if (stream->remotehost) fs_give ((void **) &stream->remotehost); if (stream->localhost) fs_give ((void **) &stream->localhost); fs_give ((void **) &stream); /* flush the stream */ } /* TCP/IP abort stream * Accepts: TCP/IP stream * Returns: NIL always */ long tcp_abort (TCPSTREAM *stream) { blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); if (stream->tcpsi >= 0) { /* no-op if no socket */ (*bn) (BLOCK_TCPCLOSE,NIL); close (stream->tcpsi); /* nuke the socket */ if (stream->tcpsi != stream->tcpso) close (stream->tcpso); stream->tcpsi = stream->tcpso = -1; } (*bn) (BLOCK_NONE,NIL); return NIL; } /* TCP/IP get host name * Accepts: TCP/IP stream * Returns: host name for this stream */ char *tcp_host (TCPSTREAM *stream) { return stream->host; /* use tcp_remotehost() if want guarantees */ } /* TCP/IP get remote host name * Accepts: TCP/IP stream * Returns: host name for this stream */ char *tcp_remotehost (TCPSTREAM *stream) { if (!stream->remotehost) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); stream->remotehost = /* get socket's peer name */ getpeername (stream->tcpsi,sadr,(void *) &sadrlen) ? cpystr (stream->host) : tcp_name (sadr,NIL); fs_give ((void **) &sadr); } return stream->remotehost; } /* TCP/IP return port for this stream * Accepts: TCP/IP stream * Returns: port number for this stream */ unsigned long tcp_port (TCPSTREAM *stream) { return stream->port; /* return port number */ } /* TCP/IP get local host name * Accepts: TCP/IP stream * Returns: local host name */ char *tcp_localhost (TCPSTREAM *stream) { if (!stream->localhost) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); stream->localhost = /* get socket's name */ ((stream->port & 0xffff000) || getsockname (stream->tcpsi,sadr,(void *) &sadrlen)) ? cpystr (mylocalhost ()) : tcp_name (sadr,NIL); fs_give ((void **) &sadr); } return stream->localhost; /* return local host name */ } /* TCP/IP get client host address (server calls only) * Returns: client host address */ char *tcp_clientaddr () { if (!myClientAddr) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if (getpeername (0,sadr,(void *) &sadrlen)) myClientAddr = cpystr ("UNKNOWN"); else { /* get stdin's peer name */ myClientAddr = cpystr (ip_sockaddrtostring (sadr)); if (myClientPort < 0) myClientPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); } return myClientAddr; } /* TCP/IP get client host name (server calls only) * Returns: client host name */ char *tcp_clienthost () { if (!myClientHost) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if (getpeername (0,sadr,(void *) &sadrlen)) { char *s,*t,*v,tmp[MAILTMPLEN]; if ((s = getenv (t = "SSH_CLIENT")) || (s = getenv (t = "KRB5REMOTEADDR")) || (s = getenv (t = "SSH2_CLIENT"))) { if (v = strchr (s,' ')) *v = '\0'; sprintf (v = tmp,"%.80s=%.80s",t,s); } else v = "UNKNOWN"; myClientHost = cpystr (v); } else { /* get stdin's peer name */ myClientHost = tcp_name (sadr,T); if (!myClientAddr) myClientAddr = cpystr (ip_sockaddrtostring (sadr)); if (myClientPort < 0) myClientPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); } return myClientHost; } /* TCP/IP get client port number (server calls only) * Returns: client port number */ long tcp_clientport () { if (!myClientHost && !myClientAddr) tcp_clientaddr (); return myClientPort; } /* TCP/IP get server host address (server calls only) * Returns: server host address */ char *tcp_serveraddr () { if (!myServerAddr) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if (getsockname (0,sadr,(void *) &sadrlen)) myServerAddr = cpystr ("UNKNOWN"); else { /* get stdin's name */ myServerAddr = cpystr (ip_sockaddrtostring (sadr)); if (myServerPort < 0) myServerPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); } return myServerAddr; } /* TCP/IP get server host name (server calls only) * Returns: server host name */ char *tcp_serverhost () { if (!myServerHost) { /* once-only */ size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); /* get stdin's name */ if (getsockname (0,sadr,(void *) &sadrlen)) myServerHost = cpystr (mylocalhost ()); else { /* get stdin's name */ myServerHost = tcp_name (sadr,NIL); if (!myServerAddr) myServerAddr = cpystr (ip_sockaddrtostring (sadr)); if (myServerPort < 0) myServerPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); } return myServerHost; } /* TCP/IP get server port number (server calls only) * Returns: server port number */ long tcp_serverport () { if (!myServerHost && !myServerAddr) tcp_serveraddr (); return myServerPort; } /* TCP/IP return canonical form of host name * Accepts: host name * Returns: canonical form of host name */ char *tcp_canonical (char *name) { char *ret,host[MAILTMPLEN]; blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); void *data; /* look like domain literal? */ if (name[0] == '[' && name[strlen (name) - 1] == ']') return name; (*bn) (BLOCK_DNSLOOKUP,NIL); /* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); if (tcpdebug) { sprintf (host,"DNS canonicalization %.80s",name); mm_log (host,TCPDEBUG); } /* get canonical name */ if (!ip_nametoaddr (name,NIL,NIL,&ret,NIL)) ret = name; (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); /* alarms OK now */ if (tcpdebug) mm_log ("DNS canonicalization done",TCPDEBUG); return ret; } /* TCP/IP return name from socket * Accepts: socket * verbose flag * Returns: cpystr name */ char *tcp_name (struct sockaddr *sadr,long flag) { char *ret,*t,adr[MAILTMPLEN],tmp[MAILTMPLEN]; sprintf (ret = adr,"[%.80s]",ip_sockaddrtostring (sadr)); if (allowreversedns) { blocknotify_t bn = (blocknotify_t)mail_parameters(NIL,GET_BLOCKNOTIFY,NIL); void *data; if (tcpdebug) { sprintf (tmp,"Reverse DNS resolution %s",adr); mm_log (tmp,TCPDEBUG); } (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); /* translate address to name */ if (t = tcp_name_valid (ip_sockaddrtoname (sadr))) { /* produce verbose form if needed */ if (flag) sprintf (ret = tmp,"%s %s",t,adr); else ret = t; } (*bn) (BLOCK_NONSENSITIVE,data); (*bn) (BLOCK_NONE,NIL); /* alarms OK now */ if (tcpdebug) mm_log ("Reverse DNS resolution done",TCPDEBUG); } return cpystr (ret); } /* TCP/IP validate name * Accepts: domain name * Returns: name if valid, NIL otherwise */ char *tcp_name_valid (char *s) { int c; char *ret,*tail; /* must be non-empty and not too long */ if ((ret = (s && *s) ? s : NIL) && (tail = ret + NETMAXHOST)) { /* must be alnum, dot, or hyphen */ while ((c = *s++) && (s <= tail) && (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || (c == '-') || (c == '.'))); if (c) ret = NIL; } return ret; } /* TCP/IP check if client is given host name * Accepts: candidate host name * Returns: T if match, NIL otherwise */ long tcp_isclienthost (char *host) { int family; size_t adrlen,sadrlen,len; void *adr,*next; struct sockaddr *sadr; long ret = NIL; /* make sure that myClientAddr is set */ if (tcp_clienthost () && myClientAddr) /* get sockaddr of client */ for (adr = ip_nametoaddr (host,&adrlen,&family,NIL,&next); adr && !ret; adr = ip_nametoaddr (NIL,&adrlen,&family,NIL,&next)) { /* build sockaddr of given address */ sadr = ip_sockaddr (family,adr,adrlen,1,&len); if (!strcmp (myClientAddr,ip_sockaddrtostring (sadr))) ret = LONGT; fs_give ((void **) &sadr); /* done with client sockaddr */ } return ret; } /* Following statement must be at end of this module */ #undef fork /* undo any use of vfork() */