diff -uprN ./config.c ../Pound-1.10_acl/config.c
--- ./config.c	2006-02-01 12:22:03.000000000 +0100
+++ ../Pound-1.10_acl/config.c	2007-03-13 00:10:21.000000000 +0100
@@ -293,13 +293,13 @@ parse_file(char *fname)
                         SSL_Verifylist, User, Group, RootJail, ExtendedHTTP, WebDAV, LogFacility, LogLevel, Alive,
                         Server, Client, UrlGroup, HeadRequire, HeadDeny, BackEnd, BackEndHA, EndGroup,
                         Err500, Err501, Err503, Err414, CheckURL, CS_SEGMENT, CS_PARM, CS_QID, CS_QVAL, CS_FRAG,
-                        RewriteRedir, NoDaemon;
-    regex_t             *req, *deny;
+                        RewriteRedir, NoDaemon, AllowIP, DenyIP;
+    regex_t             *req, *deny, *allow_ip, *deny_ip;
     regmatch_t          matches[5];
     struct sockaddr_in  addr, alive_addr;
     struct hostent      *host;
     BACKEND             *be;
-    int                 j, k, tot_be, tot_groups, tot_req, tot_deny, in_group, n_http, n_https;
+    int                 j, k, tot_be, tot_groups, tot_req, tot_deny, tot_allowip, tot_denyip, in_group, n_http, n_https;
 
     if(regcomp(&Empty, "^[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
     || regcomp(&Comment, "^[ \t]*#.*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
@@ -339,6 +339,10 @@ parse_file(char *fname)
         REG_ICASE | REG_NEWLINE | REG_EXTENDED)
     || regcomp(&HeadDeny, "^[ \t]*HeadDeny[ \t]+([^ \t]+)[ \t]+\"([^\"]+)\"[ \t]*$",
         REG_ICASE | REG_NEWLINE | REG_EXTENDED)
+    || regcomp(&AllowIP, "^[ \t]*AllowIP[ \t]+\"([^\"]+)\"[ \t]*$",
+        REG_ICASE | REG_NEWLINE | REG_EXTENDED)
+    || regcomp(&DenyIP, "^[ \t]*DenyIP[ \t]+\"([^\"]+)\"[ \t]*$",
+        REG_ICASE | REG_NEWLINE | REG_EXTENDED)
     || regcomp(&EndGroup, "^[ \t]*EndGroup[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
     || regcomp(&Err500, "^[ \t]*Err500[ \t]+\"([^\"]+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
     || regcomp(&Err501, "^[ \t]*Err501[ \t]+\"([^\"]+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
@@ -364,7 +368,7 @@ parse_file(char *fname)
     }
 
     /* first pass - just find number of groups and backends so we can allocate correctly */
-    for(n_http = n_https = tot_be = tot_groups = n_head_off = tot_req = tot_deny = 0; fgets(lin, MAXBUF, fconf); ) {
+    for(n_http = n_https = tot_be = tot_groups = n_head_off = tot_req = tot_deny = tot_allowip = tot_denyip = 0; fgets(lin, MAXBUF, fconf); ) {
         if(!regexec(&ListenHTTP, lin, 4, matches, 0))
             n_http++;
         else if(!regexec(&ListenHTTPS, lin, 4, matches, 0))
@@ -381,6 +385,10 @@ parse_file(char *fname)
             tot_req++;
         else if(!regexec(&HeadDeny, lin, 4, matches, 0))
             tot_deny++;
+        else if(!regexec(&AllowIP, lin, 4, matches, 0))
+            tot_allowip++;
+        else if(!regexec(&DenyIP, lin, 4, matches, 0))
+            tot_denyip++;
     }
     rewind(fconf);
 
@@ -417,6 +425,23 @@ parse_file(char *fname)
         }
     } else
         deny = NULL;
+
+    if(tot_allowip > 0) {
+        if((allow_ip = (regex_t *)malloc(sizeof(regex_t) * tot_allowip)) == NULL) {
+            logmsg(LOG_ERR, "allow_ip setup: out of memory - aborted");
+            exit(1);
+        }
+    } else
+        allow_ip = NULL;
+
+    if(tot_denyip > 0) {
+        if((deny_ip = (regex_t *)malloc(sizeof(regex_t) * tot_denyip)) == NULL) {
+            logmsg(LOG_ERR, "deny_ip setup: out of memory - aborted");
+            exit(1);
+        }
+    } else
+        deny_ip = NULL;
+
     if(n_head_off > 0 && (head_off = (regex_t *)malloc(sizeof(regex_t) * n_head_off)) == NULL) {
         logmsg(LOG_ERR, "HeadRemove setup: out of memory - aborted");
         exit(1);
@@ -622,7 +647,7 @@ parse_file(char *fname)
             groups[tot_groups]->tot_pri = 0;
             groups[tot_groups]->sess_type = SessNONE;
             groups[tot_groups]->sess_to = 300;
-            tot_req = tot_deny = j = 0;
+            tot_req = tot_deny = tot_allowip = tot_denyip = j = 0;
         } else if(in_group && !regexec(&BackEnd, lin, 4, matches, 0)) {
             memset(&addr, 0, sizeof(addr));
             memset(&alive_addr, 0, sizeof(addr));
@@ -728,6 +753,22 @@ parse_file(char *fname)
                     lin + matches[1].rm_so, lin + matches[2].rm_so);
                 exit(1);
             }
+        } else if(in_group && !regexec(&AllowIP, lin, 4, matches, 0)) {
+            lin[matches[1].rm_eo]  = '\0';
+            snprintf(pat, MAXBUF - 1, "^%s$", lin + matches[1].rm_so);
+            if(regcomp(&allow_ip[tot_allowip++], pat, REG_ICASE | REG_NEWLINE | REG_EXTENDED)) {
+                logmsg(LOG_ERR, "AllowIP: bad pattern \"%s\" - aborted",
+                    lin + matches[1].rm_so);
+                exit(1);
+            }
+        } else if(in_group && !regexec(&DenyIP, lin, 4, matches, 0)) {
+            lin[matches[1].rm_eo]  = '\0';
+            snprintf(pat, MAXBUF - 1, "^%s$", lin + matches[1].rm_so);
+            if(regcomp(&deny_ip[tot_denyip++], pat, REG_ICASE | REG_NEWLINE | REG_EXTENDED)) {
+                logmsg(LOG_ERR, "DenyIP: bad pattern \"%s\" - aborted",
+                    lin + matches[1].rm_so);
+                exit(1);
+            }
         } else if(in_group && !regexec(&EndGroup, lin, 4, matches, 0)) {
             if((groups[tot_groups]->backend_addr = malloc(sizeof(BACKEND) * j)) == NULL) {
                 logmsg(LOG_ERR, "EndGroup out of memory - aborted");
@@ -757,6 +798,26 @@ parse_file(char *fname)
             } else
                 groups[tot_groups]->head_deny = NULL;
 
+            if((groups[tot_groups]->n_allowip = tot_allowip) > 0) {
+                if((groups[tot_groups]->allow_ip = (regex_t *)malloc(sizeof(regex_t) * tot_allowip)) == NULL) {
+                    logmsg(LOG_ERR, "EndGroup allow_ip out of memory - aborted");
+                    exit(1);
+                }
+                while(--tot_allowip >= 0)
+                    groups[tot_groups]->allow_ip[tot_allowip] = allow_ip[tot_allowip];
+            } else
+                groups[tot_groups]->allow_ip = NULL;
+
+            if((groups[tot_groups]->n_denyip = tot_denyip) > 0) {
+                if((groups[tot_groups]->deny_ip = (regex_t *)malloc(sizeof(regex_t) * tot_denyip)) == NULL) {
+                    logmsg(LOG_ERR, "EndGroup deny_ip out of memory - aborted");
+                    exit(1);
+                }
+                while(--tot_denyip >= 0)
+                    groups[tot_groups]->deny_ip[tot_denyip] = deny_ip[tot_denyip];
+            } else
+                groups[tot_groups]->deny_ip = NULL;
+
             tot_groups++;
             in_group = 0;
         } else {
@@ -771,6 +832,10 @@ parse_file(char *fname)
         free(req);
     if(deny)
         free(deny);
+    if(allow_ip)
+        free(allow_ip);
+    if(deny_ip)
+        free(deny_ip);
     regfree(&Empty);
     regfree(&Comment);
     regfree(&ListenHTTP);
@@ -814,6 +879,8 @@ parse_file(char *fname)
     regfree(&HeadRemove);
     regfree(&HeadRequire);
     regfree(&HeadDeny);
+    regfree(&AllowIP);
+    regfree(&DenyIP);
     regfree(&RewriteRedir);
     regfree(&NoDaemon);
     return;
diff -uprN ./http.c ../Pound-1.10_acl/http.c
--- ./http.c	2006-02-01 12:22:03.000000000 +0100
+++ ../Pound-1.10_acl/http.c	2006-04-06 01:48:37.000000000 +0200
@@ -843,14 +843,14 @@ thr_http(void *arg)
             }
         }
         /* check that the requested URL still fits the old back-end */
-        if(be != NULL && grp != get_grp(url, &headers[1])) {
+        if(be != NULL && grp != get_grp(url, &headers[1], from_host)) {
             BIO_reset(be);
             BIO_free_all(be);
             be = NULL;
         }
         while(be == NULL) {
             /* find the session - if any */
-            if((srv = get_be(grp = get_grp(url, &headers[1]), from_host, url, &headers[1])) == NULL) {
+            if((srv = get_be(grp = get_grp(url, &headers[1], from_host), from_host, url, &headers[1])) == NULL) {
 				logmsg(LOG_WARNING, "no backend \"%s\" from %s", request, inet_ntoa(from_host));
                 err_reply(cl, h503, e503);
                 free_headers(headers);
diff -uprN ./pound.8 ../Pound-1.10_acl/pound.8
--- ./pound.8	2006-02-01 12:22:03.000000000 +0100
+++ ../Pound-1.10_acl/pound.8	2007-03-13 00:56:33.000000000 +0100
@@ -345,6 +345,29 @@ directive. The headers will be checked a
 pattern. As many
 .I HeadDeny
 directives as necessary may appear in a single group.
+.TP
+\fBAllowIP\fR "pattern"
+If one or more instances of this directive is specified in a
+.I UrlGroup
+then the dotted quad representation of the client IP address must match the
+regular expression "^pattern$" of at least one instance to be processed by this 
+.I UrlGroup.
+You can specify as many
+.I AllowIP
+directives as needed. 
+.TP
+\fBDenyIP\fR "pattern"
+This works just as 
+.I AllowIP
+except that IP addresses matching this pattern will not be processed by this
+.I UrlGroup.
+If a clients IP address matches a
+.I DenyIP
+statement the request will not be processed by this
+.I UrlGroup
+even if it matches an
+.I AllowIP
+statement.
 .PP
 See below for some examples.
 .SH HIGH-AVAILABILITY
diff -uprN ./pound.h ../Pound-1.10_acl/pound.h
--- ./pound.h	2006-02-01 12:22:03.000000000 +0100
+++ ../Pound-1.10_acl/pound.h	2007-03-13 00:15:08.000000000 +0100
@@ -317,6 +317,10 @@ typedef struct _group {
     int             n_req;              /* how many of them */
     regex_t         *head_deny;         /* patterns to match the headers against - disallowed */
     int             n_deny;             /* how many of them */
+    regex_t         *allow_ip;          /* allow patterns to match the IP's against */
+    int             n_allowip;          /* how many of them */
+    regex_t         *deny_ip;           /* deny patterns to match the IP's against */
+    int             n_denyip;           /* how many of them */
     BACKEND         *backend_addr;      /* array of backend servers */
     int             tot_pri;            /* total number of backend servers */
     SESS_TYPE       sess_type;          /* session type: IP, URL or COOKIE */
@@ -391,7 +395,7 @@ extern int  check_header(char *, char *)
 /*
  * Find the required group for a given URL
  */
-extern GROUP *get_grp(char *, char **);
+extern GROUP *get_grp(char *, char **, struct in_addr);
 
 /*
  * Find the host to connect to
diff -uprN ./svc.c ../Pound-1.10_acl/svc.c
--- ./svc.c	2006-02-01 12:22:03.000000000 +0100
+++ ../Pound-1.10_acl/svc.c	2007-03-13 00:04:08.000000000 +0100
@@ -462,9 +462,14 @@ sess_balance(SESS *root)
  * Find the required group for a given URL and header set
  */
 GROUP *
-get_grp(char *url, char **headers)
+get_grp(char *url, char **headers, struct in_addr from_host)
 {
     int n, i, j, found;
+    char _ip[INET_ADDRSTRLEN+1];
+    if(inet_ntop(AF_INET, &from_host, _ip, INET_ADDRSTRLEN) == NULL) {
+      logmsg(LOG_WARNING, "Failed to convert IP address");
+    }
+    _ip[INET_ADDRSTRLEN] = '\0';
 
     for(n = 0; groups[n] != NULL; n++) {
         /* URL */
@@ -484,6 +489,25 @@ get_grp(char *url, char **headers)
                 found = 1;
         if(found)
             continue;
+
+        /* AllowIP addresses */
+        if(groups[n]->n_allowip > 0) {
+          for(found = 0, i = 0; !found && i < groups[n]->n_allowip; i++)
+            if(!regexec(&groups[n]->allow_ip[i], _ip, 0, NULL, 0))
+              found = 1;
+          if(!found)
+            continue;
+        }
+
+        /* DenyIP addresses */
+        if(groups[n]->n_denyip > 0) {
+          for(found = 0, i = 0; !found && i < groups[n]->n_denyip; i++)
+            if(!regexec(&groups[n]->deny_ip[i], _ip, 0, NULL, 0))
+              found = 1;
+          if(found)
+            continue;
+        }
+
         break;
     }
     return groups[n];
