*** mod_limitipconn.c.orig	Sun Mar  2 23:06:20 2008
--- mod_limitipconn.c	Thu Feb  4 17:32:21 2010
***************
*** 42,47 ****
--- 42,50 ----
   /* array of MIME types to limit check; all other types are exempt */
      apr_array_header_t *excl_limit;
  
+     apr_array_header_t *local_ip;   /* array of local ip exempt from limit
+     				checking */
+ 
  } limitipconn_config;
  
  static limitipconn_config *create_config(apr_pool_t *p)
***************
*** 53,58 ****
--- 56,62 ----
      cfg->limit = 0;
      cfg->no_limit = apr_array_make(p, 0, sizeof(char *));
      cfg->excl_limit = apr_array_make(p, 0, sizeof(char *));
+     cfg->local_ip = apr_array_make(p, 0, sizeof(char *));
  
      return cfg;
  }
***************
*** 75,80 ****
--- 79,85 ----
      /* convert Apache arrays to normal C arrays */
      char **nolim = (char **) cfg->no_limit->elts;
      char **exlim = (char **) cfg->excl_limit->elts;
+     char **localip = (char **) cfg->local_ip->elts;
  
      const char *address;
  
***************
*** 108,114 ****
  
      /* Only check the MIME-type if we have MIME-type stuff in our config.
         The extra subreq can be quite expensive. */
!     if(cfg->no_limit->nelts > 0 || cfg->excl_limit->nelts > 0) {
          /* Look up the Content-type of this request. We need a subrequest
           * here since this module might be called before the URI has been
           * translated into a MIME type. */
--- 113,119 ----
  
      /* Only check the MIME-type if we have MIME-type stuff in our config.
         The extra subreq can be quite expensive. */
!     if(cfg->no_limit->nelts > 0 || cfg->excl_limit->nelts > 0 || cfg->local_ip->nelts) {
          /* Look up the Content-type of this request. We need a subrequest
           * here since this module might be called before the URI has been
           * translated into a MIME type. */
***************
*** 123,128 ****
--- 128,147 ----
                  "mod_limitipconn: uri: %s  Content-Type: %s", 
                  r->uri, content_type);
  
+      	/* Cycle through the local ip list; if the ip is local,
+      	 * return OK */
+ 
+      	for (i = 0; i < cfg->local_ip->nelts; i++) {
+ 	  ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ 	  	"mod_limitipconn: ip check: \"%s\" ? \"%s\"", address, localip[i]);
+      	  if ((ap_strcasecmp_match(address, localip[i]) == 0)
+      	      || (strncmp(localip[i], address, strlen(localip[i])) == 0)) {
+ 	      ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ 	      	"mod_limitipconn: ip exempt: %s", address);
+      	      return DECLINED;
+      	  }
+      	}
+ 
          /* Cycle through the exempt list; if our content_type is exempt,
           * return OK */
          for (i = 0; i < cfg->no_limit->nelts; i++) {
***************
*** 311,316 ****
--- 330,353 ----
      return NULL;
  }
  
+ /* Parse the LocalIP directive */
+ static const char *local_ip_config_cmd(cmd_parms *parms, void *mconfig,
+ 					 const char *arg)
+ {
+     limitipconn_config *cfg = (limitipconn_config *) mconfig;
+     limitipconn_config *scfg = (limitipconn_config *)
+       ap_get_module_config(parms->server->module_config, &limitipconn_module);
+ 
+     if (parms->path != NULL) {
+       /* Per-directory context */
+       *(char **) apr_array_push(cfg->local_ip) = apr_pstrdup(parms->pool, arg);
+     } else {
+       /* global context */
+       *(char **) apr_array_push(scfg->local_ip) = apr_pstrdup(parms->pool, arg);
+     }
+     return NULL;
+ }
+ 
  /* Array describing structure of configuration directives */
  static command_rec limitipconn_cmds[] = {
      AP_INIT_TAKE1("MaxConnPerIP", limit_config_cmd, NULL, OR_LIMIT|RSRC_CONF,
***************
*** 319,324 ****
--- 356,363 ----
       "MIME types for which limit checking is disabled"),
      AP_INIT_ITERATE("OnlyIPLimit", excl_limit_config_cmd, NULL,
       OR_LIMIT|RSRC_CONF, "restrict limit checking to these MIME types only"),
+      AP_INIT_ITERATE("LocalIP", local_ip_config_cmd, NULL, OR_LIMIT|RSRC_CONF,
+            "no checking on local IP"),
      {NULL},
  };
  
