perl - How do I print a computed score for all input in a file? -


here perl code takes 2 files input. files contain tcp packets. trains normal packets using packets in first file , prints anomalous packets in second file.

while (<>) {     if (($time, $to, $port, $from, $duration, $flags, $length, $text) = /(.{19}) (.{15}):(\d+) (.{15}):\d+ \+(\d+) (\s+) (\d+) (.*)/) {         $text =~ s/\^m//g;         $text =~ s/\^ /\n/g;         if (($port == 25 || $port == 80) && $text =~ /\n\n/) {$text = "$`\n";}         $text =~ s/^\^@//;         if ($time =~ /(\d\d)\/(\d\d)\/\d\d\d\d (\d\d):(\d\d):(\d\d)/) {             $now = ((($1 * 31 + $2) * 24 + $3) * 60 + $4) * 60 + $5;         }         foreach ($text =~ /.*\n/g) {             if (($k, $v) = /(\s*)(.*)/) {                 $k = substr($k, 0, 30);                 $v = substr($v, 0, 100);                 $score   = 0;                 $comment = "";                 &alarm($port,       $k);                 &alarm($to,         $flags);                 &alarm("to",        "$to:$port");                 &alarm($to,         $from);                 &alarm("$to:$port", $from);                 if ($score > 30000) {                     $score = log($score) / (10 * log(10));                     printf("    #   0 $time $to %8.6f \#%s\n", $score, substr($comment, 0, 300));                 }             }         }     } }  sub alarm {     local ($key, $val, $sc) = @_;     if ($now < 10300000) {         ++$n{$key};         if (++$v{$key . $val} == 1) {             ++$r{$key};             $t{$key} = $now;         }     } elsif ($n{$key} > 0 && !$v{$key . $val}) {         $score += ($now - $t{$key}) * $n{$key} / $r{$key};         $comment .= " $key=$val";         $t{$key} = $now;     } }  exit; 

i new perl , small part project needs anomaly score printed packets in second file. can tell how modify code?

from can see here, looks if code (as now) looks packets before cutoff time, , stores whether or not has seen conditions in %n , %v hashes.

why not give flag alarm function called $training. if true, account packet values, otherwise, calculate score anomaly (if one), , return value. if there no anomaly, or if you're in training mode, return zero:

    sub alarm {          ($key, $val, $training) = @_;          $score = 0;          if ( $training ) {              ...do accounting...          } else {              ...do comparisons & set score accordingly...          }          return $score;      } 

throw big while subroutine, , have subroutine take filename , whether in training mode or not.

     sub examine {          ($file, $training) = @_;          if ( open $fh, '<', $file ) {              while (<$fh>) {                  ...this big while loop...                  ...pass $training along alarm() calls...              }          } else {              die "failed open $file: $!\n';          }      } 

your main program now:

     use constant training => 1;       examine('file1',  training);      examine('file2', !training); 

more notes:

  • use my() instead of local, though doesn't materially affect program, it's habit into.
  • don't use known function name alarm when isn't doing of kind, instead name check_packet_values -- or makes sense , team.
  • stop using magic numbers

    use constant {     cutoff_time   => 10300000,     anomaly_score =>    30000 }; 
  • use real date/time parser values have meaning. str2time date::parse give time in epoch seconds (seconds since jan 1, 1970).

  • use variable names mean something. %n , %v hard understand in code, %n_seen , %value_seen (as %first_seen_time instead of %t). remember, code doesn't run faster if use shorter variable names.
  • stop using global variables when feasible. counters can global, comment should built in routine initializing , printing comment. so, instead of doing doing, how about:

    $to_score = check_packet_value($to, $flags)     , push @comments, "$to=$flags"; ... $score = $to_score + $from_score + ... if ( !$training && $score > anomaly_threshold ) {     print "blah blah blah @comments\n"; } 
  • also, never, ever use $` -- causes huge performance penalties in entire script (even if never calls function). instead of:

    if ( $text =~ /\n\n/ ) { $text = $` } 

use

    if ( $text =~ /(.*)\n\n/ ) {         $text = $1;     } 

(edit: added warning $`)


Comments

Popular posts from this blog

objective c - Change font of selected text in UITextView -

php - Accessing POST data in Facebook cavas app -

c# - Getting control value when switching a view as part of a multiview -