diff -uNr HEAD/src/detection-plugins/Makefile.am HEAD-kees/src/detection-plugins/Makefile.am
--- HEAD/src/detection-plugins/Makefile.am	2005-03-18 11:48:15.000000000 -0800
+++ HEAD-kees/src/detection-plugins/Makefile.am	2006-07-23 16:37:26.000000000 -0700
@@ -10,6 +10,7 @@
 sp_ip_same_check.c sp_ip_same_check.h sp_ip_tos_check.c sp_ip_tos_check.h      \
 sp_ipoption_check.c sp_ipoption_check.h sp_pattern_match.c sp_pattern_match.h  \
 sp_react.c sp_react.h \
+sp_age_check.c sp_age_check.h \
 sp_respond.c sp_respond.h sp_rpc_check.c sp_rpc_check.h         \
 sp_session.c sp_session.h sp_tcp_ack_check.c sp_tcp_ack_check.h                \
 sp_tcp_flag_check.h sp_tcp_flag_check.c sp_tcp_seq_check.c sp_tcp_seq_check.h  \
diff -uNr HEAD/src/detection-plugins/sp_age_check.c HEAD-kees/src/detection-plugins/sp_age_check.c
--- HEAD/src/detection-plugins/sp_age_check.c	1969-12-31 16:00:00.000000000 -0800
+++ HEAD-kees/src/detection-plugins/sp_age_check.c	2006-07-24 22:18:18.000000000 -0700
@@ -0,0 +1,413 @@
+/* $Id:$ */
+
+/* sp_age_check
+ *
+ * Purpose:
+ *
+ *  This plugin allows TCP session ages to be tested.
+ *
+ * Arguments:
+ *   
+ *  The "age" argument can test session age, measured in seconds:
+ *      age:>N      session is more than N seconds old
+ *      age:<N      session is less than N seconds old
+ *      age:=N      session is exactly N seconds old
+ *      age:N-M     session is between N and M seconds old
+ *
+ * Example:
+ * 
+ *  drop tcp any any <> any any (msg: "over 60 sec"; age:>60; resp:rst_all;)
+ * 
+ */
+
+/*
+** Copyright (C) 2005-2006 Kees Cook <kees@outflux.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "rules.h"
+#include "decode.h"
+#include "debug.h"
+#include "plugbase.h"
+#include "parser.h"
+#include "plugin_enum.h"
+#include "util.h"
+#include "sp_age_check.h"
+
+
+typedef struct _AgeCheckData
+{
+    int age;
+    int h_age;
+
+} AgeCheckData;
+
+void AgeCheckInit(char *, OptTreeNode *, int);
+void ParseAge(char *, OptTreeNode *);
+int CheckAgeEq(Packet *, struct _OptTreeNode *, OptFpList *);
+int CheckAgeGT(Packet *, struct _OptTreeNode *, OptFpList *);
+int CheckAgeLT(Packet *, struct _OptTreeNode *, OptFpList *);
+int CheckAgeRG(Packet *, struct _OptTreeNode *, OptFpList *);
+
+
+
+/****************************************************************************
+ * 
+ * Function: SetupAgeCheck()
+ *
+ * Purpose: Register the age option keyword with its setup function
+ *
+ * Arguments: None.
+ *
+ * Returns: void function
+ *
+ ****************************************************************************/
+void SetupAgeCheck(void)
+{
+    /* map the keyword to an initialization/processing function */
+    RegisterPlugin("age", AgeCheckInit);
+
+    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: AgeCheck Initialized\n"););
+}
+
+
+/****************************************************************************
+ * 
+ * Function: AgeCheckInit(char *, OptTreeNode *)
+ *
+ * Purpose: Parse the age keyword arguments and link the detection module
+ *          into the function list
+ *
+ * Arguments: data => rule arguments/data
+ *            otn => pointer to the current rule option list node
+ *
+ * Returns: void function
+ *
+ ****************************************************************************/
+void AgeCheckInit(char *data, OptTreeNode *otn, int protocol)
+{
+    /* multiple declaration check */ 
+    if(otn->ds_list[PLUGIN_TTL_CHECK])
+    {
+        FatalError("%s(%d): Multiple IP age options in rule\n", file_name,
+                file_line);
+    }
+
+    /* allocate the data structure and attach it to the
+       rule's data struct list */
+    otn->ds_list[PLUGIN_TTL_CHECK] = (AgeCheckData *)
+            SnortAlloc(sizeof(AgeCheckData));
+
+    /* this is where the keyword arguments are processed and placed into the 
+       rule option's data structure */
+    ParseAge(data, otn);
+
+    /* NOTE: the AddOptFuncToList call is moved to the parsing function since
+       the linking is best determined within that function */
+}
+
+
+
+/****************************************************************************
+ * 
+ * Function: ParseAge(char *, OptTreeNode *)
+ *
+ * Purpose: Parse the age keyword's arguments
+ *
+ * Arguments: data => argument data
+ *            otn => pointer to the current rule's OTN
+ *
+ * Returns: void function
+ *
+ ****************************************************************************/
+void ParseAge(char *data, OptTreeNode *otn)
+{
+    AgeCheckData *ds_ptr;  /* data struct pointer */
+    char agerel;
+
+    /* set the ds pointer to make it easier to reference the option's
+       particular data struct */
+    ds_ptr = (AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK];
+
+    while(isspace((int)*data)) data++;
+
+    agerel = *data;
+
+    switch (agerel) {
+        case '-':
+            ds_ptr->h_age = -1; /* leading dash flag */
+        case '>':
+        case '<':
+        case '=':
+            data++;
+            break;
+       default:     
+            agerel = '=';
+    }
+    while(isspace((int)*data)) data++;
+
+    ds_ptr->age = atoi(data);
+
+    /* skip digit */
+    while(isdigit((int)*data)) data++;
+    /* and spaces.. if any */ 
+    while(isspace((int)*data)) data++;
+    if (*data == '-')
+    {
+        data++;
+        agerel = '-';
+    }
+    switch (agerel) {
+        case '>':
+            AddOptFuncToList(CheckAgeGT, otn);
+            break;
+        case '<':     
+            AddOptFuncToList(CheckAgeLT, otn);
+            break;
+        case '=':
+            AddOptFuncToList(CheckAgeEq, otn);
+            break;
+        case '-':
+            while(isspace((int)*data)) data++;
+            if (ds_ptr->h_age != -1 && atoi(data) == 0)
+            {
+                ds_ptr->h_age = 255;
+            }
+            else
+            {
+                ds_ptr->h_age = atoi(data);
+            }
+            /* sanity check.. */
+            if (ds_ptr->h_age < ds_ptr->age) 
+            {
+                ds_ptr->h_age = ds_ptr->age;
+                ds_ptr->age   = atoi(data);
+            }
+            AddOptFuncToList(CheckAgeRG, otn);
+            break;
+        default:
+            /* wtf? */
+            /* we need at least one statement after "default" or else Visual C++ issues a warning */
+            break;
+    }
+             
+
+    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Set age check value to %c%d (%d)\n",
+                            agerel, ds_ptr->age, ds_ptr->h_age););
+
+}
+
+
+/****************************************************************************
+ * 
+ * Function: CheckAgeEq(char *, OptTreeNode *)
+ *
+ * Purpose: Test if the packet age equals the rule option's age
+ *
+ * Arguments: data => argument data
+ *            otn => pointer to the current rule's OTN
+ *
+ * Returns:  0 on failure, return value of next list function on success
+ *
+ ****************************************************************************/
+int CheckAgeEq(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
+{
+    Session * session = NULL;
+    u_int32_t age;
+
+    if ((session=p->ssnptr)==NULL) {
+#ifdef DEBUG
+        DebugMessage(DEBUG_PLUGIN, "CheckAgeEq: no ssnptr!\n");
+#endif
+        return 0;
+    }
+
+    age = session->last_session_time - session->start_time;
+
+    if (((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->age == age)
+    {
+        /* call the next function in the function list recursively */
+        return fp_list->next->OptTestFunc(p, otn, fp_list->next);
+    }
+#ifdef DEBUG
+    else
+    {
+        /* you can put debug comments here or not */
+        DebugMessage(DEBUG_PLUGIN, "CheckAgeEq: Not equal to %d\n",
+            ((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->age);
+    }
+#endif
+
+    /* if the test isn't successful, return 0 */
+    return 0;
+}
+
+
+
+/****************************************************************************
+ * 
+ * Function: CheckAgeGT(char *, OptTreeNode *)
+ *
+ * Purpose: Test the packet's payload size against the rule payload size 
+ *          value.  This test determines if the packet payload size is 
+ *          greater than the rule age.
+ *
+ * Arguments: data => argument data
+ *            otn => pointer to the current rule's OTN
+ *
+ * Returns:  0 on failure, return value of next list function on success
+ *
+ ****************************************************************************/
+int CheckAgeGT(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
+{
+    Session * session = NULL;
+    u_int32_t age;
+
+    if ((session=p->ssnptr)==NULL) {
+#ifdef DEBUG
+        DebugMessage(DEBUG_PLUGIN, "CheckAgeGT: no ssnptr!\n");
+#endif
+        return 0;
+    }
+
+    age = session->last_session_time - session->start_time;
+
+    if (((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->age < age)
+    {
+        /* call the next function in the function list recursively */
+        return fp_list->next->OptTestFunc(p, otn, fp_list->next);
+    }
+#ifdef DEBUG
+    else
+    {
+        /* you can put debug comments here or not */
+        DebugMessage(DEBUG_PLUGIN, "CheckAgeGt: Not greater than %d\n",
+            ((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->age);
+    }
+#endif
+
+    /* if the test isn't successful, return 0 */
+    return 0;
+}
+
+
+
+
+/****************************************************************************
+ * 
+ * Function: CheckAgeLT(char *, OptTreeNode *)
+ *
+ * Purpose: Test the packet's payload size against the rule payload size 
+ *          value.  This test determines if the packet payload size is 
+ *          less than the rule age.
+ *
+ * Arguments: data => argument data
+ *            otn => pointer to the current rule's OTN
+ *
+ * Returns:  0 on failure, return value of next list function on success
+ *
+ ****************************************************************************/
+int CheckAgeLT(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
+{
+    Session * session = NULL;
+    u_int32_t age;
+
+    if ((session=p->ssnptr)==NULL) {
+#ifdef DEBUG
+        DebugMessage(DEBUG_PLUGIN, "CheckAgeLT: no ssnptr!\n");
+#endif
+        return 0;
+    }
+
+    age = session->last_session_time - session->start_time;
+
+    if (((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->age > age)
+    {
+        /* call the next function in the function list recursively */
+        return fp_list->next->OptTestFunc(p, otn, fp_list->next);
+    }
+#ifdef DEBUG
+    else
+    {
+        /* you can put debug comments here or not */
+        DebugMessage(DEBUG_PLUGIN, "CheckAgeLT: Not Less than %d\n",
+            ((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->age);
+    }
+#endif
+
+    /* if the test isn't successful, return 0 */
+    return 0;
+}
+
+
+
+
+
+/****************************************************************************
+ * 
+ * Function: CheckAgeRG(char *, OptTreeNode *)
+ *
+ * Purpose: Test the packet's payload size against the rule payload size 
+ *          value.  This test determines if the packet payload size is 
+ *          within the rule age.
+ *
+ * Arguments: data => argument data
+ *            otn => pointer to the current rule's OTN
+ *
+ * Returns:  0 on failure, return value of next list function on success
+ *
+ ****************************************************************************/
+int CheckAgeRG(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
+{
+    Session * session;
+    u_int32_t age;
+
+    if ((session=p->ssnptr)==NULL) {
+#ifdef DEBUG
+        DebugMessage(DEBUG_PLUGIN, "CheckAgeRG: no ssnptr!\n");
+#endif
+        return 0;
+    }
+
+    age = session->last_session_time - session->start_time;
+
+    if (((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->age   <= age &&
+        ((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->h_age >= age)
+    {
+        /* call the next function in the function list recursively */
+        return fp_list->next->OptTestFunc(p, otn, fp_list->next);
+    }
+#ifdef DEBUG
+    else
+    {
+        /* you can put debug comments here or not */
+        DebugMessage(DEBUG_PLUGIN, "CheckAgeRG: Not Within the range %d - %d (%d)\n", 
+            ((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->age,
+            ((AgeCheckData *)otn->ds_list[PLUGIN_TTL_CHECK])->h_age,
+            p->iph->ip_age);
+    }
+#endif
+
+    /* if the test isn't successful, return 0 */
+    return 0;
+}
diff -uNr HEAD/src/detection-plugins/sp_age_check.h HEAD-kees/src/detection-plugins/sp_age_check.h
--- HEAD/src/detection-plugins/sp_age_check.h	1969-12-31 16:00:00.000000000 -0800
+++ HEAD-kees/src/detection-plugins/sp_age_check.h	2006-07-23 16:37:26.000000000 -0700
@@ -0,0 +1,25 @@
+/*
+** Copyright (C) 2005 Kees Cook <kees@outflux.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* $Id: sp_age_check.h,v 1.8 2003/10/20 15:03:33 chrisgreen Exp $ */
+#ifndef __SP_AGE_CHECK_H__
+#define __SP_AGE_CHECK_H__
+
+void SetupAgeCheck(void);
+
+#endif  /* __SP_AGE_CHECK_H__ */
diff -uNr HEAD/src/plugbase.c HEAD-kees/src/plugbase.c
--- HEAD/src/plugbase.c	2005-08-23 08:52:22.000000000 -0700
+++ HEAD-kees/src/plugbase.c	2006-07-23 16:45:18.000000000 -0700
@@ -102,6 +102,7 @@
 #include "detection-plugins/sp_react.h"
 #endif
 #include "detection-plugins/sp_ftpbounce.h"
+#include "detection-plugins/sp_age_check.h"
 
 
 /* built-in output plugins */
@@ -180,6 +181,7 @@
     SetupReact();
 #endif
     SetupFTPBounce();
+    SetupAgeCheck();
 }
 
 /****************************************************************************
diff -uNr HEAD/src/plugin_enum.h HEAD-kees/src/plugin_enum.h
--- HEAD/src/plugin_enum.h	2003-10-20 08:03:22.000000000 -0700
+++ HEAD-kees/src/plugin_enum.h	2006-07-23 16:37:26.000000000 -0700
@@ -34,4 +34,5 @@
     PLUGIN_TTL_CHECK,
     PLUGIN_BYTE_TEST,
     PLUGIN_PCRE,
+    PLUGIN_AGE_CHECK,
 };
