Forum Discussion

mbaertl_132813's avatar
mbaertl_132813
Icon for Nimbostratus rankNimbostratus
May 13, 2014

LTM - I-Rule http_process_state_prepend - Invalid action

Hi, we have a new issue since an upgrade from 11.2. to 11.5. One of our I-rules is not working anymore and we only have a hint to an invalid action. Is there any chance to see what syntax is responsible for that issue. is the number 0x109040 giving us any hint?

 

err tmm[14076]: 011f0007:3: http_process_state_prepend - Invalid action:0x109040

 

thanks a lot, Matthias

 

7 Replies

  • Sure, here it is.

    when HTTP_REQUEST {
         log local0.info "[IP::client_addr]:[TCP::client_port]: request triggered - irule_Public"
    
    if {[class match [IP::client_addr] equals authError]}
    {
       log local0.info "[IP::client_addr] from authError sent a request"
       HTTP::collect 1500
    }
    else
    {
       if { not (([HTTP::path] equals "/cwmpWeb/CPEMgt") || ([HTTP::path] starts_with "/BackupRestore/"))  }
       {
          HTTP::respond 404 content {Page Not FoundPage Not Found} "Connection" "close"
       }
       if { [HTTP::header exists Authorization] }
       {
          if { [HTTP::header "User-Agent"] starts_with "Thomson" }
          {
             log local0.info "[IP::client_addr]:[TCP::client_port]: Filter_noserial Authorisation exists"
             HTTP::collect 1500
          }
          else
          {
             if { ([HTTP::header exists "Content-Length"]) && ([HTTP::header "Content-Length"] <= 1000000) && ([HTTP::header "Content-Length"] > 0) }
             { 
                HTTP::collect [HTTP::header Content-Length]
                log local0.info "[IP::client_addr]:[TCP::client_port]:[TCP::remote_port]: Filter_noserial triggered. ContentLength Exists"
             }
          }
       }
       else
       {
          HTTP::respond 401 "WWW-Authenticate" "Basic realm=\"default\"" "Connection" "close"
          log local0.info "[IP::client_addr]:[TCP::client_port]: Filter_noserial Authorisation doese not exists"
       }
    }
    }
    
    when HTTP_REQUEST_DATA {  
       log local0.info "[IP::client_addr]:[TCP::client_port]: Filter_noserial REQUEST_DATA triggered. irule_Public"
    
       if {[class match [IP::client_addr] equals authError]}
       {
          if {([findstr [HTTP::payload] "2 PERIODIC" ] ne "") || ([findstr [HTTP::payload] "6 CONNECTION REQUEST" ] ne "") || ([findstr [HTTP::payload] "1 BOOT" ] ne "") }
          {
             log local0.info "[IP::client_addr] request contains Periodic Inform or normal boot and has to be sent to Bootstrap"
             pool APPL_iwe
          }
          else
          {
             log local0.info "[IP::client_addr] request should get activated but has to wait till the script gets disabled"
             log local0.info "[IP::client_addr] [HTTP::payload]"
             pool Application_public
             HTTP::respond 503 Retry-After: 300
          }
       }
       else
       {
          if { not ([findstr [HTTP::payload] "" ] eq "")  }
          {
             HTTP::respond 204 "Connection" "close"
             log local0.info "[IP::client_addr]->[TCP::local_port] Filter_noserial matched"   
          }  
          if { [findstr [HTTP::payload] "Router" ] ne "" }
          {
             log local0.info "[IP::client_addr]->[TCP::local_port] ROUTER"   
             HTTP::payload replace 0 [HTTP::payload length] [string map -nocase "Router PRGAV4202N" [HTTP::payload]]
          }    
          if { [findstr [HTTP::payload] ">0.0.0.0" ] ne "" }
          {
             log local0.info "[IP::client_addr]->[TCP::local_port] 0.0.0.0"   
             set client_ip [IP::client_addr]
          }
          HTTP::disable
       }
    }
    
  • Hi,

    I could now identify the guilty line and it is following command:

    HTTP::disable

    Any idea why this is now an ivalid action? This changed between version 11.2 and 11.4

    regards,

    Matthias

  • Probably just better error checking. Why do you use HTTP::disable anyway. Also, I don't see a HTTP::release, is that required somewhere? Also, in the second to last if you are using HTTP::payload but then disabling HTTP in all cases, bit odd. It may be better to put the disable command within each test expression body (apart from the one I just mentioned) rather than have it apply to all?

     

  • What is the impact if I do not have this command? Less performance?

     

    i do not think it is there because of performance. it seems he disables http profile when client ip is not in authError data group. HTTP::disable is normally used to turn off http profile for traffic which does not comply with http specification or traffic which is encrypted (no ssl offloading).

     

    HTTP::disable

     

    https://devcentral.f5.com/wiki/iRules.http__disable.ashx

     

  • The condition in which the HTTP::disable command is being called is after 3 if statements, any one of which (or potentially more) could be triggered. If you think of an iRule event and the code within it as sort of a bucket of aggregate values that get "dumped" at the end of the event parsing, then you can sort of see why the "too many redirect invocations" error is reported so frequently here in the forum. For example:

     

    when HTTP_REQUEST {
        set a 1
        if { $a equals 1 } {
            HTTP::redirect "somewhere"
        }
        if { $a < 2 } {
            HTTP::redirect "somewhere else"
        }
        if { $a > 0 } {
            HTTP::redirect "another place"
        }
    }

    I know this isn't highly indicative of your code, but here to draw a point. All three conditions match. The variable a is 1, is less than 2, and is greater than 0. If you thought of this in strict procedural terms, you'd guess that the first condition would get triggered and that would be the end of it. But iRules don't always work that way. In this HTTP event, each relevant condition is going to be parsed, which fills a "bucket" with data to be handled at the end of the event. In this case 3 redirects go into the bucket and that's bad. So back to your code. The HTTP::disable command essentially says, "stop the HTTP filter". In the else clause where it's found, any one (or more) of the 3 conditions before it, each either attempting to perform an HTTP response, or replace payload, is going to conflict with the HTTP::disable command which gets called regardless. Perhaps a more appropriate thing to do would be to make sure only one of the conditions gets triggered:

     

    if { not ( [findstr [HTTP::payload] "" ] eq "" ) } {
        HTTP::respond 204 "Connection" "close"
        log local0.info "[IP::client_addr]->[TCP::local_port] Filter_noserial matched"   
    } elseif { [findstr [HTTP::payload] "Router" ] ne "" } {
        log local0.info "[IP::client_addr]->[TCP::local_port] ROUTER"   
        HTTP::payload replace 0 [HTTP::payload length] [string map -nocase "Router PRGAV4202N" [HTTP::payload]]
    } elseif { [findstr [HTTP::payload] ">0.0.0.0" ] ne "" } {
        log local0.info "[IP::client_addr]->[TCP::local_port] 0.0.0.0"   
        set client_ip [IP::client_addr]
    } else {
        HTTP::disable
    }

    Just a suggestion and not 100% certain what implications that has on your application, but at the very least it solves another potential conflict between the HTTP::respond and HTTP::payload replace commands. As far as whether or not it's needed, I'd say probably not. It's at the end of an else clause at the end of an HTTP_REQUEST_DATA event, which for all intents and purposes is probably already at the end of HTTP parsing.

     

  • Hi Kevin,

    thanks a lot for your proposals and good comments. I have reworked the I-rule completely and I get an error when using elseif. I have version 11.5.1 HF2 and it seem elseif is not supported.

    when HTTP_REQUEST_DATA {  
       log local0.info "$LogString: REQUEST_DATA triggered"
       if {[class match [IP::client_addr] equals authError]}
       {
          log local0.info "$LogString: REQUEST_DATA authError"
          if { [HTTP::payload] contains "6 BOOTSTRAP" }
          {
             log local0.info "$LogString: contains Bootstrap - send 503"
             HTTP::respond 503 
          }
          else
          {
             log local0.info "$LogString: contains other than Bootstrap - send to Bootstrap - pool APPL_iwe"
             pool APPL_iwe
          }
       }
       else
       {
          log local0.info "$LogString: Filter_noserial REQUEST_DATA no_auth_error"
          if { [HTTP::payload] contains "" }
          {
             log local0.info "$LogString: Filter_noserial matched - send 204"   
             HTTP::respond 204 "Connection" "close"
          }  
          if { [HTTP::payload] contains "Router" }
          {
             log local0.info "$LogString: Filter_ROUTER - set Router PRGAV4202N"                
             HTTP::payload replace 0 [HTTP::payload length] [string map -nocase "Router PRGAV4202N" [HTTP::payload]]
          }    
         if { [HTTP::payload] contains ">0.0.0.0" }
         {
            log local0.info "$LogString: Filter_replace 0.0.0.0 with client IP"   
            set client_ip [IP::client_addr]
            HTTP::payload replace 0 [HTTP::payload length] [string map -nocase ">0.0.0.0 >$client_ip" [HTTP::payload]]
          }
          else
          {
            log local0.info "$LogString: REQUEST_DATA else - disable"  
            HTTP::disable
          }
          log local0.info "$LogString: REQUEST_DATA completed"   
       }
    }
    

    If I use elseif I get following error:

    01070151:3: Rule [/Common/public_20140602] error: /Common/public_20140602:100: error: [undefined procedure: elseif][elseif { [HTTP::payload] contains "Router" }
    {
    log local0.info "$LogString: Filter_ROUTER - set Router PRGAV4202N" 
    HTTP::payload replace 0 [HTTP::payload length] [string map -nocase "Router PRGAV4202N" [HTTP::payload]]
    } ]
    

    Any idea why this is an undefined procedure? br, Matthias