diff options
author | Marc Balmer <mbalmer@cvs.openbsd.org> | 2008-05-14 08:42:21 +0000 |
---|---|---|
committer | Marc Balmer <mbalmer@cvs.openbsd.org> | 2008-05-14 08:42:21 +0000 |
commit | fe81372a2d30924e3809af4e1a384a13ef38d7e5 (patch) | |
tree | 1d5781d721aef6f516b198db8af0a613af7c3a87 /usr.sbin | |
parent | a3bee37496571c4f1f92cf81531ec9cb069da3db (diff) |
Next chunk of KNF/readability changes.
no binary change.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/httpd/src/main/alloc.c | 2 | ||||
-rw-r--r-- | usr.sbin/httpd/src/main/http_log.c | 832 | ||||
-rw-r--r-- | usr.sbin/httpd/src/main/http_vhost.c | 1702 |
3 files changed, 1282 insertions, 1254 deletions
diff --git a/usr.sbin/httpd/src/main/alloc.c b/usr.sbin/httpd/src/main/alloc.c index d917db267bf..896a470a9f7 100644 --- a/usr.sbin/httpd/src/main/alloc.c +++ b/usr.sbin/httpd/src/main/alloc.c @@ -1,3 +1,5 @@ +/* $OpenBSD: alloc.c,v 1.18 2008/05/14 08:42:20 mbalmer Exp $ */ + /* ==================================================================== * The Apache Software License, Version 1.1 * diff --git a/usr.sbin/httpd/src/main/http_log.c b/usr.sbin/httpd/src/main/http_log.c index 118698ebcc1..8a4a45469a9 100644 --- a/usr.sbin/httpd/src/main/http_log.c +++ b/usr.sbin/httpd/src/main/http_log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: http_log.c,v 1.17 2005/02/09 12:13:09 henning Exp $ */ +/* $OpenBSD: http_log.c,v 1.18 2008/05/14 08:42:20 mbalmer Exp $ */ /* ==================================================================== * The Apache Software License, Version 1.1 @@ -20,8 +20,8 @@ * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * @@ -78,359 +78,356 @@ typedef struct { char *t_name; - int t_val; + int t_val; } TRANS; static const TRANS facilities[] = { - {"auth", LOG_AUTH}, - {"authpriv",LOG_AUTHPRIV}, - {"cron", LOG_CRON}, - {"daemon", LOG_DAEMON}, - {"ftp", LOG_FTP}, - {"kern", LOG_KERN}, - {"lpr", LOG_LPR}, - {"mail", LOG_MAIL}, - {"news", LOG_NEWS}, - {"syslog", LOG_SYSLOG}, - {"user", LOG_USER}, - {"uucp", LOG_UUCP}, - {"local0", LOG_LOCAL0}, - {"local1", LOG_LOCAL1}, - {"local2", LOG_LOCAL2}, - {"local3", LOG_LOCAL3}, - {"local4", LOG_LOCAL4}, - {"local5", LOG_LOCAL5}, - {"local6", LOG_LOCAL6}, - {"local7", LOG_LOCAL7}, - {NULL, -1}, + {"auth", LOG_AUTH}, + {"authpriv", LOG_AUTHPRIV}, + {"cron", LOG_CRON}, + {"daemon", LOG_DAEMON}, + {"ftp", LOG_FTP}, + {"kern", LOG_KERN}, + {"lpr", LOG_LPR}, + {"mail", LOG_MAIL}, + {"news", LOG_NEWS}, + {"syslog", LOG_SYSLOG}, + {"user", LOG_USER}, + {"uucp", LOG_UUCP}, + {"local0", LOG_LOCAL0}, + {"local1", LOG_LOCAL1}, + {"local2", LOG_LOCAL2}, + {"local3", LOG_LOCAL3}, + {"local4", LOG_LOCAL4}, + {"local5", LOG_LOCAL5}, + {"local6", LOG_LOCAL6}, + {"local7", LOG_LOCAL7}, + {NULL, -1}, }; static const TRANS priorities[] = { - {"emerg", APLOG_EMERG}, - {"alert", APLOG_ALERT}, - {"crit", APLOG_CRIT}, - {"error", APLOG_ERR}, - {"warn", APLOG_WARNING}, - {"notice", APLOG_NOTICE}, - {"info", APLOG_INFO}, - {"debug", APLOG_DEBUG}, - {NULL, -1}, + {"emerg", APLOG_EMERG}, + {"alert", APLOG_ALERT}, + {"crit", APLOG_CRIT}, + {"error", APLOG_ERR}, + {"warn", APLOG_WARNING}, + {"notice", APLOG_NOTICE}, + {"info", APLOG_INFO}, + {"debug", APLOG_DEBUG}, + {NULL, -1}, }; -static int error_log_child(void *cmd, child_info *pinfo) +static int +error_log_child(void *cmd, child_info *pinfo) { - /* Child process code for 'ErrorLog "|..."'; - * may want a common framework for this, since I expect it will - * be common for other foo-loggers to want this sort of thing... - */ - int child_pid = 0; - - ap_cleanup_for_exec(); - /* No concept of a child process on Win32 */ - signal(SIGHUP, SIG_IGN); - execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, (char *)NULL); - exit(1); - /* NOT REACHED */ - return(child_pid); + /* Child process code for 'ErrorLog "|..."'; + * may want a common framework for this, since I expect it will + * be common for other foo-loggers to want this sort of thing... + */ + int child_pid = 0; + + ap_cleanup_for_exec(); + /* No concept of a child process on Win32 */ + signal(SIGHUP, SIG_IGN); + execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, (char *)NULL); + exit(1); + /* NOT REACHED */ + return(child_pid); } -static void open_error_log(server_rec *s, pool *p) +static void +open_error_log(server_rec *s, pool *p) { - char *fname; - - if (*s->error_fname == '|') { - FILE *dummy; - if (!ap_spawn_child(p, error_log_child, (void *)(s->error_fname+1), - kill_after_timeout, &dummy, NULL, NULL)) { - perror("ap_spawn_child"); - fprintf(stderr, "Couldn't fork child for ErrorLog process\n"); - exit(1); - } - - s->error_log = dummy; - } - - else if (!strncasecmp(s->error_fname, "syslog", 6)) { - if ((fname = strchr(s->error_fname, ':'))) { - const TRANS *fac; + char *fname; + + if (*s->error_fname == '|') { + FILE *dummy; + if (!ap_spawn_child(p, error_log_child, + (void *)(s->error_fname+1), kill_after_timeout, &dummy, + NULL, NULL)) { + perror("ap_spawn_child"); + fprintf(stderr, "Couldn't fork child for ErrorLog " + "process\n"); + exit(1); + } - fname++; - for (fac = facilities; fac->t_name; fac++) { - if (!strcasecmp(fname, fac->t_name)) { - openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, - fac->t_val); - s->error_log = NULL; - return; + s->error_log = dummy; + } else if (!strncasecmp(s->error_fname, "syslog", 6)) { + if ((fname = strchr(s->error_fname, ':'))) { + const TRANS *fac; + + fname++; + for (fac = facilities; fac->t_name; fac++) { + if (!strcasecmp(fname, fac->t_name)) { + openlog(ap_server_argv0, + LOG_NDELAY|LOG_CONS|LOG_PID, + fac->t_val); + s->error_log = NULL; + return; + } + } + } else + openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, + LOG_LOCAL7); + + s->error_log = NULL; + } else { + fname = ap_server_root_relative(p, s->error_fname); + if (!(s->error_log = ap_pfopen(p, fname, "a"))) { + perror("fopen"); + fprintf(stderr, "%s: could not open error log file " + "%s.\n", ap_server_argv0, fname); + exit(1); } - } - } - else - openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7); - - s->error_log = NULL; - } - else { - fname = ap_server_root_relative(p, s->error_fname); - if (!(s->error_log = ap_pfopen(p, fname, "a"))) { - perror("fopen"); - fprintf(stderr, "%s: could not open error log file %s.\n", - ap_server_argv0, fname); - exit(1); } - } } -API_EXPORT(void) ap_open_logs(server_rec *s_main, pool *p) +API_EXPORT(void) +ap_open_logs(server_rec *s_main, pool *p) { - server_rec *virt, *q; - int replace_stderr; + server_rec *virt, *q; + int replace_stderr; - open_error_log(s_main, p); + open_error_log(s_main, p); - replace_stderr = 1; - if (s_main->error_log) { - /* replace stderr with this new log */ - fflush(stderr); - if (dup2(fileno(s_main->error_log), STDERR_FILENO) == -1) { - ap_log_error(APLOG_MARK, APLOG_CRIT, s_main, - "unable to replace stderr with error_log"); - } else { - replace_stderr = 0; + replace_stderr = 1; + if (s_main->error_log) { + /* replace stderr with this new log */ + fflush(stderr); + if (dup2(fileno(s_main->error_log), STDERR_FILENO) == -1) + ap_log_error(APLOG_MARK, APLOG_CRIT, s_main, + "unable to replace stderr with error_log"); + else + replace_stderr = 0; } - } - /* note that stderr may still need to be replaced with something - * because it points to the old error log, or back to the tty - * of the submitter. - */ - if (replace_stderr && freopen("/dev/null", "w", stderr) == NULL) { - ap_log_error(APLOG_MARK, APLOG_CRIT, s_main, - "unable to replace stderr with /dev/null"); - } - - for (virt = s_main->next; virt; virt = virt->next) { - if (virt->error_fname) - { - for (q=s_main; q != virt; q = q->next) - if (q->error_fname != NULL && - strcmp(q->error_fname, virt->error_fname) == 0) - break; - if (q == virt) - open_error_log(virt, p); - else - virt->error_log = q->error_log; + /* note that stderr may still need to be replaced with something + * because it points to the old error log, or back to the tty + * of the submitter. + */ + if (replace_stderr && freopen("/dev/null", "w", stderr) == NULL) + ap_log_error(APLOG_MARK, APLOG_CRIT, s_main, + "unable to replace stderr with /dev/null"); + + for (virt = s_main->next; virt; virt = virt->next) { + if (virt->error_fname) { + for (q=s_main; q != virt; q = q->next) + if (q->error_fname != NULL && + strcmp(q->error_fname, virt->error_fname) + == 0) + break; + if (q == virt) + open_error_log(virt, p); + else + virt->error_log = q->error_log; + } else + virt->error_log = s_main->error_log; } - else - virt->error_log = s_main->error_log; - } } -API_EXPORT(void) ap_error_log2stderr(server_rec *s) { - if ( s->error_log != NULL - && fileno(s->error_log) != STDERR_FILENO) - dup2(fileno(s->error_log), STDERR_FILENO); +API_EXPORT(void) +ap_error_log2stderr(server_rec *s) +{ + if (s->error_log != NULL && fileno(s->error_log) != STDERR_FILENO) + dup2(fileno(s->error_log), STDERR_FILENO); } -static void log_error_core(const char *file, int line, int level, - const server_rec *s, const request_rec *r, - const char *fmt, va_list args) +static void +log_error_core(const char *file, int line, int level, const server_rec *s, + const request_rec *r, const char *fmt, va_list args) { - char errstr[MAX_STRING_LEN]; - char scratch[MAX_STRING_LEN]; - size_t len; - int save_errno = errno; - FILE *logf; - - if (s == NULL) { - /* - * If we are doing stderr logging (startup), don't log messages that are - * above the default server log level unless it is a startup/shutdown - * notice - */ - if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) && - ((level & APLOG_LEVELMASK) > DEFAULT_LOGLEVEL)) - return; - logf = stderr; - } - else if (s->error_log) { - /* - * If we are doing normal logging, don't log messages that are - * above the server log level unless it is a startup/shutdown notice - */ - if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) && - ((level & APLOG_LEVELMASK) > s->loglevel)) - return; - logf = s->error_log; - } - else { - /* - * If we are doing syslog logging, don't log messages that are - * above the server log level (including a startup/shutdown notice) - */ - if ((level & APLOG_LEVELMASK) > s->loglevel) - return; - logf = NULL; - } - - if (logf) { - len = ap_snprintf(errstr, sizeof(errstr), "[%s] ", ap_get_time()); - } else { - len = 0; - } + char errstr[MAX_STRING_LEN]; + char scratch[MAX_STRING_LEN]; + size_t len; + int save_errno = errno; + FILE *logf; + + if (s == NULL) { + /* + * If we are doing stderr logging (startup), don't log messages + * that are above the default server log level unless it is a + * startup/shutdown notice + */ + if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) && + ((level & APLOG_LEVELMASK) > DEFAULT_LOGLEVEL)) + return; + logf = stderr; + } else if (s->error_log) { + /* + * If we are doing normal logging, don't log messages that are + * above the server log level unless it is a startup/shutdown + * notice + */ + if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) && + ((level & APLOG_LEVELMASK) > s->loglevel)) + return; + logf = s->error_log; + } else { + /* + * If we are doing syslog logging, don't log messages that are + * above the server log level (including a startup/shutdown + * notice) + */ + if ((level & APLOG_LEVELMASK) > s->loglevel) + return; + logf = NULL; + } - len += ap_snprintf(errstr + len, sizeof(errstr) - len, - "[%s] ", priorities[level & APLOG_LEVELMASK].t_name); + if (logf) + len = ap_snprintf(errstr, sizeof(errstr), "[%s] ", + ap_get_time()); + else + len = 0; - if (file && (level & APLOG_LEVELMASK) == APLOG_DEBUG) { - len += ap_snprintf(errstr + len, sizeof(errstr) - len, - "%s(%d): ", file, line); - } - if (r) { - /* XXX: TODO: add a method of selecting whether logged client - * addresses are in dotted quad or resolved form... dotted - * quad is the most secure, which is why I'm implementing it - * first. -djg - */ - len += ap_snprintf(errstr + len, sizeof(errstr) - len, - "[client %s] ", r->connection->remote_ip); - } - if (!(level & APLOG_NOERRNO) - && (save_errno != 0) - ) { len += ap_snprintf(errstr + len, sizeof(errstr) - len, - "(%d)%s: ", save_errno, strerror(save_errno)); - } - - if (ap_vsnprintf(scratch, sizeof(scratch) - len, fmt, args)) { - len += ap_escape_errorlog_item(errstr + len, scratch, - sizeof(errstr) - len); - } - - /* NULL if we are logging to syslog */ - if (logf) { - fputs(errstr, logf); - fputc('\n', logf); - fflush(logf); - } - else { - syslog(level & APLOG_LEVELMASK, "%s", errstr); - } + "[%s] ", priorities[level & APLOG_LEVELMASK].t_name); + + if (file && (level & APLOG_LEVELMASK) == APLOG_DEBUG) + len += ap_snprintf(errstr + len, sizeof(errstr) - len, + "%s(%d): ", file, line); + if (r) + /* XXX: TODO: add a method of selecting whether logged client + * addresses are in dotted quad or resolved form... dotted + * quad is the most secure, which is why I'm implementing it + * first. -djg + */ + len += ap_snprintf(errstr + len, sizeof(errstr) - len, + "[client %s] ", r->connection->remote_ip); + + if (!(level & APLOG_NOERRNO) && (save_errno != 0)) + len += ap_snprintf(errstr + len, sizeof(errstr) - len, + "(%d)%s: ", save_errno, strerror(save_errno)); + + if (ap_vsnprintf(scratch, sizeof(scratch) - len, fmt, args)) + len += ap_escape_errorlog_item(errstr + len, scratch, + sizeof(errstr) - len); + + /* NULL if we are logging to syslog */ + if (logf) { + fputs(errstr, logf); + fputc('\n', logf); + fflush(logf); + } else + syslog(level & APLOG_LEVELMASK, "%s", errstr); } - -API_EXPORT_NONSTD(void) ap_log_error(const char *file, int line, int level, - const server_rec *s, const char *fmt, ...) + +API_EXPORT_NONSTD(void) +ap_log_error(const char *file, int line, int level, const server_rec *s, + const char *fmt, ...) { - va_list args; + va_list args; - va_start(args, fmt); - log_error_core(file, line, level, s, NULL, fmt, args); - va_end(args); + va_start(args, fmt); + log_error_core(file, line, level, s, NULL, fmt, args); + va_end(args); } -API_EXPORT_NONSTD(void) ap_log_rerror(const char *file, int line, int level, - const request_rec *r, const char *fmt, ...) +API_EXPORT_NONSTD(void) +ap_log_rerror(const char *file, int line, int level, const request_rec *r, + const char *fmt, ...) { - va_list args; - - va_start(args, fmt); - log_error_core(file, line, level, r->server, r, fmt, args); - /* - * IF the error level is 'warning' or more severe, - * AND there isn't already error text associated with this request, - * THEN make the message text available to ErrorDocument and - * other error processors. This can be disabled by stuffing - * something, even an empty string, into the "error-notes" cell - * before calling this routine. - */ - va_end(args); - va_start(args,fmt); - if (((level & APLOG_LEVELMASK) <= APLOG_WARNING) - && (ap_table_get(r->notes, "error-notes") == NULL)) { - ap_table_setn(r->notes, "error-notes", - ap_escape_html(r->pool, ap_pvsprintf(r->pool, fmt, - args))); - } - va_end(args); + va_list args; + + va_start(args, fmt); + log_error_core(file, line, level, r->server, r, fmt, args); + /* + * IF the error level is 'warning' or more severe, + * AND there isn't already error text associated with this request, + * THEN make the message text available to ErrorDocument and + * other error processors. This can be disabled by stuffing + * something, even an empty string, into the "error-notes" cell + * before calling this routine. + */ + va_end(args); + va_start(args,fmt); + if (((level & APLOG_LEVELMASK) <= APLOG_WARNING) + && (ap_table_get(r->notes, "error-notes") == NULL)) { + ap_table_setn(r->notes, "error-notes", + ap_escape_html(r->pool, ap_pvsprintf(r->pool, fmt, args))); + } + va_end(args); } -API_EXPORT(void) ap_log_pid(pool *p, char *fname) +API_EXPORT(void) +ap_log_pid(pool *p, char *fname) { - FILE *pid_file; - struct stat finfo; - static pid_t saved_pid = -1; - pid_t mypid; - mode_t u; - - if (!fname) - return; - - fname = ap_server_root_relative(p, fname); - mypid = getpid(); - if (!ap_server_chroot_desired() && mypid != saved_pid - && stat(fname, &finfo) == 0) { - /* USR1 and HUP call this on each restart. - * Only warn on first time through for this pid. - * - * XXX: Could just write first time through too, although - * that may screw up scripts written to do something - * based on the last modification time of the pid file. - */ - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL, - ap_psprintf(p, - "pid file %s overwritten -- Unclean shutdown of previous Apache run?", - fname) - ); - } - - u = umask(022); - (void) umask(u | 022); - if(!(pid_file = fopen(fname, "w"))) { - perror("fopen"); - fprintf(stderr, "%s: could not log pid to file %s\n", - ap_server_argv0, fname); - exit(1); - } - (void) umask(u); - fprintf(pid_file, "%ld\n", (long)mypid); - fclose(pid_file); - saved_pid = mypid; + FILE *pid_file; + struct stat finfo; + static pid_t saved_pid = -1; + pid_t mypid; + mode_t u; + + if (!fname) + return; + + fname = ap_server_root_relative(p, fname); + mypid = getpid(); + if (!ap_server_chroot_desired() && mypid != saved_pid + && stat(fname, &finfo) == 0) + /* USR1 and HUP call this on each restart. + * Only warn on first time through for this pid. + * + * XXX: Could just write first time through too, although + * that may screw up scripts written to do something + * based on the last modification time of the pid file. + */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL, + ap_psprintf(p, "pid file %s overwritten -- Unclean shutdown" + " of previous Apache run?", fname)); + + u = umask(022); + (void)umask(u | 022); + if(!(pid_file = fopen(fname, "w"))) { + perror("fopen"); + fprintf(stderr, "%s: could not log pid to file %s\n", + ap_server_argv0, fname); + exit(1); + } + (void)umask(u); + fprintf(pid_file, "%ld\n", (long)mypid); + fclose(pid_file); + saved_pid = mypid; } -API_EXPORT(void) ap_log_error_old(const char *err, server_rec *s) +API_EXPORT(void) +ap_log_error_old(const char *err, server_rec *s) { - ap_log_error(APLOG_MARK, APLOG_ERR, s, "%s", err); + ap_log_error(APLOG_MARK, APLOG_ERR, s, "%s", err); } -API_EXPORT(void) ap_log_unixerr(const char *routine, const char *file, - const char *msg, server_rec *s) +API_EXPORT(void) +ap_log_unixerr(const char *routine, const char *file, const char *msg, + server_rec *s) { - ap_log_error(file, 0, APLOG_ERR, s, "%s", msg); + ap_log_error(file, 0, APLOG_ERR, s, "%s", msg); } -API_EXPORT_NONSTD(void) ap_log_printf(const server_rec *s, const char *fmt, ...) +API_EXPORT_NONSTD(void) +ap_log_printf(const server_rec *s, const char *fmt, ...) { - va_list args; - - va_start(args, fmt); - log_error_core(APLOG_MARK, APLOG_ERR, s, NULL, fmt, args); - va_end(args); + va_list args; + + va_start(args, fmt); + log_error_core(APLOG_MARK, APLOG_ERR, s, NULL, fmt, args); + va_end(args); } -API_EXPORT(void) ap_log_reason(const char *reason, const char *file, request_rec *r) +API_EXPORT(void) +ap_log_reason(const char *reason, const char *file, request_rec *r) { - ap_log_error(APLOG_MARK, APLOG_ERR, r->server, - "access to %s failed for %s, reason: %s", - file, - ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME), - reason); + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "access to %s failed for %s, reason: %s", file, + ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME), + reason); } -API_EXPORT(void) ap_log_assert(const char *szExp, const char *szFile, int nLine) +API_EXPORT(void) +ap_log_assert(const char *szExp, const char *szFile, int nLine) { - fprintf(stderr, "[%s] file %s, line %d, assertion \"%s\" failed\n", + fprintf(stderr, "[%s] file %s, line %d, assertion \"%s\" failed\n", ap_get_time(), szFile, nLine, szExp); - /* unix assert does an abort leading to a core dump */ - abort(); + /* unix assert does an abort leading to a core dump */ + abort(); } /* piped log support */ @@ -438,146 +435,151 @@ API_EXPORT(void) ap_log_assert(const char *szExp, const char *szFile, int nLine) /* forward declaration */ static void piped_log_maintenance(int reason, void *data, ap_wait_t status); -static int piped_log_spawn(piped_log *pl) +static int +piped_log_spawn(piped_log *pl) { - int pid; - - ap_block_alarms(); - pid = fork(); - if (pid == 0) { - /* XXX: need to check what open fds the logger is actually passed, - * XXX: and CGIs for that matter ... cleanup_for_exec *should* - * XXX: close all the relevant stuff, but hey, it could be broken. */ - RAISE_SIGSTOP(PIPED_LOG_SPAWN); - /* we're now in the child */ - close(STDIN_FILENO); - dup2(pl->fds[0], STDIN_FILENO); - - ap_cleanup_for_exec(); - signal(SIGCHLD, SIG_DFL); /* for HPUX */ - signal(SIGHUP, SIG_IGN); - execl(SHELL_PATH, SHELL_PATH, "-c", pl->program, (char *)NULL); - fprintf(stderr, - "piped_log_spawn: unable to exec %s -c '%s': %s\n", - SHELL_PATH, pl->program, strerror (errno)); - exit(1); - } - if (pid == -1) { - fprintf(stderr, - "piped_log_spawn: unable to fork(): %s\n", strerror (errno)); + int pid; + + ap_block_alarms(); + pid = fork(); + if (pid == 0) { + /* XXX: need to check what open fds the logger is actually + * passed, + * XXX: and CGIs for that matter ... cleanup_for_exec *should* + * XXX: close all the relevant stuff, but hey, it could be + * broken. */ + RAISE_SIGSTOP(PIPED_LOG_SPAWN); + /* we're now in the child */ + close(STDIN_FILENO); + dup2(pl->fds[0], STDIN_FILENO); + + ap_cleanup_for_exec(); + signal(SIGCHLD, SIG_DFL); /* for HPUX */ + signal(SIGHUP, SIG_IGN); + execl(SHELL_PATH, SHELL_PATH, "-c", pl->program, (char *)NULL); + fprintf(stderr, + "piped_log_spawn: unable to exec %s -c '%s': %s\n", + SHELL_PATH, pl->program, strerror (errno)); + exit(1); + } + if (pid == -1) { + fprintf(stderr, + "piped_log_spawn: unable to fork(): %s\n", strerror(errno)); + ap_unblock_alarms(); + return -1; + } ap_unblock_alarms(); - return -1; - } - ap_unblock_alarms(); - pl->pid = pid; - ap_register_other_child(pid, piped_log_maintenance, pl, pl->fds[1]); - return 0; + pl->pid = pid; + ap_register_other_child(pid, piped_log_maintenance, pl, pl->fds[1]); + return 0; } -static void piped_log_maintenance(int reason, void *data, ap_wait_t status) +static void +piped_log_maintenance(int reason, void *data, ap_wait_t status) { - piped_log *pl = data; - - switch (reason) { - case OC_REASON_DEATH: - case OC_REASON_LOST: - pl->pid = -1; - ap_unregister_other_child(pl); - if (pl->program == NULL) { - /* during a restart */ - break; + piped_log *pl = data; + + switch (reason) { + case OC_REASON_DEATH: + case OC_REASON_LOST: + pl->pid = -1; + ap_unregister_other_child(pl); + if (pl->program == NULL) + /* during a restart */ + break; + if (piped_log_spawn(pl) == -1) + /* what can we do? This could be the error log we're having + * problems opening up... */ + fprintf(stderr, + "piped_log_maintenance: unable to respawn '%s': %s\n", + pl->program, strerror(errno)); + break; + case OC_REASON_UNWRITABLE: + /* We should not kill off the pipe here, since it may only be + * full. If it really is locked, we should kill it off manually. + */ + break; + case OC_REASON_RESTART: + pl->program = NULL; + if (pl->pid != -1) + kill(pl->pid, SIGTERM); + break; + case OC_REASON_UNREGISTER: + break; } - if (piped_log_spawn(pl) == -1) { - /* what can we do? This could be the error log we're having - * problems opening up... */ - fprintf(stderr, - "piped_log_maintenance: unable to respawn '%s': %s\n", - pl->program, strerror(errno)); - } - break; - - case OC_REASON_UNWRITABLE: - /* We should not kill off the pipe here, since it may only be full. - * If it really is locked, we should kill it off manually. */ - break; - - case OC_REASON_RESTART: - pl->program = NULL; - if (pl->pid != -1) { - kill(pl->pid, SIGTERM); - } - break; - - case OC_REASON_UNREGISTER: - break; - } } -static void piped_log_cleanup(void *data) +static void +piped_log_cleanup(void *data) { - piped_log *pl = data; - - if (pl->pid != -1) { - kill(pl->pid, SIGTERM); - } - ap_unregister_other_child(pl); - close(pl->fds[0]); - close(pl->fds[1]); + piped_log *pl = data; + + if (pl->pid != -1) + kill(pl->pid, SIGTERM); + + ap_unregister_other_child(pl); + close(pl->fds[0]); + close(pl->fds[1]); } -static void piped_log_cleanup_for_exec(void *data) +static void +piped_log_cleanup_for_exec(void *data) { - piped_log *pl = data; + piped_log *pl = data; - close(pl->fds[0]); - close(pl->fds[1]); + close(pl->fds[0]); + close(pl->fds[1]); } -static int piped_log_magic_cleanup(void *data) +static int +piped_log_magic_cleanup(void *data) { - piped_log *pl = data; + piped_log *pl = data; - /* Yes, I _do_ mean a binary and */ - return ap_close_fd_on_exec(pl->fds[0]) & ap_close_fd_on_exec(pl->fds[1]); + /* Yes, I _do_ mean a binary and */ + return ap_close_fd_on_exec(pl->fds[0]) & + ap_close_fd_on_exec(pl->fds[1]); } -API_EXPORT(piped_log *) ap_open_piped_log(pool *p, const char *program) +API_EXPORT(piped_log *) +ap_open_piped_log(pool *p, const char *program) { - piped_log *pl; - - pl = ap_palloc(p, sizeof (*pl)); - pl->p = p; - pl->program = ap_pstrdup(p, program); - pl->pid = -1; - ap_block_alarms (); - if (pipe(pl->fds) == -1) { - int save_errno = errno; - ap_unblock_alarms(); - errno = save_errno; - return NULL; - } - ap_register_cleanup_ex(p, pl, piped_log_cleanup, piped_log_cleanup_for_exec, - piped_log_magic_cleanup); - if (piped_log_spawn(pl) == -1) { - int save_errno = errno; - ap_kill_cleanup(p, pl, piped_log_cleanup); - close(pl->fds[0]); - close(pl->fds[1]); + piped_log *pl; + + pl = ap_palloc(p, sizeof (*pl)); + pl->p = p; + pl->program = ap_pstrdup(p, program); + pl->pid = -1; + ap_block_alarms (); + if (pipe(pl->fds) == -1) { + int save_errno = errno; + ap_unblock_alarms(); + errno = save_errno; + return NULL; + } + ap_register_cleanup_ex(p, pl, piped_log_cleanup, + piped_log_cleanup_for_exec, piped_log_magic_cleanup); + if (piped_log_spawn(pl) == -1) { + int save_errno = errno; + ap_kill_cleanup(p, pl, piped_log_cleanup); + close(pl->fds[0]); + close(pl->fds[1]); + ap_unblock_alarms(); + errno = save_errno; + return NULL; + } ap_unblock_alarms(); - errno = save_errno; - return NULL; - } - ap_unblock_alarms(); - return pl; + return pl; } -API_EXPORT(void) ap_close_piped_log(piped_log *pl) +API_EXPORT(void) +ap_close_piped_log(piped_log *pl) { - ap_block_alarms(); - piped_log_cleanup(pl); - ap_kill_cleanup(pl->p, pl, piped_log_cleanup); - ap_unblock_alarms(); + ap_block_alarms(); + piped_log_cleanup(pl); + ap_kill_cleanup(pl->p, pl, piped_log_cleanup); + ap_unblock_alarms(); } diff --git a/usr.sbin/httpd/src/main/http_vhost.c b/usr.sbin/httpd/src/main/http_vhost.c index c659dbb1a7c..8a028adf0f5 100644 --- a/usr.sbin/httpd/src/main/http_vhost.c +++ b/usr.sbin/httpd/src/main/http_vhost.c @@ -1,3 +1,5 @@ +/* $OpenBSD: http_vhost.c,v 1.9 2008/05/14 08:42:20 mbalmer Exp $ */ + /* ==================================================================== * The Apache Software License, Version 1.1 * @@ -58,7 +60,7 @@ /* * http_vhost.c: functions pertaining to virtual host addresses - * (configuration and run-time) + * (configuration and run-time) */ #define CORE_PRIVATE @@ -79,10 +81,11 @@ */ typedef struct name_chain name_chain; struct name_chain { - name_chain *next; - server_addr_rec *sar; /* the record causing it to be in - * this chain (needed for port comparisons) */ - server_rec *server; /* the server to use on a match */ + name_chain *next; + server_addr_rec *sar; /* the record causing it to be in + * this chain (needed for port + * comparisons) */ + server_rec *server; /* the server to use on a match */ }; /* meta-list of ip addresses. Each server_rec can be in possibly multiple @@ -90,13 +93,13 @@ struct name_chain { */ typedef struct ipaddr_chain ipaddr_chain; struct ipaddr_chain { - ipaddr_chain *next; - server_addr_rec *sar; /* the record causing it to be in - * this chain (need for both ip addr and port - * comparisons) */ - server_rec *server; /* the server to use if this matches */ - name_chain *names; /* if non-NULL then a list of name-vhosts - * sharing this address */ + ipaddr_chain *next; + server_addr_rec *sar; /* the record causing it to be in + * this chain (need for both ip addr + * and port comparisons) */ + server_rec *server; /* the server to use if this matches */ + name_chain *names; /* if non-NULL then a list of + * name-vhosts sharing this address */ }; /* This defines the size of the hash table used for hashing ip addresses @@ -149,12 +152,13 @@ static server_addr_rec **name_vhost_list_tail; /* called at the beginning of the config */ -API_EXPORT(void) ap_init_vhost_config(pool *p) +API_EXPORT(void) +ap_init_vhost_config(pool *p) { - memset(iphash_table, 0, sizeof(iphash_table)); - default_list = NULL; - name_vhost_list = NULL; - name_vhost_list_tail = &name_vhost_list; + memset(iphash_table, 0, sizeof(iphash_table)); + default_list = NULL; + name_vhost_list = NULL; + name_vhost_list_tail = &name_vhost_list; } @@ -165,146 +169,148 @@ API_EXPORT(void) ap_init_vhost_config(pool *p) * *paddr is the variable used to keep track of **paddr between calls * port is the default port to assume */ -static const char *get_addresses(pool *p, char *w, char *pstr, - server_addr_rec ***paddr, unsigned port) +static const char * +get_addresses(pool *p, char *w, char *pstr, server_addr_rec ***paddr, + unsigned port) { - struct addrinfo hints, *res, *res0; - server_addr_rec *sar; - char *t = NULL, *u = NULL, *v = NULL; - char *hoststr = NULL, *portstr = NULL; - char portpool[10]; - int error; - char servbuf[NI_MAXSERV]; - - if (w == 0 || *w == 0) - return NULL; - - portstr = portpool; - ap_snprintf(portpool, sizeof(portpool), "%u", port); - if (!pstr) { - v = w; - u = NULL; - if (*w == '['){ - u = strrchr(w, ']'); - if (u) { /* [host]:port or [host] */ - w++; - *u = '\0'; - v = u + 1; - } + struct addrinfo hints, *res, *res0; + server_addr_rec *sar; + char *t = NULL, *u = NULL, *v = NULL; + char *hoststr = NULL, *portstr = NULL; + char portpool[10]; + int error; + char servbuf[NI_MAXSERV]; + + if (w == 0 || *w == 0) + return NULL; + + portstr = portpool; + ap_snprintf(portpool, sizeof(portpool), "%u", port); + if (!pstr) { + v = w; + u = NULL; + if (*w == '['){ + u = strrchr(w, ']'); + if (u) { /* [host]:port or [host] */ + w++; + *u = '\0'; + v = u + 1; + } + } + /* w uv , w=v , w=v */ + /* u!=0: [host]:port , u==0: [host:port , host */ + t = strchr(v, ':'); + if (t != NULL && strchr(t+1, ':') == NULL) { + /* [host]:port-w/o-colons, + * host-without-colons:port-w/o-colons + */ + *t = '\0'; + portstr = t + 1; + } else + portstr = "0"; + } else + portstr = pstr; + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + if (strcmp(w, "*") == 0 || strlen(w) == 0) { + hoststr = NULL; + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + } else if (strcasecmp(w, "_default4_") == 0 || + ((ap_default_family == PF_INET || ap_default_family == PF_UNSPEC) + && strcasecmp(w, "_default_") == 0)){ + hoststr = "255.255.255.255"; + hints.ai_family = PF_INET; + } else if (strcasecmp(w, "_default6_") == 0 || + ((ap_default_family == PF_INET6 || ap_default_family == PF_UNSPEC) + && strcasecmp(w, "_default_") == 0)){ + hoststr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; + hints.ai_family = PF_INET6; + } else{ + hoststr = w; + hints.ai_family = PF_UNSPEC; } - /* w uv , w=v , w=v */ - /* u!=0: [host]:port , u==0: [host:port , host */ - t = strchr(v, ':'); - if (t != NULL && strchr(t+1, ':') == NULL) { - /* [host]:port-w/o-colons, host-without-colons:port-w/o-colons */ - *t = '\0'; - portstr = t + 1; + + error = getaddrinfo(hoststr, portstr, &hints, &res0); + if (error || !res0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "Cannot resolve host %s port %s --- ignoring!", hoststr, + portstr); + if (t != NULL) + *t = ':'; + if (u != NULL) + *u = ']'; + return NULL; } - else { - portstr = "0"; + for (res=res0; res; res=res->ai_next) { + switch (res->ai_addr->sa_family) { + case AF_INET: + case AF_INET6: + break; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "Unsupported address family %u, for host %s " + "port %s --- ignoring!", res->ai_addr->sa_family, + hoststr, portstr); + continue; + } + sar = ap_pcalloc(p, sizeof(server_addr_rec)); + **paddr = sar; + *paddr = &sar->next; + memcpy(&sar->host_addr, res->ai_addr, res->ai_addrlen); + if (getnameinfo(res->ai_addr, res->ai_addrlen, NULL, 0, + servbuf, sizeof(servbuf), NI_NUMERICSERV) == 0) + sar->host_port = atoi(servbuf); + else + sar->host_port = 0; + sar->virthost = ap_pstrdup(p, w); } - } else { - portstr = pstr; - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = SOCK_STREAM; - if (strcmp(w, "*") == 0 || strlen(w) == 0) { - hoststr = NULL; - hints.ai_family = PF_UNSPEC; - hints.ai_flags = AI_PASSIVE; - } - else if (strcasecmp(w, "_default4_") == 0 || - ((ap_default_family == PF_INET - || ap_default_family == PF_UNSPEC - ) && strcasecmp(w, "_default_") == 0)){ - hoststr = "255.255.255.255"; - hints.ai_family = PF_INET; - } - else if (strcasecmp(w, "_default6_") == 0 || - ((ap_default_family == PF_INET6 - || ap_default_family == PF_UNSPEC - ) && strcasecmp(w, "_default_") == 0)){ - hoststr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; - hints.ai_family = PF_INET6; - } - else{ - hoststr = w; - hints.ai_family = PF_UNSPEC; - } - - error = getaddrinfo(hoststr, portstr, &hints, &res0); - if (error || !res0) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, - "Cannot resolve host %s port %s --- ignoring!", hoststr, portstr); - if (t != NULL) *t = ':'; - if (u != NULL) *u = ']'; + + freeaddrinfo(res0); + if (t != NULL) + *t = ':'; + if (u != NULL) + *u = ']'; return NULL; - } - for (res=res0; res; res=res->ai_next) { - switch (res->ai_addr->sa_family) { - case AF_INET: - case AF_INET6: - break; - default: - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, - "Unsupported address family %u, for host %s port %s --- ignoring!", - res->ai_addr->sa_family, hoststr, portstr); - continue; - } - sar = ap_pcalloc(p, sizeof(server_addr_rec)); - **paddr = sar; - *paddr = &sar->next; - memcpy(&sar->host_addr, res->ai_addr, res->ai_addrlen); - if (getnameinfo(res->ai_addr, res->ai_addrlen, NULL, 0, servbuf, - sizeof(servbuf), NI_NUMERICSERV) == 0) - sar->host_port = atoi(servbuf); - else - sar->host_port = 0; - sar->virthost = ap_pstrdup(p, w); - } - - freeaddrinfo(res0); - if (t != NULL) *t = ':'; - if (u != NULL) *u = ']'; - return NULL; } - /* parse the <VirtualHost> addresses */ -API_EXPORT(const char *) ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s) +API_EXPORT(const char *) +ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s) { - server_addr_rec **addrs; - const char *err; - - /* start the list of addreses */ - addrs = &s->addrs; - while (hostname[0]) { - err = get_addresses(p, ap_getword_conf(p, &hostname), NULL, - &addrs, s->port); - if (err) { - *addrs = NULL; - return err; + server_addr_rec **addrs; + const char *err; + + /* start the list of addreses */ + addrs = &s->addrs; + while (hostname[0]) { + err = get_addresses(p, ap_getword_conf(p, &hostname), NULL, + &addrs, s->port); + if (err) { + *addrs = NULL; + return err; + } } - } - /* terminate the list */ - *addrs = NULL; - if (s->addrs) { - if (s->addrs->host_port) { - /* override the default port which is inherited from main_server */ - s->port = s->addrs->host_port; + /* terminate the list */ + *addrs = NULL; + if (s->addrs) { + if (s->addrs->host_port) + /* override the default port which is + * inherited from main_server + */ + s->port = s->addrs->host_port; } - } - return NULL; + return NULL; } -API_EXPORT_NONSTD(const char *) ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *h, - char *p) +API_EXPORT_NONSTD(const char *) +ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *h, char *p) { - /* use whatever port the main server has at this point */ - return get_addresses(cmd->pool, h, p, &name_vhost_list_tail, - cmd->server->port); + /* use whatever port the main server has at this point */ + return get_addresses(cmd->pool, h, p, &name_vhost_list_tail, + cmd->server->port); } @@ -312,51 +318,50 @@ API_EXPORT_NONSTD(const char *) ap_set_name_virtual_host (cmd_parms *cmd, void * * we can find out if the hash function is ok */ #ifdef IPHASH_STATISTICS -static int iphash_compare(const void *a, const void *b) +static int +iphash_compare(const void *a, const void *b) { - return (*(const int *) b - *(const int *) a); + return (*(const int *)b - *(const int *)a); } -static void dump_iphash_statistics(server_rec *main_s) +static void +dump_iphash_statistics(server_rec *main_s) { - unsigned count[IPHASH_TABLE_SIZE]; - int i; - ipaddr_chain *src; - unsigned total; - char buf[HUGE_STRING_LEN]; - char *p; - - total = 0; - for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { - count[i] = 0; - for (src = iphash_table[i]; src; src = src->next) { - ++count[i]; - if (i < IPHASH_TABLE_SIZE) { - /* don't count the slop buckets in the total */ - ++total; - } - } - } - qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare); - p = buf + ap_snprintf(buf, sizeof(buf), - "iphash: total hashed = %u, avg chain = %u, " - "chain lengths (count x len):", - total, total / IPHASH_TABLE_SIZE); - total = 1; - for (i = 1; i < IPHASH_TABLE_SIZE; ++i) { - if (count[i - 1] != count[i]) { - p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u", - total, count[i - 1]); - total = 1; + unsigned count[IPHASH_TABLE_SIZE]; + int i; + ipaddr_chain *src; + unsigned total; + char buf[HUGE_STRING_LEN]; + char *p; + + total = 0; + for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { + count[i] = 0; + for (src = iphash_table[i]; src; src = src->next) { + ++count[i]; + if (i < IPHASH_TABLE_SIZE) + /* don't count the slop buckets in the total */ + ++total; + } } - else { - ++total; + qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare); + p = buf + ap_snprintf(buf, sizeof(buf), + "iphash: total hashed = %u, avg chain = %u, " + "chain lengths (count x len):", + total, total / IPHASH_TABLE_SIZE); + total = 1; + for (i = 1; i < IPHASH_TABLE_SIZE; ++i) { + if (count[i - 1] != count[i]) { + p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u", + total, count[i - 1]); + total = 1; + } else + ++total; } - } - p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u", - total, count[IPHASH_TABLE_SIZE - 1]); - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf); + p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u", + total, count[IPHASH_TABLE_SIZE - 1]); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf); } #endif @@ -371,442 +376,463 @@ static void dump_iphash_statistics(server_rec *main_s) * * Hash function provided by David Hankins. */ -static ap_inline unsigned hash_inaddr(unsigned key) +static ap_inline unsigned +hash_inaddr(unsigned key) { - key ^= (key >> 16); - return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE; + key ^= (key >> 16); + return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE; } -static unsigned hash_addr(struct sockaddr *sa) +static unsigned +hash_addr(struct sockaddr *sa) { - switch (sa->sa_family) { - case AF_INET: - return hash_inaddr(((struct sockaddr_in *)sa)->sin_addr.s_addr); - case AF_INET6: - return hash_inaddr(((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12]); - default: - return hash_inaddr(sa->sa_family); - } + switch (sa->sa_family) { + case AF_INET: + return hash_inaddr(((struct sockaddr_in *)sa)->sin_addr.s_addr); + case AF_INET6: + return hash_inaddr( + ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12]); + default: + return hash_inaddr(sa->sa_family); + } } -static ipaddr_chain *new_ipaddr_chain(pool *p, - server_rec *s, server_addr_rec *sar) +static ipaddr_chain * +new_ipaddr_chain(pool *p, server_rec *s, server_addr_rec *sar) { - ipaddr_chain *new; - - new = ap_palloc(p, sizeof(*new)); - new->names = NULL; - new->server = s; - new->sar = sar; - new->next = NULL; - return new; + ipaddr_chain *new; + + new = ap_palloc(p, sizeof(*new)); + new->names = NULL; + new->server = s; + new->sar = sar; + new->next = NULL; + return new; } -static name_chain *new_name_chain(pool *p, server_rec *s, server_addr_rec *sar) +static name_chain * +new_name_chain(pool *p, server_rec *s, server_addr_rec *sar) { - name_chain *new; + name_chain *new; - new = ap_palloc(p, sizeof(*new)); - new->server = s; - new->sar = sar; - new->next = NULL; - return new; + new = ap_palloc(p, sizeof(*new)); + new->server = s; + new->sar = sar; + new->next = NULL; + return new; } -static ap_inline ipaddr_chain *find_ipaddr(struct sockaddr *sa) +static ap_inline ipaddr_chain * +find_ipaddr(struct sockaddr *sa) { - unsigned bucket; - ipaddr_chain *trav; - char a[NI_MAXHOST], b[NI_MAXHOST]; - - /* scan the hash table for an exact match first */ - bucket = hash_addr(sa); - for (trav = iphash_table[bucket]; trav; trav = trav->next) { - server_addr_rec *sar = trav->sar; - if (sar->host_addr.ss_family != sa->sa_family) - continue; - switch (sa->sa_family) { - case AF_INET: - { - struct sockaddr_in *sin1, *sin2; - sin1 = (struct sockaddr_in *)&sar->host_addr; - sin2 = (struct sockaddr_in *)sa; - if (sin1->sin_port == 0 || sin2->sin_port == 0 - || sin1->sin_port == sin2->sin_port) { - if (memcmp(&sin1->sin_addr, &sin2->sin_addr, - sizeof(sin1->sin_addr)) == 0) { - return trav; + unsigned bucket; + ipaddr_chain *trav; + char a[NI_MAXHOST], b[NI_MAXHOST]; + + /* scan the hash table for an exact match first */ + bucket = hash_addr(sa); + for (trav = iphash_table[bucket]; trav; trav = trav->next) { + server_addr_rec *sar = trav->sar; + if (sar->host_addr.ss_family != sa->sa_family) + continue; + switch (sa->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin1, *sin2; + sin1 = (struct sockaddr_in *)&sar->host_addr; + sin2 = (struct sockaddr_in *)sa; + if (sin1->sin_port == 0 || sin2->sin_port == 0 + || sin1->sin_port == sin2->sin_port) { + if (memcmp(&sin1->sin_addr, &sin2->sin_addr, + sizeof(sin1->sin_addr)) == 0) + return trav; + } + break; } - } - break; - } - case AF_INET6: - { - struct sockaddr_in6 *sin1, *sin2; - sin1 = (struct sockaddr_in6 *)&sar->host_addr; - sin2 = (struct sockaddr_in6 *)sa; - if (sin1->sin6_port == 0 || sin2->sin6_port == 0 - || sin1->sin6_port == sin2->sin6_port) { - if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr, - sizeof(sin1->sin6_addr)) == 0) { - return trav; + case AF_INET6: + { + struct sockaddr_in6 *sin1, *sin2; + sin1 = (struct sockaddr_in6 *)&sar->host_addr; + sin2 = (struct sockaddr_in6 *)sa; + if (sin1->sin6_port == 0 || sin2->sin6_port == 0 + || sin1->sin6_port == sin2->sin6_port) { + if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr, + sizeof(sin1->sin6_addr)) == 0) + return trav; + } + break; + } + default: /*unsupported*/ + break; } - } - break; - } - default: /*unsupported*/ - break; } - } - return NULL; + return NULL; } -static ipaddr_chain *find_default_server(unsigned port) +static ipaddr_chain * +find_default_server(unsigned port) { - server_addr_rec *sar; - ipaddr_chain *trav; - - for (trav = default_list; trav; trav = trav->next) { - sar = trav->sar; - if (sar->host_port == 0 || sar->host_port == port) { - /* match! */ - return trav; - } - } - return NULL; + server_addr_rec *sar; + ipaddr_chain *trav; + + for (trav = default_list; trav; trav = trav->next) { + sar = trav->sar; + if (sar->host_port == 0 || sar->host_port == port) + /* match! */ + return trav; + } + return NULL; } -static void dump_a_vhost(FILE *f, ipaddr_chain *ic) +static void +dump_a_vhost(FILE *f, ipaddr_chain *ic) { - name_chain *nc; - int len; - char buf[MAX_STRING_LEN]; - - len = ap_snprintf(buf, sizeof(buf), "%pI", &ic->sar->host_addr); - if (ic->names == NULL) { - if (ic->server == NULL) - fprintf(f, "%-22s WARNING: No <VirtualHost> defined for this NameVirtualHost!\n", buf); - else - fprintf(f, "%-22s %s (%s:%u)\n", buf, ic->server->server_hostname, - ic->server->defn_name, ic->server->defn_line_number); - return; - } - fprintf(f, "%-22s is a NameVirtualHost\n" - "%22s default server %s (%s:%u)\n", - buf, "", ic->server->server_hostname, - ic->server->defn_name, ic->server->defn_line_number); - for (nc = ic->names; nc; nc = nc->next) { - if (nc->sar->host_port) { - fprintf(f, "%22s port %u ", "", nc->sar->host_port); + name_chain *nc; + int len; + char buf[MAX_STRING_LEN]; + + len = ap_snprintf(buf, sizeof(buf), "%pI", &ic->sar->host_addr); + if (ic->names == NULL) { + if (ic->server == NULL) + fprintf(f, "%-22s WARNING: No <VirtualHost> defined " + "for this NameVirtualHost!\n", buf); + else + fprintf(f, "%-22s %s (%s:%u)\n", buf, + ic->server->server_hostname, ic->server->defn_name, + ic->server->defn_line_number); + return; } - else { - fprintf(f, "%22s port * ", ""); + fprintf(f, "%-22s is a NameVirtualHost\n" + "%22s default server %s (%s:%u)\n", buf, "", + ic->server->server_hostname, ic->server->defn_name, + ic->server->defn_line_number); + for (nc = ic->names; nc; nc = nc->next) { + if (nc->sar->host_port) + fprintf(f, "%22s port %u ", "", nc->sar->host_port); + else + fprintf(f, "%22s port * ", ""); + fprintf(f, "namevhost %s (%s:%u)\n", + nc->server->server_hostname, nc->server->defn_name, + nc->server->defn_line_number); } - fprintf(f, "namevhost %s (%s:%u)\n", nc->server->server_hostname, - nc->server->defn_name, nc->server->defn_line_number); - } } -static void dump_vhost_config(FILE *f) +static void +dump_vhost_config(FILE *f) { - ipaddr_chain *ic; - int i; + ipaddr_chain *ic; + int i; - fprintf(f, "VirtualHost configuration:\n"); - for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { - for (ic = iphash_table[i]; ic; ic = ic->next) { - dump_a_vhost(f, ic); + fprintf(f, "VirtualHost configuration:\n"); + for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { + for (ic = iphash_table[i]; ic; ic = ic->next) + dump_a_vhost(f, ic); } - } - if (default_list) { - fprintf(f, "wildcard NameVirtualHosts and _default_ servers:\n"); - for (ic = default_list; ic; ic = ic->next) { - dump_a_vhost(f, ic); + if (default_list) { + fprintf(f, "wildcard NameVirtualHosts and _default_ " + "servers:\n"); + for (ic = default_list; ic; ic = ic->next) + dump_a_vhost(f, ic); } - } } /* * Helper functions for ap_fini_vhost_config() */ -static int add_name_vhost_config(pool *p, server_rec *main_s, server_rec *s, - server_addr_rec *sar, ipaddr_chain *ic) +static int +add_name_vhost_config(pool *p, server_rec *main_s, server_rec *s, + server_addr_rec *sar, ipaddr_chain *ic) { - /* the first time we encounter a NameVirtualHost address - * ic->server will be NULL, on subsequent encounters - * ic->names will be non-NULL. - */ - if (ic->names || ic->server == NULL) { - name_chain *nc = new_name_chain(p, s, sar); - nc->next = ic->names; - ic->names = nc; - ic->server = s; - if (sar->host_port != ic->sar->host_port) { - /* one of the two is a * port, the other isn't */ - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s, - "VirtualHost %s:%u -- mixing * " - "ports and non-* ports with " - "a NameVirtualHost address is not supported," - " proceeding with undefined results", - sar->virthost, sar->host_port); - } - return 1; - } - else { - /* IP-based vhosts are handled by the caller */ - return 0; - } + /* the first time we encounter a NameVirtualHost address + * ic->server will be NULL, on subsequent encounters + * ic->names will be non-NULL. + */ + if (ic->names || ic->server == NULL) { + name_chain *nc = new_name_chain(p, s, sar); + nc->next = ic->names; + ic->names = nc; + ic->server = s; + if (sar->host_port != ic->sar->host_port) { + /* one of the two is a * port, the other isn't */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s, + "VirtualHost %s:%u -- mixing * ports and non-* " + "ports with a NameVirtualHost address is not " + "supported, proceeding with undefined results", + sar->virthost, sar->host_port); + } + return 1; + } else + /* IP-based vhosts are handled by the caller */ + return 0; } -static void remove_unused_name_vhosts(server_rec *main_s, ipaddr_chain **pic) +static void +remove_unused_name_vhosts(server_rec *main_s, ipaddr_chain **pic) { - while (*pic) { - ipaddr_chain *ic = *pic; - - if (ic->server == NULL) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, main_s, - "NameVirtualHost %s:%u has no VirtualHosts", - ic->sar->virthost, ic->sar->host_port); - *pic = ic->next; - } - else if (ic->names == NULL) { - /* if server != NULL and names == NULL then we're done - * looking at NameVirtualHosts - */ - break; - } - else { - pic = &ic->next; + while (*pic) { + ipaddr_chain *ic = *pic; + + if (ic->server == NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, + main_s, "NameVirtualHost %s:%u has no VirtualHosts", + ic->sar->virthost, ic->sar->host_port); + *pic = ic->next; + } else if (ic->names == NULL) + /* if server != NULL and names == NULL then we're done + * looking at NameVirtualHosts + */ + break; + else + pic = &ic->next; } - } } /* compile the tables and such we need to do the run-time vhost lookups */ -API_EXPORT(void) ap_fini_vhost_config(pool *p, server_rec *main_s) +API_EXPORT(void) +ap_fini_vhost_config(pool *p, server_rec *main_s) { - server_addr_rec *sar; - int has_default_vhost_addr; - server_rec *s; - int i; - ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE]; - - /* terminate the name_vhost list */ - *name_vhost_list_tail = NULL; - - /* Main host first */ - s = main_s; - - if (!s->server_hostname) { - s->server_hostname = ap_get_local_host(p); - } - - /* initialize the tails */ - for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { - iphash_table_tail[i] = &iphash_table[i]; - } - - /* The first things to go into the hash table are the NameVirtualHosts - * Since name_vhost_list is in the same order that the directives - * occured in the config file, we'll copy it in that order. - */ - for (sar = name_vhost_list; sar; sar = sar->next) { - unsigned bucket = hash_addr((struct sockaddr *)&sar->host_addr); - ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar); - int wildcard; - - wildcard = 0; - switch (sar->host_addr.ss_family) { - case AF_INET: - { - struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sar->host_addr; - if (sin->sin_addr.s_addr == INADDR_ANY) - wildcard++; - break; - } - case AF_INET6: - { - struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&sar->host_addr; - if (*(uint32_t *)&sin6->sin6_addr.s6_addr[0] == 0 - && *(uint32_t *)&sin6->sin6_addr.s6_addr[4] == 0 - && *(uint32_t *)&sin6->sin6_addr.s6_addr[8] == 0 - && *(uint32_t *)&sin6->sin6_addr.s6_addr[12] == 0) { - wildcard++; - } - break; - } - } + server_addr_rec *sar; + int has_default_vhost_addr; + server_rec *s; + int i; + ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE]; - if (!wildcard) { - *iphash_table_tail[bucket] = ic; - iphash_table_tail[bucket] = &ic->next; - } - else { - /* A wildcard NameVirtualHost goes on the default_list so - * that it can catch incoming requests on any address. - */ - ic->next = default_list; - default_list = ic; - } - /* Notice that what we've done is insert an ipaddr_chain with - * both server and names NULL. This fact is used to spot name- - * based vhosts in add_name_vhost_config(). - */ - } - - /* The next things to go into the hash table are the virtual hosts - * themselves. They're listed off of main_s->next in the reverse - * order they occured in the config file, so we insert them at - * the iphash_table_tail but don't advance the tail. - */ - - for (s = main_s->next; s; s = s->next) { - has_default_vhost_addr = 0; - for (sar = s->addrs; sar; sar = sar->next) { - ipaddr_chain *ic; - int wildcard; - - wildcard = 0; - switch (sar->host_addr.ss_family) { - case AF_INET: - { - struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sar->host_addr; - if (sin->sin_addr.s_addr == DEFAULT_VHOST_ADDR) - wildcard++; - else if (sin->sin_addr.s_addr == INADDR_ANY) - wildcard++; - break; - } - case AF_INET6: - { - struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&sar->host_addr; - if (*(uint32_t *)&sin6->sin6_addr.s6_addr[0] == ~0 - && *(uint32_t *)&sin6->sin6_addr.s6_addr[4] == ~0 - && *(uint32_t *)&sin6->sin6_addr.s6_addr[8] == ~0 - && *(uint32_t *)&sin6->sin6_addr.s6_addr[12] == ~0) { - wildcard++; - } - break; - } - } + /* terminate the name_vhost list */ + *name_vhost_list_tail = NULL; - if (wildcard) { - /* add it to default bucket for each appropriate sar - * since we need to do a port test - */ - ipaddr_chain *other; + /* Main host first */ + s = main_s; - other = find_default_server(sar->host_port); - if (!other || !add_name_vhost_config(p, main_s, s, sar, other)) { - if (other && other->sar->host_port != 0) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, - main_s, "_default_ VirtualHost overlap on port %u," - " the first has precedence", sar->host_port); - } - ic = new_ipaddr_chain(p, s, sar); - ic->next = default_list; - default_list = ic; + if (!s->server_hostname) + s->server_hostname = ap_get_local_host(p); + + /* initialize the tails */ + for (i = 0; i < IPHASH_TABLE_SIZE; ++i) + iphash_table_tail[i] = &iphash_table[i]; + + /* The first things to go into the hash table are the NameVirtualHosts + * Since name_vhost_list is in the same order that the directives + * occured in the config file, we'll copy it in that order. + */ + for (sar = name_vhost_list; sar; sar = sar->next) { + unsigned bucket = hash_addr((struct sockaddr *)&sar->host_addr); + ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar); + int wildcard; + + wildcard = 0; + switch (sar->host_addr.ss_family) { + case AF_INET: + { + struct sockaddr_in *sin; + sin = (struct sockaddr_in *)&sar->host_addr; + if (sin->sin_addr.s_addr == INADDR_ANY) + wildcard++; + break; } - has_default_vhost_addr = 1; - } - else { - /* see if it matches something we've already got */ - ic = find_ipaddr((struct sockaddr *)&sar->host_addr); - - if (!ic) { - unsigned bucket = - hash_addr((struct sockaddr *)&sar->host_addr); - - ic = new_ipaddr_chain(p, s, sar); - ic->next = *iphash_table_tail[bucket]; - *iphash_table_tail[bucket] = ic; + case AF_INET6: + { + struct sockaddr_in6 *sin6; + sin6 = (struct sockaddr_in6 *)&sar->host_addr; + if (*(uint32_t *)&sin6->sin6_addr.s6_addr[0] == 0 + && *(uint32_t *)&sin6->sin6_addr.s6_addr[4] == 0 + && *(uint32_t *)&sin6->sin6_addr.s6_addr[8] == 0 + && *(uint32_t *)&sin6->sin6_addr.s6_addr[12] == 0) + wildcard++; + break; } - else if (!add_name_vhost_config(p, main_s, s, sar, ic)) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, main_s, - "VirtualHost %s:%u overlaps with " - "VirtualHost %s:%u, the first has precedence, " - "perhaps you need a NameVirtualHost directive", - sar->virthost, sar->host_port, - ic->sar->virthost, ic->sar->host_port); - ic->sar = sar; - ic->server = s; } - } + + if (!wildcard) { + *iphash_table_tail[bucket] = ic; + iphash_table_tail[bucket] = &ic->next; + } else { + /* A wildcard NameVirtualHost goes on the default_list so + * that it can catch incoming requests on any address. + */ + ic->next = default_list; + default_list = ic; + } + /* Notice that what we've done is insert an ipaddr_chain with + * both server and names NULL. This fact is used to spot name- + * based vhosts in add_name_vhost_config(). + */ } - /* Ok now we want to set up a server_hostname if the user was - * silly enough to forget one. - * XXX: This is silly we should just crash and burn. + /* The next things to go into the hash table are the virtual hosts + * themselves. They're listed off of main_s->next in the reverse + * order they occured in the config file, so we insert them at + * the iphash_table_tail but don't advance the tail. */ - if (!s->server_hostname) { - if (has_default_vhost_addr) { - s->server_hostname = main_s->server_hostname; - } - else if (!s->addrs) { - /* what else can we do? at this point this vhost has - no configured name, probably because they used - DNS in the VirtualHost statement. It's disabled - anyhow by the host matching code. -djg */ - s->server_hostname = - ap_pstrdup(p, "bogus_host_without_forward_dns"); - } - else { - struct hostent *h; - char hostnamebuf[MAXHOSTNAMELEN]; - - if (!getnameinfo((struct sockaddr *)&s->addrs->host_addr, + + for (s = main_s->next; s; s = s->next) { + has_default_vhost_addr = 0; + for (sar = s->addrs; sar; sar = sar->next) { + ipaddr_chain *ic; + int wildcard; + + wildcard = 0; + switch (sar->host_addr.ss_family) { + case AF_INET: + { + struct sockaddr_in *sin; + sin = (struct sockaddr_in *)&sar->host_addr; + if (sin->sin_addr.s_addr == DEFAULT_VHOST_ADDR) + wildcard++; + else if (sin->sin_addr.s_addr == INADDR_ANY) + wildcard++; + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6; + sin6 = (struct sockaddr_in6 *)&sar->host_addr; + if (*(uint32_t *)&sin6->sin6_addr.s6_addr[0] + == ~0 + && *(uint32_t *)&sin6->sin6_addr.s6_addr[4] + == ~0 + && *(uint32_t *)&sin6->sin6_addr.s6_addr[8] + == ~0 + && *(uint32_t *)&sin6->sin6_addr.s6_addr[12] + == ~0) + wildcard++; + break; + } + } + + if (wildcard) { + /* add it to default bucket for each + * appropriate sar since we need to do a port + * test + */ + ipaddr_chain *other; + + other = find_default_server(sar->host_port); + if (!other || + !add_name_vhost_config(p, main_s, s, sar, + other)) { + if (other && other->sar->host_port != 0) + ap_log_error(APLOG_MARK, + APLOG_NOERRNO|APLOG_WARNING, + main_s, + "_default_ VirtualHost " + "overlap on port %u," + " the first has precedence", + sar->host_port); + ic = new_ipaddr_chain(p, s, sar); + ic->next = default_list; + default_list = ic; + } + has_default_vhost_addr = 1; + } + else { + /* see if it matches something we've already + * got */ + ic = find_ipaddr( + (struct sockaddr *)&sar->host_addr); + + if (!ic) { + unsigned bucket = + hash_addr( + (struct sockaddr *)&sar->host_addr); + + ic = new_ipaddr_chain(p, s, sar); + ic->next = *iphash_table_tail[bucket]; + *iphash_table_tail[bucket] = ic; + } + else if (!add_name_vhost_config(p, main_s, s, + sar, ic)) { + ap_log_error(APLOG_MARK, + APLOG_NOERRNO|APLOG_WARNING, main_s, + "VirtualHost %s:%u overlaps with " + "VirtualHost %s:%u, the first has " + "precedence, perhaps you need a " + "NameVirtualHost directive", + sar->virthost, sar->host_port, + ic->sar->virthost, + ic->sar->host_port); + ic->sar = sar; + ic->server = s; + } + } + } + + /* Ok now we want to set up a server_hostname if the user was + * silly enough to forget one. + * XXX: This is silly we should just crash and burn. + */ + if (!s->server_hostname) { + if (has_default_vhost_addr) + s->server_hostname = main_s->server_hostname; + else if (!s->addrs) { + /* what else can we do? at this point this + * vhost has no configured name, probably + * because they used DNS in the VirtualHost + * statement. It's disabled anyhow by the + * host matching code. -djg + */ + s->server_hostname = + ap_pstrdup(p, + "bogus_host_without_forward_dns"); + } else { + struct hostent *h; + char hostnamebuf[MAXHOSTNAMELEN]; + + if (!getnameinfo( + (struct sockaddr *)&s->addrs->host_addr, #ifndef SIN6_LEN - SA_LEN((struct sockaddr *)&s->addrs->host_addr), -#else - s->addrs->host_addr.ss_len, + SA_LEN((struct sockaddr *)&s->addrs->host_addr), +#else + s->addrs->host_addr.ss_len, #endif - hostnamebuf, sizeof(hostnamebuf), - NULL, 0, 0)) { - s->server_hostname = ap_pstrdup(p, hostnamebuf); - } - else { - /* again, what can we do? They didn't specify a - ServerName, and their DNS isn't working. -djg */ - getnameinfo((struct sockaddr *)&s->addrs->host_addr, + hostnamebuf, sizeof(hostnamebuf), + NULL, 0, 0)) + s->server_hostname = + ap_pstrdup(p, hostnamebuf); + else { + /* again, what can we do? They didn't + * specify a ServerName, and their DNS + * isn't working. -djg */ + getnameinfo((struct sockaddr *) + &s->addrs->host_addr, #ifndef SIN6_LEN - SA_LEN((struct sockaddr *)&s->addrs->host_addr), -#else - s->addrs->host_addr.ss_len, + SA_LEN((struct sockaddr *) + &s->addrs->host_addr), +#else + s->addrs->host_addr.ss_len, #endif - hostnamebuf, sizeof(hostnamebuf), - NULL, 0, NI_NUMERICHOST); - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s, - "Failed to resolve server name " - "for %s (check DNS) -- or specify an explicit " - "ServerName", hostnamebuf); - s->server_hostname = - ap_pstrdup(p, "bogus_host_without_reverse_dns"); + hostnamebuf, + sizeof(hostnamebuf), + NULL, 0, NI_NUMERICHOST); + ap_log_error(APLOG_MARK, + APLOG_NOERRNO|APLOG_ERR, main_s, + "Failed to resolve server name " + "for %s (check DNS) -- or specify " + "an explicit ServerName", + hostnamebuf); + s->server_hostname = + ap_pstrdup(p, + "bogus_host_without_reverse_dns"); + } + } } - } } - } - /* now go through and delete any NameVirtualHosts that didn't have any - * hosts associated with them. Lamers. - */ - for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { - remove_unused_name_vhosts(main_s, &iphash_table[i]); - } - remove_unused_name_vhosts(main_s, &default_list); + /* now go through and delete any NameVirtualHosts that didn't have any + * hosts associated with them. Lamers. + */ + for (i = 0; i < IPHASH_TABLE_SIZE; ++i) + remove_unused_name_vhosts(main_s, &iphash_table[i]); + remove_unused_name_vhosts(main_s, &default_list); #ifdef IPHASH_STATISTICS - dump_iphash_statistics(main_s); + dump_iphash_statistics(main_s); #endif - if (ap_dump_settings) { - dump_vhost_config(stderr); - } + if (ap_dump_settings) + dump_vhost_config(stderr); } @@ -827,113 +853,113 @@ API_EXPORT(void) ap_fini_vhost_config(pool *p, server_rec *main_s) * Instead we just check for filesystem metacharacters: directory * separators / and \ and sequences of more than one dot. */ -static void fix_hostname(request_rec *r) +static void +fix_hostname(request_rec *r) { - char *host = ap_palloc(r->pool, strlen(r->hostname) + 1); - const char *src; - char *dst; - const char *u = NULL, *v = NULL; - - /* check and copy the host part */ - u = src = r->hostname; - - dst = host; - if (*u == '[') { /* IPv6 numeral address in brackets */ - v = strchr(u, ']'); - if (v == NULL) { - /* missing closing bracket */ - goto bad; - } - if (v == (u + 1)) { - /* bad empty address */ - goto bad; - } - for (src = u+1; src < v; src++) /* copy IPv6 adress */ - *dst = *src; - v++; - if (*v == ':') { - v++; - while (*v) { /* check if portnum is correct */ - if (!ap_isdigit(*v++)) - goto bad; - } - } - } else { - while (*src) { - if (*src == '.') { - *dst++ = *src++; - if (*src == '.') - goto bad; - else - continue; - } - if (*src == '/' || *src == '\\') { - goto bad; - } - if (*src == ':') { - /* sheck the port part */ - while (*++src) { - if (!ap_isdigit(*src)) { + char *host = ap_palloc(r->pool, strlen(r->hostname) + 1); + const char *src; + char *dst; + const char *u = NULL, *v = NULL; + + /* check and copy the host part */ + u = src = r->hostname; + + dst = host; + if (*u == '[') { /* IPv6 numeral address in brackets */ + v = strchr(u, ']'); + if (v == NULL) + /* missing closing bracket */ + goto bad; + + if (v == (u + 1)) + /* bad empty address */ goto bad; - } + + for (src = u+1; src < v; src++) /* copy IPv6 adress */ + *dst = *src; + v++; + if (*v == ':') { + v++; + while (*v) { /* check if portnum is correct */ + if (!ap_isdigit(*v++)) + goto bad; + } } - if (src[-1] == ':') - goto bad; - else - break; - } - *dst++ = *src++; - } - } - /* strip trailing gubbins */ - if (dst > host && dst[-1] == '.') { - dst[-1] = '\0'; - } else { - dst[0] = '\0'; - } - - r->hostname = host; - return; + } else { + while (*src) { + if (*src == '.') { + *dst++ = *src++; + if (*src == '.') + goto bad; + else + continue; + } + if (*src == '/' || *src == '\\') + goto bad; + if (*src == ':') { + /* sheck the port part */ + while (*++src) { + if (!ap_isdigit(*src)) + goto bad; + } + if (src[-1] == ':') + goto bad; + else + break; + } + *dst++ = *src++; + } + } + /* strip trailing gubbins */ + if (dst > host && dst[-1] == '.') + dst[-1] = '\0'; + else + dst[0] = '\0'; + + r->hostname = host; + return; bad: - r->status = HTTP_BAD_REQUEST; - ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "Client sent malformed Host header <<%s>>",u); - return; + r->status = HTTP_BAD_REQUEST; + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, + "Client sent malformed Host header <<%s>>",u); + return; } /* return 1 if host matches ServerName or ServerAliases */ -static int matches_aliases(server_rec *s, const char *host) +static int +matches_aliases(server_rec *s, const char *host) { - int i; - array_header *names; - - /* match ServerName */ - if (!strcasecmp(host, s->server_hostname)) { - return 1; - } - - /* search all the aliases from ServerAlias directive */ - names = s->names; - if (names) { - char **name = (char **) names->elts; - for (i = 0; i < names->nelts; ++i) { - if(!name[i]) continue; - if (!strcasecmp(host, name[i])) + int i; + array_header *names; + + /* match ServerName */ + if (!strcasecmp(host, s->server_hostname)) return 1; + + /* search all the aliases from ServerAlias directive */ + names = s->names; + if (names) { + char **name = (char **) names->elts; + for (i = 0; i < names->nelts; ++i) { + if(!name[i]) + continue; + if (!strcasecmp(host, name[i])) + return 1; + } } - } - names = s->wild_names; - if (names) { - char **name = (char **) names->elts; - for (i = 0; i < names->nelts; ++i) { - if(!name[i]) continue; - if (!ap_strcasecmp_match(host, name[i])) - return 1; + names = s->wild_names; + if (names) { + char **name = (char **) names->elts; + for (i = 0; i < names->nelts; ++i) { + if(!name[i]) + continue; + if (!ap_strcasecmp_match(host, name[i])) + return 1; + } } - } - return 0; + return 0; } @@ -944,243 +970,241 @@ static int matches_aliases(server_rec *s, const char *host) * we just call it a match. But here we require the host:port to match * the ServerName and/or ServerAliases. */ -API_EXPORT(int) ap_matches_request_vhost(request_rec *r, const char *host, - unsigned port) +API_EXPORT(int) +ap_matches_request_vhost(request_rec *r, const char *host, unsigned port) { - server_rec *s; - server_addr_rec *sar; - - s = r->server; - - /* search all the <VirtualHost> values */ - /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing - * consider: - * - * NameVirtualHost 10.1.1.1 - * <VirtualHost 10.1.1.1> - * ServerName v1 - * </VirtualHost> - * <VirtualHost 10.1.1.1> - * ServerName v2 - * </VirtualHost> - * - * Suppose r->server is v2, and we're asked to match "10.1.1.1". We'll say - * "yup it's v2", when really it isn't... if a request came in for 10.1.1.1 - * it would really go to v1. - */ - for (sar = s->addrs; sar; sar = sar->next) { - if ((sar->host_port == 0 || port == sar->host_port) - && !strcasecmp(host, sar->virthost)) { - return 1; - } - } + server_rec *s; + server_addr_rec *sar; + + s = r->server; + + /* search all the <VirtualHost> values */ + /* XXX: If this is a NameVirtualHost then we may not be doing the + * Right Thing, consider: + * + * NameVirtualHost 10.1.1.1 + * <VirtualHost 10.1.1.1> + * ServerName v1 + * </VirtualHost> + * <VirtualHost 10.1.1.1> + * ServerName v2 + * </VirtualHost> + * + * Suppose r->server is v2, and we're asked to match "10.1.1.1". + * We'll say "yup it's v2", when really it isn't... if a request + * came in for 10.1.1.1 it would really go to v1. + */ + for (sar = s->addrs; sar; sar = sar->next) + if ((sar->host_port == 0 || port == sar->host_port) + && !strcasecmp(host, sar->virthost)) + return 1; - /* the Port has to match now, because the rest don't have ports associated - * with them. */ - if (port != s->port) { - return 0; - } + /* the Port has to match now, because the rest don't have ports + * associated with them. + */ + if (port != s->port) + return 0; - return matches_aliases(s, host); + return matches_aliases(s, host); } -static void check_hostalias(request_rec *r) +static void +check_hostalias(request_rec *r) { - /* - * Even if the request has a Host: header containing a port we ignore - * that port. We always use the physical port of the socket. There - * are a few reasons for this: - * - * - the default of 80 or 443 for SSL is easier to handle this way - * - there is less of a possibility of a security problem - * - it simplifies the data structure - * - the client may have no idea that a proxy somewhere along the way - * translated the request to another ip:port - * - except for the addresses from the VirtualHost line, none of the other - * names we'll match have ports associated with them - */ - const char *host = r->hostname; - unsigned port; - server_rec *s; - server_rec *last_s; - name_chain *src; - - switch (r->connection->local_addr.ss_family) { - case AF_INET: - port = ntohs(((struct sockaddr_in *) + /* + * Even if the request has a Host: header containing a port we ignore + * that port. We always use the physical port of the socket. There + * are a few reasons for this: + * + * - the default of 80 or 443 for SSL is easier to handle this way + * - there is less of a possibility of a security problem + * - it simplifies the data structure + * - the client may have no idea that a proxy somewhere along the way + * translated the request to another ip:port + * - except for the addresses from the VirtualHost line, none of the + * other names we'll match have ports associated with them + */ + const char *host = r->hostname; + unsigned port; + server_rec *s; + server_rec *last_s; + name_chain *src; + + switch (r->connection->local_addr.ss_family) { + case AF_INET: + port = ntohs(((struct sockaddr_in *) &r->connection->local_addr)->sin_port); - break; - case AF_INET6: - port = ntohs(((struct sockaddr_in6 *) + break; + case AF_INET6: + port = ntohs(((struct sockaddr_in6 *) &r->connection->local_addr)->sin6_port); - break; - default: - port = 0; /*XXX*/ - } - last_s = NULL; - - /* Recall that the name_chain is a list of server_addr_recs, some of - * whose ports may not match. Also each server may appear more than - * once in the chain -- specifically, it will appear once for each - * address from its VirtualHost line which matched. We only want to - * do the full ServerName/ServerAlias comparisons once for each - * server, fortunately we know that all the VirtualHost addresses for - * a single server are adjacent to each other. - */ - - for (src = r->connection->vhost_lookup_data; src; src = src->next) { - server_addr_rec *sar; - - /* We only consider addresses on the name_chain which have a matching - * port - */ - sar = src->sar; - if (sar->host_port != 0 && port != sar->host_port) { - continue; + break; + default: + port = 0; /*XXX*/ } + last_s = NULL; + + /* Recall that the name_chain is a list of server_addr_recs, some of + * whose ports may not match. Also each server may appear more than + * once in the chain -- specifically, it will appear once for each + * address from its VirtualHost line which matched. We only want to + * do the full ServerName/ServerAlias comparisons once for each + * server, fortunately we know that all the VirtualHost addresses for + * a single server are adjacent to each other. + */ - s = src->server; + for (src = r->connection->vhost_lookup_data; src; src = src->next) { + server_addr_rec *sar; - /* does it match the virthost from the sar? */ - if (!strcasecmp(host, sar->virthost)) { - goto found; - } + /* We only consider addresses on the name_chain which have a + * matching port + */ + sar = src->sar; + if (sar->host_port != 0 && port != sar->host_port) + continue; - if (s == last_s) { - /* we've already done ServerName and ServerAlias checks for this - * vhost - */ - continue; - } - last_s = s; + s = src->server; + + /* does it match the virthost from the sar? */ + if (!strcasecmp(host, sar->virthost)) + goto found; + + if (s == last_s) + /* we've already done ServerName and ServerAlias checks + * for this vhost + */ + continue; - if (matches_aliases(s, host)) { - goto found; + last_s = s; + + if (matches_aliases(s, host)) + goto found; } - } - return; + return; found: - /* s is the first matching server, we're done */ - r->server = r->connection->server = s; + /* s is the first matching server, we're done */ + r->server = r->connection->server = s; } -static void check_serverpath(request_rec *r) +static void +check_serverpath(request_rec *r) { - server_rec *s; - server_rec *last_s; - name_chain *src; - unsigned port; - - switch (r->connection->local_addr.ss_family) { - case AF_INET: - port = ntohs(((struct sockaddr_in *) + server_rec *s; + server_rec *last_s; + name_chain *src; + unsigned port; + + switch (r->connection->local_addr.ss_family) { + case AF_INET: + port = ntohs(((struct sockaddr_in *) &r->connection->local_addr)->sin_port); - break; - case AF_INET6: - port = ntohs(((struct sockaddr_in6 *) + break; + case AF_INET6: + port = ntohs(((struct sockaddr_in6 *) &r->connection->local_addr)->sin6_port); - break; - default: - port = 0; /*XXX*/ - } - - /* - * This is in conjunction with the ServerPath code in http_core, so we - * get the right host attached to a non- Host-sending request. - * - * See the comment in check_hostalias about how each vhost can be - * listed multiple times. - */ - - last_s = NULL; - for (src = r->connection->vhost_lookup_data; src; src = src->next) { - /* We only consider addresses on the name_chain which have a matching - * port - */ - if (src->sar->host_port != 0 && port != src->sar->host_port) { - continue; + break; + default: + port = 0; /*XXX*/ } - s = src->server; - if (s == last_s) { - continue; - } - last_s = s; - - if (s->path && !strncmp(r->uri, s->path, s->pathlen) && - (s->path[s->pathlen - 1] == '/' || - r->uri[s->pathlen] == '/' || - r->uri[s->pathlen] == '\0')) { - r->server = r->connection->server = s; - return; + /* + * This is in conjunction with the ServerPath code in http_core, so we + * get the right host attached to a non- Host-sending request. + * + * See the comment in check_hostalias about how each vhost can be + * listed multiple times. + */ + + last_s = NULL; + for (src = r->connection->vhost_lookup_data; src; src = src->next) { + /* We only consider addresses on the name_chain which have a + * matching port + */ + if (src->sar->host_port != 0 && port != src->sar->host_port) + continue; + + s = src->server; + if (s == last_s) + continue; + last_s = s; + + if (s->path && !strncmp(r->uri, s->path, s->pathlen) && + (s->path[s->pathlen - 1] == '/' || + r->uri[s->pathlen] == '/' || + r->uri[s->pathlen] == '\0')) { + r->server = r->connection->server = s; + return; + } } - } } -API_EXPORT(void) ap_update_vhost_from_headers(request_rec *r) +API_EXPORT(void) +ap_update_vhost_from_headers(request_rec *r) { - /* must set this for HTTP/1.1 support */ - if (r->hostname || (r->hostname = ap_table_get(r->headers_in, "Host"))) { - fix_hostname(r); - if (r->status != HTTP_OK) - return; - } - /* check if we tucked away a name_chain */ - if (r->connection->vhost_lookup_data) { - if (r->hostname) - check_hostalias(r); - else - check_serverpath(r); - } + /* must set this for HTTP/1.1 support */ + if (r->hostname || + (r->hostname = ap_table_get(r->headers_in, "Host"))) { + fix_hostname(r); + if (r->status != HTTP_OK) + return; + } + /* check if we tucked away a name_chain */ + if (r->connection->vhost_lookup_data) { + if (r->hostname) + check_hostalias(r); + else + check_serverpath(r); + } } /* Called for a new connection which has a known local_addr. Note that the * new connection is assumed to have conn->server == main server. */ -API_EXPORT(void) ap_update_vhost_given_ip(conn_rec *conn) +API_EXPORT(void) +ap_update_vhost_given_ip(conn_rec *conn) { - ipaddr_chain *trav; - char portbuf[NI_MAXSERV]; - unsigned port; + ipaddr_chain *trav; + char portbuf[NI_MAXSERV]; + unsigned port; - if (getnameinfo((struct sockaddr *)&conn->local_addr, + if (getnameinfo((struct sockaddr *)&conn->local_addr, #ifndef SIN6_LEN - SA_LEN((struct sockaddr *)&conn->local_addr), -#else - conn->local_addr.ss_len, + SA_LEN((struct sockaddr *)&conn->local_addr), +#else + conn->local_addr.ss_len, #endif - NULL, 0, portbuf, sizeof(portbuf), NI_NUMERICSERV) != 0) { - goto fail; - } - port = atoi(portbuf); - - /* scan the hash table for an exact match first */ - trav = find_ipaddr((struct sockaddr *)&conn->local_addr); - if (trav) { - /* save the name_chain for later in case this is a name-vhost */ - conn->vhost_lookup_data = trav->names; - conn->server = trav->server; - return; - } - - /* maybe there's a default server or wildcard name-based vhost - * matching this port - */ - trav = find_default_server(port); - if (trav) { - conn->vhost_lookup_data = trav->names; - conn->server = trav->server; - return; - } + NULL, 0, portbuf, sizeof(portbuf), NI_NUMERICSERV) != 0) + goto fail; + + port = atoi(portbuf); + + /* scan the hash table for an exact match first */ + trav = find_ipaddr((struct sockaddr *)&conn->local_addr); + if (trav) { + /* save the name_chain for later in case this is a name-vhost */ + conn->vhost_lookup_data = trav->names; + conn->server = trav->server; + return; + } + + /* maybe there's a default server or wildcard name-based vhost + * matching this port + */ + trav = find_default_server(port); + if (trav) { + conn->vhost_lookup_data = trav->names; + conn->server = trav->server; + return; + } fail: - /* otherwise we're stuck with just the main server - * and no name-based vhosts - */ - conn->vhost_lookup_data = NULL; + /* otherwise we're stuck with just the main server + * and no name-based vhosts + */ + conn->vhost_lookup_data = NULL; } |