How to use check_threshold() to add a threshold for notice / print?

Hello world,

I want the ip in the detection range to be printed at the first time and the tenth time it appears. It seems like the code has no grammatical mistake, but it doesn’t print like what i want:

@load base/frameworks/notice/main
@load base/utils/thresholds

module Conn;
 
export{
        redef enum Notice::Type += { IP_WIRED };
        
        global detection_range: set[subnet] = set( 192.168.1.0/16 );
        global count_threshold: GLOBAL::TrackCount;
		global notice_thresholds: vector of count = {1, 10};
        }
        
event connection_state_remove(c:connection)
        {
        if (check_threshold(notice_thresholds, count_threshold) && c$id$orig_h in detection_range)
        	{
        	print fmt("yes %s is in %s.", c$id$orig_h, detection_range);
        	}
        }

(Or just click Try Zeek and choice the exercise traffic packet)

What changes should I make please?

Looking forward to your reply,
Thank you very very much

looking at the source of check_threshold I see your problem:

function check_threshold(v: vector of count, tracker: TrackCount): bool
    {
    if ( tracker$index <= |v| && tracker$n >= v[tracker$index] )
        {
        ++tracker$index;
        return T;
        }
    return F;
    }

You’re never incrementing count_threshold$n, so that will never do anything.

You can sort of get things to work by doing

export{
        redef enum Notice::Type += { IP_WIRED };
        
        global detection_range: set[subnet] = set( 192.168.1.0/16 );
        global count_threshold: GLOBAL::TrackCount;
		global notice_thresholds: vector of count = {1, 10, 100000};

        }
        
event connection_state_remove(c:connection)
        {
        if ( c$id$orig_h !in detection_range)
        	return;
        	
        ++count_threshold$n;
        if (check_threshold(notice_thresholds, count_threshold))
        	{
        	print fmt("yes %s is in %s.", c$id$orig_h, detection_range);
        	}
        }

It looks like that function has a bit of a big where if the last threshold crosses it tries to access an index that does not exist. That method isn’t used anywhere so I’m not surprised it has a bug…

Maybe you want something like this instead

export{
        redef enum Notice::Type += { IP_WIRED };
        
        global detection_range: set[subnet] = set( 192.168.1.0/16 );
        global count_threshold: table[addr] of count &default=0 &create_expire=1day;
        }
        
event connection_state_remove(c:connection)
        {
        if ( c$id$orig_h !in detection_range)
        	return;
        	
        local cnt = ++count_threshold[c$id$orig_h];
        if (cnt == 1 || cnt == 10)
        	{
        	print fmt("yes %s is in %s.", c$id$orig_h, cnt);
        	}
        }

Thank you very much again Justin, It’s a very good idea.
Because my source code have more than a dozen notification types, so I would like to ask if you can recommend me a more concise way to directly add a threshold (I prefer your method than option notice_threshold) for all notices (or notices of all scripts) under a script?

For exemple, I have 4 this kind of block:

        # For all the trafic Inbound  in detection range
        if ( c$id$resp_h in detection_range && c$id$resp_h ! in ip_fix && id_matches_direction(c$id, INBOUND))
            {

            if ( c$id$resp_h ! in ip_attributed && c$id$resp_h ! in ip_gateway)
                    {
                    notice_info$msg = "Trafic INBOUND: Destination's IP not attributed by DHCP";
                    notice_info$sub = fmt("Unknow ip is %s", c$id$resp_h);
                    NOTICE(notice_info);
                    }
            else if ( c$id$resp_h in ip_attributed && c$conn$resp_l2_addr != ip_attributed[c$id$resp_h]$Mac_addr )
                    { 
                    notice_info$msg = "Trafic OUTBOUND: IP addr reuse";
                    notice_info$sub = fmt("IP %s (%s dhcp record) is reused by %s", c$id$resp_h, ip_attributed[c$id$resp_h]$Mac_addr, c$conn$resp_l2_addr);
                    NOTICE(notice_info);
                    }
            else if ( c$id$resp_h in ip_attributed && c$conn$ts > ip_attributed[c$id$resp_h]$End_time )
                    {
                    notice_info$msg = "Trafic OUTBOUND: Destination's IP is expired";
                    notice_info$sub = fmt("Expired ip is %s", c$id$resp_h);
                    NOTICE(notice_info);
                    }
            }

Thanks a lot :blush: