httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jor...@apache.org
Subject svn commit: r1816609 - in /httpd/httpd/trunk: CHANGES server/listen.c server/vhost.c
Date Wed, 29 Nov 2017 09:07:48 GMT
Author: jorton
Date: Wed Nov 29 09:07:48 2017
New Revision: 1816609

URL: http://svn.apache.org/viewvc?rev=1816609&view=rev
Log:
Support IPv6 link-local scope IDs in Listen and VirtualHost, if built
with APR 1.7 or later:

* server/listen.c (match_address): New function, factored out from
  find_listeners.
  (find_listeners): Use it; add scope and temp pool arguments.
  (alloc_listener): Take scope_id and pool arguments and pass through;
  set zone for addresses if present.
  (ap_set_listener): Pass through temp pool and scope id.
  
* server/vhost.c (get_addresses): Set zone for vhost address if
  present.

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/server/listen.c
    httpd/httpd/trunk/server/vhost.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1816609&r1=1816608&r2=1816609&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Wed Nov 29 09:07:48 2017
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.1
 
+  *) core: Support zone/scope in IPv6 link-local addresses in Listen and
+     VirtualHost directives (requires APR 1.7.x or later).  [Joe Orton]
+
   *) mod_md: v1.0.5, restricting post_config dry run to be more silent and performing
      only necessary work for mod_ssl to be also happy with the configuration.
      [Stefan Eissing] 

Modified: httpd/httpd/trunk/server/listen.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/listen.c?rev=1816609&r1=1816608&r2=1816609&view=diff
==============================================================================
--- httpd/httpd/trunk/server/listen.c (original)
+++ httpd/httpd/trunk/server/listen.c Wed Nov 29 09:07:48 2017
@@ -19,6 +19,7 @@
 
 #define APR_WANT_STRFUNC
 #include "apr_want.h"
+#include "apr_version.h"
 
 #include "ap_config.h"
 #include "httpd.h"
@@ -404,8 +405,32 @@ static const char *set_systemd_listener(
 
 #endif /* HAVE_SYSTEMD */
 
+/* Returns non-zero if socket address SA matches hostname, port and
+ * scope_id.  p is used for temporary allocations. */
+static int match_address(const apr_sockaddr_t *sa,
+                         const char *hostname, apr_port_t port,
+                         const char *scope_id, apr_pool_t *p)
+{
+    const char *old_scope = NULL;
+
+#if APR_VERSION_AT_LEAST(1,7,0)
+    /* To be clever here we could correctly match numeric and
+     * non-numeric zone ids.  Ignore failure, old_scope will be left
+     * as NULL. */
+    (void) apr_sockaddr_zone_get(sa, &old_scope, NULL, p);
+#endif
+    
+    return port == sa->port
+        && ((!hostname && !sa->hostname)
+            || (hostname && sa->hostname && !strcmp(sa->hostname, hostname)))
+        && ((!scope_id && !old_scope)
+            || (scope_id && old_scope && !strcmp(scope_id, old_scope)));
           
+}
+
+/* ### This logic doesn't cope with DNS changes across a restart. */
 static int find_listeners(ap_listen_rec **from, ap_listen_rec **to,
-                          const char *addr, apr_port_t port)
+                          const char *addr, apr_port_t port,
+                          const char *scope_id, apr_pool_t *temp_pool)
 {
     int found = 0;
 
@@ -415,15 +440,10 @@ static int find_listeners(ap_listen_rec
         /* Some listeners are not real so they will not have a bind_addr. */
         if (sa) {
             ap_listen_rec *new;
-            apr_port_t oldport;
 
-            oldport = sa->port;
-            /* If both ports are equivalent, then if their names are equivalent,
-             * then we will re-use the existing record.
-             */
-            if (port == oldport &&
-                ((!addr && !sa->hostname) ||
-                 ((addr && sa->hostname) && !strcmp(sa->hostname, addr))))
{
+            /* Re-use the existing record if it matches completely
+             * against an existing listener. */
+            if (match_address(sa, addr, port, scope_id, temp_pool)) {
                 found = 1;
                 if (!to) {
                     break;
@@ -444,19 +464,21 @@ static int find_listeners(ap_listen_rec
 
 static const char *alloc_listener(process_rec *process, const char *addr,
                                   apr_port_t port, const char* proto,
-                                  void *slave)
+                                  const char *scope_id, void *slave,
+                                  apr_pool_t *temp_pool)
 {
     ap_listen_rec *last;
     apr_status_t status;
     apr_sockaddr_t *sa;
 
     /* see if we've got a listener for this address:port, which is an error */
-    if (find_listeners(&ap_listeners, NULL, addr, port)) {
+    if (find_listeners(&ap_listeners, NULL, addr, port, scope_id, temp_pool)) {
         return "Cannot define multiple Listeners on the same IP:port";
     }
 
     /* see if we've got an old listener for this address:port */
-    if (find_listeners(&old_listeners, &ap_listeners, addr, port)) {
+    if (find_listeners(&old_listeners, &ap_listeners, addr, port,
+                       scope_id, temp_pool)) {
         if (ap_listeners->slave != slave) {
             return "Cannot define a slave on the same IP:port as a Listener";
         }
@@ -510,6 +532,18 @@ static const char *alloc_listener(proces
             return "Listen setup failed";
         }
 
+#if APR_VERSION_AT_LEAST(1,7,0)
+        if (scope_id) {
+            status = apr_sockaddr_zone_set(new->bind_addr, scope_id);
+            if (status) {
+                ap_log_perror(APLOG_MARK, APLOG_CRIT, status, process->pool, APLOGNO()
+                              "alloc_listener: failed to set scope for %pI to %s",
+                              new->bind_addr, scope_id);
+                return "Listen step failed";
+            }
+        }
+#endif
+
         /* We need to preserve the order returned by getaddrinfo() */
         if (last == NULL) {
             ap_listeners = last = new;
@@ -1000,10 +1034,14 @@ AP_DECLARE_NONSTD(const char *) ap_set_l
         host = NULL;
     }
 
+#if !APR_VERSION_AT_LEAST(1,7,0)
     if (scope_id) {
-        /* XXX scope id support is useful with link-local IPv6 addresses */
-        return "Scope id is not supported";
+        return apr_pstrcat(cmd->pool,
+                           "Scope ID in address '", argv[0],
+                           "' not supported with APR " APR_VERSION_STRING,
+                           NULL);
     }
+#endif
 
     if (!port) {
         return "Port must be specified";
@@ -1027,7 +1065,8 @@ AP_DECLARE_NONSTD(const char *) ap_set_l
     }
 #endif
 
-    return alloc_listener(cmd->server->process, host, port, proto, NULL);
+    return alloc_listener(cmd->server->process, host, port, proto,
+                          scope_id, NULL, cmd->temp_pool);
 }
 
 AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,

Modified: httpd/httpd/trunk/server/vhost.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/vhost.c?rev=1816609&r1=1816608&r2=1816609&view=diff
==============================================================================
--- httpd/httpd/trunk/server/vhost.c (original)
+++ httpd/httpd/trunk/server/vhost.c Wed Nov 29 09:07:48 2017
@@ -23,6 +23,7 @@
 #include "apr.h"
 #include "apr_strings.h"
 #include "apr_lib.h"
+#include "apr_version.h"
 
 #define APR_WANT_STRFUNC
 #include "apr_want.h"
@@ -181,9 +182,14 @@ static const char *get_addresses(apr_poo
     if (!host) {
         return "Missing address for VirtualHost";
     }
+#if !APR_VERSION_AT_LEAST(1,7,0)
     if (scope_id) {
-        return "Scope ids are not supported";
+        return apr_pstrcat(p,
+                           "Scope ID in address '", w,
+                           "' not supported with APR " APR_VERSION_STRING,
+                           NULL);
     }
+#endif
     if (!port && !wild_port) {
         port = default_port;
     }
@@ -202,6 +208,17 @@ static const char *get_addresses(apr_poo
                 "Could not resolve host name %s -- ignoring!", host);
             return NULL;
         }
+#if APR_VERSION_AT_LEAST(1,7,0)
+        if (scope_id) {
+            rv = apr_sockaddr_zone_set(my_addr, scope_id);
+            if (rv) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, APLOGNO()
+                             "Could not set scope ID %s for %pI -- ignoring!",
+                             scope_id, my_addr);
+                return NULL;
+            }
+        }
+#endif
     }
 
     /* Remember all addresses for the host */



Mime
View raw message