;; load a clips formatted logfile
(load* "{$home}/log.clp")

;; rules for finding log message that satisfies criteria for
;; severity and module 
(deftemplate find "find command"
    (slot datebegin
        (type INTEGER))
    (slot dateend
        (type INTEGER))
    (slot severity
        (type SYMBOL)
        (allowed-symbols notice warn error any)))

(deftemplate suspect "suspects"
    (slot count
        (type INTEGER)
        (default 0))
    (slot line
        (type INTEGER))
    (slot time
        (type INTEGER))
    (slot module
        (type STRING))
    (slot message
        (type STRING)))

;;(module "matching module name string")
;;(except "excepting module name string")
;;(mode attack/filter)
;;(count number-of-lines)
;;(range range-in-seconds)

;;--------- rules for filter ----------
;;
(defrule find-all-module
    (mode filter)
    (or (not (exists (module ?)))
        (module ?mod))
    (find (severity ?sev&~any)(datebegin ?b)(dateend ?e))
    (log (severity ?sev)(day ?t&:(and (>= ?t ?b) (<= ?t ?e)))(line ?line)
        (date $?date)(module ?mod)(message ?mes))
    (not (exists (except ?mod)))
=>
    (printout t ?line " " $?date " [" ?sev "] [" ?mod "] " ?mes crlf))

(defrule find-any-severity-all-module
    (mode filter)
    (or (not (exists (module ?)))
        (module ?mod))
    (find (severity any)(datebegin ?b)(dateend ?e))
    (log (day ?t&:(and (>= ?t ?b) (<= ?t ?e)))(line ?line)(severity ?sev)
        (date $?date)(module ?mod)(message ?mes))
    (not (exists (except ?mod)))
=>
    (printout t ?line " " $?date " [" ?sev "] [" ?mod "] " ?mes crlf))

;;---------- rules for dos attack ---------------
;;
(defrule find-suspected-line
    (mode attack)
    (or (not (exists (module ?))) ;; no module specified
        (module ?mod))
    (find (datebegin ?b)(dateend ?e))
    (log (line ?line)(day ?day&:(and (>= ?day ?b) (<= ?day ?e)))(time ?time)
        (module ?mod)(message ?mes))
    (not (exists (except ?mod)))
    (not (exists (counter ? ?mod ?mes)))
    (count ?count)
    (range ?r)
    (log (line ?l&:(>= ?l (+ ?line ?count)))(day ?day&:(and (>= ?day ?b) (<= ?day ?e)))
        (time ?t&:(<= ?t (+ ?time ?r)))(module ?mod)(message ?mes))
=>
    (assert (counter 0 ?mod ?mes)))

(defrule collect-suspects
    (mode attack)
    (counter ? ?mod ?mes)
    (find (datebegin ?b)(dateend ?e))
    (log (line ?line)(day ?day&:(and (>= ?day ?b) (<= ?day ?e)))(time ?time)
        (module ?mod)(message ?mes))
    (not (exists (suspect (line ?line))))
=>
    (assert (suspect (line ?line)(time ?time)(module ?mod)(message ?mes))))

(defrule change-mode
    (declare (salience -100))
     ?m <- (mode attack)
=>
    (retract ?m)
    (assert (mode check)))

(defrule count-suspects
    (mode check)
    ?sus <- (suspect (count 0)(line ?line)(module ?mod)(message ?mes))
    (not (exists (suspect (count 0)(line ?l&:(< ?l ?line))(module ?mod)
        (message ?mes))))
    ?cnt <- (counter ?c ?mod ?mes)
=>
    (modify ?sus (count (+ 1 ?c)))
    (retract ?cnt)
    (assert (counter (+ 1 ?c) ?mod ?mes)))

(defrule check-for-condition
    (mode check)
    ?ct <- (counter ?cc ?mod ?mes)
    (count ?count)
    (range ?r)
    (suspect (module ?mode)(message ?mes)(count ?cnt)(time ?time)(line ?line))
    (suspect (count ?c&:(>= (- ?c ?cnt 1) ?count))(time ?t&:(<= ?t (+ ?time ?r)))
        (module ?mode)(message ?mes))
    (log (line ?line)(date $?date)(severity ?sev))
=>
    (retract ?ct)
    (printout t "message count: " ?cc ", line=")
    (printout t ?line " " $?date " [" ?sev "] [" ?mod "] " ?mes  crlf))