1
# sentinel.tcl v2.60 (29 March 2001)
2
# Copyright 1998-2001 by slennox <slennox@egghelp.org>
1
# sentinel.tcl v2.70 (15 April 2002)
2
# Copyright 1998-2002 by slennox
3
3
# slennox's eggdrop page - http://www.egghelp.org/
5
5
# Flood protection system for eggdrop, with integrated BitchX CTCP
14
14
# v2.50 - Locktimes of less than 30 were erroneously allowed.
15
15
# putquick -next is now supported (eggdrop 1.5+) for faster channel
17
# Ban mechanism now checks if flooders are coming from the same
17
# - Ban mechanism now checks if flooders are coming from the same
18
18
# domain or ident and performs wildcard bans instead of banning
19
19
# each IP/host individually.
20
# Added tsunami detection to the avalanche flood detection system.
21
# Variables are now cleared after removing a channel.
22
# Removed unnecessary botonchan checks throughout components where
20
# - Added tsunami detection to the avalanche flood detection system.
21
# - Variables are now cleared after removing a channel.
22
# - Removed unnecessary botonchan checks throughout components where
23
23
# botisop already checks for that.
24
# Removed all unnecessary use of parentheses.
24
# - Removed all unnecessary use of parentheses.
25
25
# v2.60 - Modified putquick compatibility proc.
26
# Added sl_wideban option to make domain/ident bans optional.
27
# Fixed typos in various ban-related functions.
28
# Unused procs are now unloaded.
29
# Wildcard bans covering domains/idents were not doing proper
26
# - Added sl_wideban option to make domain/ident bans optional.
27
# - Fixed typos in various ban-related functions.
28
# - Unused procs are now unloaded.
29
# - Wildcard bans covering domains/idents were not doing proper
30
30
# checks on join-part flooders.
31
# v2.70 - Fixed "allbans" error which could occur when sl_wideban is
33
# - Added sl_masktype option, currently offering three different
34
# ban/ignore mask types.
35
# - Merged unsets in sl_unsetarray.
36
# - Changed use of "split" in timers to the less ugly "list".
32
38
# sentinel.tcl is centered around its channel lock mechanism. It sets the
33
39
# channel +mi (moderated and invite-only) whenever a substantial flood on
82
88
# bot's internal ban list until it expires.
83
89
# - For greater protection against large channel floods, I recommend you
84
90
# also use a channel limiter script, such as chanlimit.tcl.
91
# - There is a trade-off between convenience and security. The more
92
# automation you enable, the more stress the bot will be under during a
93
# flood and the more stuff it will be sending to the server.
85
94
# - Where security is paramount, have one or two bots that aren't running
86
95
# sentinel.tcl. Since sentinel.tcl is a complex script with many
87
# automated and convenience features, there is a small potential for
96
# automated and convenience features, there is a potential for
90
99
# The following flood settings are in number:seconds format, 0:0 to
177
186
set sl_igtime 240
178
187
# Valid settings: 1 or higher.
189
# Select the type of hostmask to use when banning and/or ignoring flooders.
190
# There are three to choose from:
191
# 0 - *!*@machine.domain.com / *!*@555.555.555.555
192
# 1 - *!*ident@machine.domain.com / *!*ident@555.555.555.555
193
# 2 - *!*ident@*.domain.com / *!*ident@555.555.555.*
194
# The default option, 0, is strongly recommended for most situations, and
195
# provides the best level of protection. The other two options are provided
196
# mainly for special cases.
198
# Valid settings: 0, 1, or 2, depending on the hostmask type you wish to use.
180
200
# Length of time in seconds to set channel +i if flooded. If set to 0, +i
181
201
# will not be removed automatically.
182
202
set sl_ilocktime 120
256
276
if {$nick == $botnick} {return 0}
257
277
if {$sl_ban && !$sl_locked($chan) && ![matchattr $hand f|f $chan]} {
258
278
lappend sl_ccbannick($chan) $nick ; lappend sl_ccbanhost($chan) [string tolower $uhost]
259
utimer [lindex $sl_ccflood 1] [split "sl_ccbanqueue $chan"]
279
utimer [lindex $sl_ccflood 1] [list sl_ccbanqueue $chan]
261
281
if {$sl_flooded($chan)} {return 1}
262
282
incr sl_ccqueue($chan)
263
utimer [lindex $sl_ccflood 1] [split "sl_ccqueuereset $chan"]
283
utimer [lindex $sl_ccflood 1] [list sl_ccqueuereset $chan]
264
284
if {$sl_ccqueue($chan) >= [lindex $sl_ccflood 0]} {
265
285
sl_lock $chan "CTCP flood" ${botnet-nick} ; return 1
270
290
sl_ignore [string tolower $uhost] $hand "CTCP flooder" ; return 1
273
utimer [lindex $sl_bcflood 1] "incr sl_bcqueue -1"
293
utimer [lindex $sl_bcflood 1] {incr sl_bcqueue -1}
274
294
if {$sl_bcqueue >= [lindex $sl_bcflood 0]} {
275
295
putlog "sentinel: CTCP flood detected on me! Stopped answering CTCPs temporarily."
276
296
set sl_bflooded 1
277
utimer [lindex $sl_bcflood 1] "set sl_bflooded 0"
297
utimer [lindex $sl_bcflood 1] {set sl_bflooded 0}
278
298
if {[info commands sendnote] != ""} {
279
299
foreach recipient $sl_note {
280
300
if {[validuser $recipient]} {
289
309
if {!$sl_bxsimul} {return 0}
290
310
if {$sl_bxonestack} {return 1}
291
set sl_bxonestack 1 ; utimer 2 "set sl_bxonestack 0"
311
set sl_bxonestack 1 ; utimer 2 {set sl_bxonestack 0}
292
312
switch -exact -- $key {
294
314
set bxcmd [string toupper $arg]
390
410
sl_ignore [string tolower $uhost] $hand "MSG flooder" ; return 0
393
utimer [lindex $sl_bmflood 1] "incr sl_bmqueue -1"
413
utimer [lindex $sl_bmflood 1] {incr sl_bmqueue -1}
394
414
if {$sl_bmqueue >= [lindex $sl_bmflood 0]} {
395
415
putlog "sentinel: MSG flood detected on me! Stopped answering MSGs temporarily."
396
416
set sl_bflooded 1
397
utimer [lindex $sl_bmflood 1] "set sl_bflooded 0"
417
utimer [lindex $sl_bmflood 1] {set sl_bflooded 0}
398
418
if {[info commands sendnote] != ""} {
399
419
foreach recipient $sl_note {
400
420
if {[validuser $recipient]} {
426
446
set hand [nick2hand $nick $chan]
427
447
if {$sl_ban && !$sl_locked($chan) && $nick != $botnick && ![matchattr $hand f|f $chan]} {
428
448
lappend sl_avbannick($chan) $nick ; lappend sl_avbanhost($chan) [string tolower $uhost]
429
utimer [lindex $sl_avflood 1] [split "sl_avbanqueue $chan"]
449
utimer [lindex $sl_avflood 1] [list sl_avbanqueue $chan]
431
451
if {$sl_flooded($chan)} {return 0}
432
452
incr sl_avqueue($chan)
433
utimer [lindex $sl_avflood 1] [split "sl_avqueuereset $chan"]
453
utimer [lindex $sl_avflood 1] [list sl_avqueuereset $chan]
434
454
if {$sl_avqueue($chan) >= [lindex $sl_avflood 0]} {
435
455
sl_lock $chan "AVALANCHE/TSUNAMI flood" ${botnet-nick}
451
471
if {[isop $newnick $chan]} {return 0}
452
472
if {$sl_ban && !$sl_locked($chan) && $nick != $botnick && ![matchattr $hand f|f $chan]} {
453
473
lappend sl_nkbanhost($chan) [string tolower $uhost]
454
utimer [lindex $sl_nkflood 1] [split "sl_nkbanqueue $chan"]
474
utimer [lindex $sl_nkflood 1] [list sl_nkbanqueue $chan]
456
476
if {!$sl_nickkick && $sl_flooded($chan) && $sl_locked($chan)} {
457
477
putserv "KICK $chan $newnick :NICK flooder"
458
478
set sl_nickkick 1 ; set sl_nkflooding($chan) [unixtime]
460
set bhost *!*[string tolower [string range $uhost [string first @ $uhost] end]]
480
set bhost [string tolower [sl_masktype $uhost]]
461
481
if {$sl_globalban} {
462
482
if {[llength [banlist]] < $sl_banmax && ![isban $bhost] && ![matchban $bhost]} {
463
483
newban $bhost sentinel "NICK flooder" $sl_ban
471
utimer [expr [rand 2] + 3] "set sl_nickkick 0"
491
utimer [expr [rand 2] + 3] {set sl_nickkick 0}
474
494
if {$sl_flooded($chan)} {return 0}
475
495
incr sl_nkqueue($chan)
476
utimer [lindex $sl_nkflood 1] [split "sl_nkqueuereset $chan"]
496
utimer [lindex $sl_nkflood 1] [list sl_nkqueuereset $chan]
477
497
if {$sl_nkqueue($chan) >= [lindex $sl_nkflood 0]} {
478
498
sl_lock $chan "NICK flood" ${botnet-nick}
485
505
if {$nick == $botnick} {
486
506
sl_setarray $chan
488
set ihost *!*[string tolower [string range $uhost [string first @ $uhost] end]]
508
set ihost [string tolower [sl_masktype $uhost]]
489
509
if {[isignore $ihost]} {
490
510
killignore $ihost
492
512
set chan [string tolower $chan]
493
513
if {[lsearch -exact $sl_boflood 0] == -1 && [sl_checkbogus [lindex [split $uhost @] 0]]} {
494
514
if {!$sl_locked($chan) && ![matchattr $hand f|f $chan]} {
495
set bhost *!*[string tolower [string range $uhost [string first @ $uhost] end]]
515
set bhost [string tolower [sl_masktype $uhost]]
496
516
if {$sl_boban && [botisop $chan] && !$sl_flooded($chan)} {
497
517
putserv "KICK $chan $nick :BOGUS username"
498
518
if {$sl_globalban} {
509
529
lappend sl_bobannick($chan) $nick ; lappend sl_bobanhost($chan) [string tolower $uhost]
510
utimer [lindex $sl_boflood 1] [split "sl_bobanqueue $chan"]
530
utimer [lindex $sl_boflood 1] [list sl_bobanqueue $chan]
513
533
if {!$sl_flooded($chan)} {
514
534
incr sl_boqueue($chan)
515
utimer [lindex $sl_boflood 1] [split "sl_boqueuereset $chan"]
535
utimer [lindex $sl_boflood 1] [list sl_boqueuereset $chan]
516
536
if {$sl_boqueue($chan) >= [lindex $sl_boflood 0]} {
517
537
sl_lock $chan "BOGUS joins" ${botnet-nick}
521
541
if {[lsearch -exact $sl_jflood 0] == -1} {
522
542
if {$sl_ban && !$sl_locked($chan) && ![matchattr $hand f|f $chan]} {
523
543
lappend sl_jbannick($chan) $nick ; lappend sl_jbanhost($chan) [string tolower $uhost]
524
utimer [lindex $sl_jflood 1] [split "sl_jbanqueue $chan"]
544
utimer [lindex $sl_jflood 1] [list sl_jbanqueue $chan]
526
546
if {$sl_flooded($chan)} {return 0}
527
547
incr sl_jqueue($chan)
528
utimer [lindex $sl_jflood 1] [split "sl_jqueuereset $chan"]
548
utimer [lindex $sl_jflood 1] [list sl_jqueuereset $chan]
529
549
if {$sl_jqueue($chan) >= [lindex $sl_jflood 0] && $sl_pqueue($chan) >= [lindex $sl_jflood 0]} {
530
550
sl_lock $chan "JOIN-PART flood" ${botnet-nick}
544
564
if {[lsearch -exact $sl_jflood 0] != -1} {return 0}
545
565
if {$nick == $botnick} {
546
566
if {![validchan $chan]} {
547
timer 5 [split "sl_unsetarray $chan"]
567
timer 5 [list sl_unsetarray $chan]
551
571
set chan [string tolower $chan]
552
572
if {$sl_ban && !$sl_locked($chan) && ![matchattr $hand f|f $chan]} {
553
573
lappend sl_pbannick($chan) $nick ; lappend sl_pbanhost($chan) [string tolower $uhost]
554
utimer [lindex $sl_jflood 1] [split "sl_pbanqueue $chan"]
574
utimer [lindex $sl_jflood 1] [list sl_pbanqueue $chan]
556
576
if {$sl_flooded($chan)} {return 0}
557
577
incr sl_pqueue($chan)
558
utimer [lindex $sl_jflood 1] [split "sl_pqueuereset $chan"]
578
utimer [lindex $sl_jflood 1] [list sl_pqueuereset $chan]
566
586
set chan [string tolower $chan]
567
587
if {$sl_flooded($chan)} {return 0}
568
588
incr sl_pqueue($chan)
569
utimer [lindex $sl_jflood 1] [split "sl_pqueuereset $chan"]
589
utimer [lindex $sl_jflood 1] [list sl_pqueuereset $chan]
573
593
proc sl_lock {chan flood detected} {
574
594
global botnet-nick sl_bflooded sl_cfnotice sl_flooded sl_ilocktime sl_mlocktime sl_note
575
if {$detected == ${botnet-nick}} {
595
if {[string tolower $detected] == [string tolower ${botnet-nick}]} {
576
596
set sl_flooded($chan) 1 ; set sl_bflooded 1
577
597
if {[botisop $chan]} {
578
598
sl_quicklock $chan
579
599
sl_killutimer "sl_unlock $chan *"
580
600
sl_killutimer "set sl_bflooded 0"
581
601
if {$sl_mlocktime} {
582
utimer $sl_mlocktime [split "sl_unlock $chan m"]
602
utimer $sl_mlocktime [list sl_unlock $chan m]
584
604
if {$sl_ilocktime} {
585
utimer $sl_ilocktime [split "sl_unlock $chan i"]
605
utimer $sl_ilocktime [list sl_unlock $chan i]
587
utimer 120 "set sl_bflooded 0"
607
utimer 120 {set sl_bflooded 0}
588
608
putlog "sentinel: $flood detected on $chan! Channel locked temporarily."
589
609
if {$sl_cfnotice != ""} {
590
610
puthelp "NOTICE $chan :$sl_cfnotice"
593
613
putlog "sentinel: $flood detected on $chan! Cannot lock channel because I'm not opped."
594
utimer 120 "set sl_bflooded 0"
614
utimer 120 {set sl_bflooded 0}
597
617
putlog "sentinel: $flood detected by $detected on $chan!"
599
619
if {[info commands sendnote] != ""} {
600
620
foreach recipient $sl_note {
601
621
if {[validuser $recipient]} {
602
if {$detected == ${botnet-nick}} {
622
if {[string tolower $detected] == [string tolower ${botnet-nick}]} {
603
623
sendnote SENTINEL $recipient "$flood detected on $chan."
605
625
sendnote SENTINEL $recipient "$flood detected by $detected on $chan."
617
637
set sl_flooded($chan) 1 ; set sl_bflooded 1
618
638
sl_killutimer "sl_unlock $chan *"
619
639
sl_killutimer "set sl_bflooded 0"
620
utimer $sl_mlocktime [split "sl_unlock $chan m"] ; utimer $sl_ilocktime [split "sl_unlock $chan i"]
621
utimer 120 "set sl_bflooded 0"
640
utimer $sl_mlocktime [list sl_unlock $chan m] ; utimer $sl_ilocktime [list sl_unlock $chan i]
641
utimer 120 {set sl_bflooded 0}
623
643
set sl_flooded($chan) 0
624
644
if {![botisop $chan]} {return 0}
647
667
if {$mode == "+b" && $sl_bfmaxbans && !$sl_bfull($chan) && ![string match *i* [lindex [split [getchanmode $chan]] 0]] && [botisop $chan] && [llength [chanbans $chan]] >= $sl_bfmaxbans} {
648
668
putserv "MODE $chan +i"
649
669
set sl_bfull($chan) 1
650
utimer 5 [split "set sl_bfull($chan) 0"]
670
utimer 5 [list set sl_bfull($chan) 0]
651
671
putlog "sentinel: locked $chan due to full ban list!"
652
672
if {$sl_bfnotice != ""} {
653
673
puthelp "NOTICE $chan :$sl_bfnotice"
663
683
set sl_locked($chan) 1
665
685
sl_killutimer "sl_*banqueue $chan"
666
utimer 7 [split "sl_dokicks $chan"] ; utimer 16 [split "sl_setbans $chan"]
686
utimer 7 [list sl_dokicks $chan] ; utimer 16 [list sl_setbans $chan]
668
688
} elseif {$mode == "-i" || $mode == "-m"} {
669
689
set sl_locked($chan) 0
772
set allbans [sl_dfilter [concat $sl_ccbanhost($chan) $sl_avbanhost($chan) $sl_nkbanhost($chan) $sl_bobanhost($chan) $blist]]
752
773
if {$sl_wideban} {
753
set allbans [sl_dfilter [concat $sl_ccbanhost($chan) $sl_avbanhost($chan) $sl_nkbanhost($chan) $sl_bobanhost($chan) $blist]]
754
774
sl_ban $chan [sl_dcheck $allbans] "MULTIPLE IDENT/HOST flooders"
756
776
sl_ban $chan $sl_ccbanhost($chan) "CTCP flooder" ; set sl_ccbanhost($chan) ""
761
781
set sl_jbanhost($chan) "" ; set sl_pbanhost($chan) ""
762
782
if {$sl_shortlock && $sl_kflooders <= 2 && [llength $allbans] <= 2 && [expr [unixtime] - $sl_unlocked($chan)] > 120} {
763
783
sl_killutimer "sl_unlock $chan *"
764
utimer 10 [split "sl_unlock $chan mi"]
784
utimer 10 [list sl_unlock $chan mi]
779
799
proc sl_dcheck {bhosts} {
781
801
foreach bhost $bhosts {
782
set baddr [string tolower [lindex [split [maskhost $bhost] "@"] 1]]
783
set bident [string trimleft [string tolower [lindex [split $bhost "@"] 0]] "~"]
802
set baddr [lindex [split [maskhost $bhost] "@"] 1]
803
set bident [string trimleft [lindex [split $bhost "@"] 0] "~"]
784
804
if {![info exists baddrs($baddr)]} {
785
805
set baddrs($baddr) 1
812
832
foreach bhost $blist {
813
833
if {![string match *!* $bhost]} {
814
834
if {[matchban *!$bhost]} {continue}
815
set bhost *!*[string range $bhost [string first @ $bhost] end]
835
set bhost [sl_masktype $bhost]
816
836
if {[isban $bhost]} {continue}
818
838
if {[isban $bhost]} {continue}
825
if {[llength [banlist]] >= $sl_banmax || [isban $bhost]} {continue}
845
if {[llength [banlist]] >= $sl_banmax} {continue}
826
846
newban $bhost sentinel $reason $sl_ban
827
847
putlog "sentinel: banned $bhost ($reason)"
828
848
sl_ignore $bhost * $reason
831
851
foreach bhost $blist {
832
852
if {![string match *!* $bhost]} {
833
853
if {[matchban *!$bhost $chan]} {continue}
834
set bhost *!*[string range $bhost [string first @ $bhost] end]
854
set bhost [sl_masktype $bhost]
835
855
if {[isban $bhost $chan]} {continue}
837
857
if {[isban $bhost $chan]} {continue}
844
if {[llength [banlist $chan]] >= $sl_banmax || [isban $bhost $chan]} {continue}
864
if {[llength [banlist $chan]] >= $sl_banmax} {continue}
845
865
newchanban $chan $bhost sentinel $reason $sl_ban
846
866
putlog "sentinel: banned $bhost on $chan ($reason)"
847
867
sl_ignore $bhost * $reason
858
878
if {[matchattr $hand f|f $chan]} {return 0}
861
if {![string match *!* $ihost]} {
881
if {![string match *!* $ihost]} {
862
882
foreach ignore [ignorelist] {
863
if {[string match [string tolower [lindex $ignore 0]] [string tolower $ihost]]} {
883
if {[string match [string tolower [lindex $ignore 0]] $ihost]} {
867
set ihost *!*[string range $ihost [string first @ $ihost] end]
887
set ihost [sl_masktype $ihost]
868
888
if {[isignore $ihost]} {return 0}
870
890
if {[isignore $ihost]} {return 0}
1083
1104
proc sl_dcc {hand idx arg} {
1084
global sl_avflood sl_ban sl_banmax sl_bcflood sl_boban sl_boflood sl_bmflood sl_bxsimul sl_bfmaxbans sl_ccflood sl_globalban sl_igtime sl_jflood sl_kicks sl_lockcmds sl_lockflags sl_ilocktime sl_mlocktime sl_nkflood sl_note sl_shortlock sl_tsunami sl_txflood
1105
global sl_avflood sl_ban sl_banmax sl_bcflood sl_boban sl_boflood sl_bmflood sl_bxsimul sl_bfmaxbans sl_ccflood sl_detectquits sl_globalban sl_igtime sl_jflood sl_kicks sl_lockcmds sl_lockflags sl_ilocktime sl_mlocktime sl_nkflood sl_note sl_shortlock sl_tsunami sl_txflood
1085
1106
putcmdlog "#$hand# sentinel $arg"
1086
1107
putidx $idx "This bot is protected by sentinel.tcl by slennox"
1087
1108
putidx $idx "Current settings"
1121
1142
putidx $idx "- Channel BOGUS flood: [lindex $sl_boflood 0] in [lindex $sl_boflood 1] secs"
1144
if {$sl_detectquits} {
1145
set detectquits "quit detection ON"
1147
set detectquits "quit detection OFF"
1123
1149
if {[lsearch -exact $sl_jflood 0] != -1} {
1124
1150
putidx $idx "- Channel JOIN-PART flood: Off"
1126
putidx $idx "- Channel JOIN-PART flood: [lindex $sl_jflood 0] in [lindex $sl_jflood 1] secs"
1152
putidx $idx "- Channel JOIN-PART flood: [lindex $sl_jflood 0] in [lindex $sl_jflood 1] secs ($detectquits)"
1128
1154
if {[lsearch -exact $sl_nkflood 0] != -1} {
1129
1155
putidx $idx "- Channel NICK flood: Off"
1162
1188
if {$sl_ban || [lsearch -exact $sl_boflood 0] == -1} {
1163
1189
if {$sl_globalban} {
1164
putidx $idx "- Ban type: Global"
1190
putidx $idx "- Ban type: Global [sl_masktype nick@host.domain]"
1166
putidx $idx "- Ban type: Channel-specific"
1192
putidx $idx "- Ban type: Channel-specific [sl_masktype nick@host.domain]"
1169
1195
if {$sl_ban || [lsearch -exact $sl_boflood 0] == -1} {
1267
1293
global sl_avbanhost sl_avbannick sl_avqueue sl_bfull sl_bobanhost sl_bobannick sl_boqueue sl_ccbanhost sl_ccbannick sl_ccqueue sl_flooded sl_jbanhost sl_jbannick sl_jqueue sl_locked sl_nkbanhost sl_nkflooding sl_nkqueue sl_pbanhost sl_pbannick sl_pqueue sl_txqueue sl_unlocked
1268
1294
set chan [string tolower $chan]
1269
1295
if {![validchan $chan] && [info exists sl_flooded($chan)]} {
1270
unset sl_flooded($chan) ; unset sl_locked($chan) ; unset sl_unlocked($chan)
1271
unset sl_nkflooding($chan)
1272
unset sl_ccqueue($chan) ; unset sl_ccbanhost($chan) ; unset sl_ccbannick($chan)
1273
unset sl_avqueue($chan) ; unset sl_avbanhost($chan) ; unset sl_avbannick($chan)
1274
unset sl_txqueue($chan)
1275
unset sl_nkqueue($chan) ; unset sl_nkbanhost($chan)
1276
unset sl_boqueue($chan) ; unset sl_bobanhost($chan) ; unset sl_bobannick($chan)
1277
unset sl_jqueue($chan) ; unset sl_jbanhost($chan) ; unset sl_jbannick($chan)
1278
unset sl_pqueue($chan) ; unset sl_pbanhost($chan) ; unset sl_pbannick($chan)
1279
unset sl_bfull($chan)
1296
unset sl_flooded($chan) sl_locked($chan) sl_unlocked($chan) sl_nkflooding($chan) sl_ccqueue($chan) sl_ccbanhost($chan) sl_ccbannick($chan) sl_avqueue($chan) sl_avbanhost($chan) sl_avbannick($chan) sl_txqueue($chan) sl_nkqueue($chan) sl_nkbanhost($chan) sl_boqueue($chan) sl_bobanhost($chan) sl_bobannick($chan) sl_jqueue($chan) sl_jbanhost($chan) sl_jbannick($chan) sl_pqueue($chan) sl_pbanhost($chan) sl_pbannick($chan) sl_bfull($chan)
1320
proc sl_masktype {uhost} {
1322
switch -exact -- $sl_masktype {
1323
0 {return *!*[string range $uhost [string first @ $uhost] end]}
1324
1 {return *!*$uhost}
1325
2 {return *!*[lindex [split [maskhost $uhost] "!"] 1]}
1303
1330
if {![info exists sl_unlocked] && ![string match *sl_settimer* [utimers]]} {
1304
1331
utimer 3 sl_settimer
1362
1389
bind dcc $sl_lockflags|$sl_lockflags unlock sl_dccuc
1363
1390
if {!$sl_lockcmds} {
1364
1391
unbind pub $sl_lockflags|$sl_lockflags lc sl_lc
1392
unbind pub $sl_lockflags|$sl_lockflags uc sl_uc
1365
1393
rename sl_lc ""
1366
unbind pub $sl_lockflags|$sl_lockflags uc sl_uc
1367
1394
rename sl_uc ""
1369
1396
bind dcc m|m sentinel sl_dcc