]> git.pld-linux.org Git - packages/boa.git/commitdiff
- another fixes for IPv6
authorkravietz <kravietz@pld-linux.org>
Sun, 10 Sep 2000 02:59:25 +0000 (02:59 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    boa-PLD.patch -> 1.9

boa-PLD.patch

index 2737525c75ac16e649d666ac890f01474c5acc3d..40950178633afffed550abfa50f7c82f129a5350 100644 (file)
@@ -55,6 +55,670 @@ diff -bruN boa-0.94.8.2/boa.conf boa-0.94.8.2.pld/boa.conf
 -ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
 +ScriptAlias /cgi-bin/ /home/httpd/cgi-bin/
  
+diff -bruN boa-0.94.8.2/request.c boa-0.94.8.2.pld/request.c
+--- boa-0.94.8.2/request.c     Thu Jan  1 01:00:00 1970
++++ boa-0.94.8.2.pld/request.c Sun Sep 10 04:58:44 2000
+@@ -0,0 +1,660 @@
++/*
++ *  Boa, an http server
++ *  Copyright (C) 1995 Paul Phillips <psp@well.com>
++ *  Some changes Copyright (C) 1996,97 Larry Doolittle <ldoolitt@jlab.org>
++ *  Some changes Copyright (C) 1996-99 Jon Nelson <jnelson@boa.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 1, or (at your option)
++ *  any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/* $Id$*/
++
++#include "boa.h"
++#include <netinet/tcp.h>
++#include <arpa/inet.h>          /* inet_ntoa */
++#include <stddef.h>
++
++int sockbufsize = SOCKETBUF_SIZE;
++int total_connections;
++
++/*
++ * Name: new_request
++ * Description: Obtains a request struct off the free list, or if the
++ * free list is empty, allocates memory
++ *
++ * Return value: pointer to initialized request
++ */
++
++request *new_request(void)
++{
++    request *req;
++
++    if (request_free) {
++        req = request_free;     /* first on free list */
++        dequeue(&request_free, request_free); /* dequeue the head */
++    } else {
++        req = (request *) malloc(sizeof (request));
++        if (!req) {
++            log_error_mesg(__FILE__, __LINE__,
++                           "out of memory allocating for new request structure");
++            exit(errno);
++        }
++    }
++
++    memset(req, 0, offsetof(request, buffer) + 1);
++
++    return req;
++}
++
++
++/*
++ * Name: get_request
++ *
++ * Description: Polls the server socket for a request.  If one exists,
++ * does some basic initialization and adds it to the ready queue;.
++ */
++
++void get_request(int server_s)
++{
++    int fd;                     /* socket */
++    struct SOCKADDR remote_addr; /* address */
++    int remote_addrlen = sizeof (struct sockaddr_in);
++    request *conn;              /* connection */
++    int len;
++    static int system_bufsize = 0; /* Default size of SNDBUF given by system */
++
++    remote_addr.S_FAMILY = 0xdead;
++    fd = accept(server_s, (struct sockaddr *) &remote_addr,
++                &remote_addrlen);
++
++    if (fd == -1) {
++        if (errno != EAGAIN && errno != EWOULDBLOCK) /* no requests */
++            log_error_mesg(__FILE__, __LINE__, "accept");
++        return;
++    }
++#ifdef DEBUGNONINET
++    /* This shows up due to race conditions in some Linux kernels
++       when the client closes the socket sometime between
++       the select() and accept() syscalls.
++       Code and description by Larry Doolittle <ldoolitt@boa.org>
++     */
++#define HEX(x) (((x)>9)?(('a'-10)+(x)):('0'+(x)))
++    if (remote_addr.sin_family != AF_INET) {
++        struct sockaddr *bogus = (struct sockaddr *) &remote_addr;
++        char *ap, ablock[44];
++        int i;
++        close(fd);
++        log_error_time();
++        for (ap = ablock, i = 0; i < remote_addrlen && i < 14; i++) {
++            *ap++ = ' ';
++            *ap++ = HEX((bogus->sa_data[i] >> 4) & 0x0f);
++            *ap++ = HEX(bogus->sa_data[i] & 0x0f);
++        }
++        *ap = '\0';
++        fprintf(stderr, "non-INET connection attempt: socket %d, "
++                "sa_family = %hu, sa_data[%d] = %s\n",
++                fd, bogus->sa_family, remote_addrlen, ablock);
++        return;
++    }
++#endif
++
++/* XXX Either delete this, or document why it's needed */
++/* Pointed out 3-Oct-1999 by Paul Saab <paul@mu.org> */
++#ifdef REUSE_EACH_CLIENT_CONNECTION_SOCKET
++    if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt,
++                    sizeof (sock_opt))) == -1) {
++        log_error_mesg(__FILE__, __LINE__,
++                       "setsockopt: unable to set SO_REUSEADDR");
++        exit(errno);
++    }
++#endif
++
++    conn = new_request();
++    conn->fd = fd;
++    conn->status = READ_HEADER;
++    conn->header_line = conn->client_stream;
++    conn->time_last = current_time;
++    conn->kacount = ka_max;
++
++    /* fill in local_ip_addr if relevant */
++    if (virtualhost) {
++        struct SOCKADDR salocal;
++        int dummy = sizeof (salocal);
++        if (getsockname(conn->fd, (struct sockaddr *) &salocal, &dummy) ==
++            -1) {
++            log_error_mesg(__FILE__, __LINE__, "getsockname");
++            exit(errno);
++        }
++        ascii_sockaddr(&salocal, conn->local_ip_addr, NI_MAXHOST);
++    }
++
++    /* nonblocking socket */
++    if (fcntl(conn->fd, F_SETFL, NOBLOCK) == -1)
++        log_error_mesg(__FILE__, __LINE__,
++                       "fcntl: unable to set new socket to non-block");
++
++    /* set close on exec to true */
++    if (fcntl(conn->fd, F_SETFD, 1) == -1)
++        log_error_mesg(__FILE__, __LINE__,
++                       "fctnl: unable to set close-on-exec for new socket");
++
++    /* Increase buffer size if we have to.
++     * Only ask the system the buffer size on the first request,
++     * and assume all subsequent sockets have the same size.
++     */
++    if (system_bufsize == 0) {
++        len = sizeof (system_bufsize);
++        if (getsockopt
++            (conn->fd, SOL_SOCKET, SO_SNDBUF, &system_bufsize, &len) == 0
++            && len == sizeof (system_bufsize)) {
++            /*
++               fprintf(stderr, "%sgetsockopt reports SNDBUF %d\n",
++               get_commonlog_time(), system_bufsize);
++             */
++            ;
++        } else {
++            log_error_mesg(__FILE__, __LINE__, "getsockopt(SNDBUF)");
++            system_bufsize = 1;
++        }
++    }
++    if (system_bufsize < sockbufsize) {
++        if (setsockopt
++            (conn->fd, SOL_SOCKET, SO_SNDBUF, (void *) &sockbufsize,
++             sizeof (sockbufsize)) == -1) {
++            log_error_mesg(__FILE__, __LINE__,
++                           "setsockopt: unable to set socket buffer size");
++#ifdef DIE_ON_ERROR_TUNING_SNDBUF
++            exit(errno);
++#endif
++        }
++    }
++
++    /* for log file and possible use by CGI programs */
++    ascii_sockaddr(&remote_addr, conn->remote_ip_addr, NI_MAXHOST);
++
++    /* for possible use by CGI programs */
++    /* the structure doesn't contain port
++          conn->remote_port = ntohs(remote_addr.sin_port);
++     */
++    conn->remote_port = 0;
++
++    status.requests++;
++
++#ifdef USE_TCPNODELAY
++    /* Thanks to Jef Poskanzer <jef@acme.com> for this tweak */
++    {
++        int one = 1;
++        if (setsockopt(conn->fd, IPPROTO_TCP, TCP_NODELAY,
++                       (void *) &one, sizeof (one)) == -1) {
++            log_error_mesg(__FILE__, __LINE__,
++                           "setsockopt: unable to set TCP_NODELAY");
++            exit(errno);
++        }
++
++    }
++#endif
++
++    total_connections++;
++    enqueue(&request_ready, conn);
++}
++
++
++/*
++ * Name: free_request
++ *
++ * Description: Deallocates memory for a finished request and closes
++ * down socket.
++ */
++
++static void free_request(request ** list_head_addr, request * req)
++{
++    /* free_request should *never* get called by anything but
++       process_requests */
++
++    if (req->buffer_end && req->status != DEAD) {
++        req->status = DONE;
++        return;
++    }
++    /* put request on the free list */
++    dequeue(list_head_addr, req); /* dequeue from ready or block list */
++
++    FD_CLR(req->fd, &block_read_fdset);
++    FD_CLR(req->fd, &block_write_fdset);
++    FD_CLR(req->data_fd, &block_read_fdset);
++    FD_CLR(req->post_data_fd, &block_write_fdset);
++
++    if (req->logline)           /* access log */
++        log_access(req);
++
++    if (req->mmap_entry_var)
++        release_mmap(req->mmap_entry_var);
++    else if (req->data_mem)
++        munmap(req->data_mem, req->filesize);
++
++    if (req->data_fd)
++        close(req->data_fd);
++
++    if (req->response_status >= 400)
++        status.errors++;
++
++    if (req->cgi_env) {
++        int i;
++        for (i = COMMON_CGI_COUNT; i < req->cgi_env_index; ++i)
++            if (req->cgi_env[i])
++                free(req->cgi_env[i]);
++        free(req->cgi_env);
++    }
++    if (req->pathname)
++        free(req->pathname);
++    if (req->path_info)
++        free(req->path_info);
++    if (req->path_translated)
++        free(req->path_translated);
++    if (req->script_name)
++        free(req->script_name);
++    if (req->query_string)
++        free(req->query_string);
++
++    if ((req->keepalive == KA_ACTIVE) &&
++        (req->response_status < 500) && req->kacount > 0) {
++
++        request *conn = new_request();
++        conn->fd = req->fd;
++        conn->status = READ_HEADER;
++        conn->header_line = conn->client_stream;
++        conn->kacount = req->kacount - 1;
++
++        /* close enough and we avoid a call to time(NULL) */
++        conn->time_last = req->time_last;
++
++        /* for log file and possible use by CGI programs */
++        memcpy(conn->remote_ip_addr, req->remote_ip_addr, NI_MAXHOST);
++
++        /* for possible use by CGI programs */
++        conn->remote_port = req->remote_port;
++
++        status.requests++;
++
++        {
++            int bytes_to_move;
++
++            /* we haven't parsed beyond req->parse_pos, so... */
++            bytes_to_move = req->client_stream_pos - req->parse_pos;
++
++            if (bytes_to_move) {
++                memcpy(conn->client_stream,
++                       req->client_stream + req->parse_pos, bytes_to_move);
++                conn->client_stream_pos = bytes_to_move;
++                FD_CLR(conn->fd, &block_read_fdset);
++                enqueue(&request_ready, conn);
++            } else {
++                FD_SET(conn->fd, &block_read_fdset);
++                enqueue(&request_block, conn);
++            }
++        }
++    } else {
++        close(req->fd);
++        total_connections--;
++    }
++
++    enqueue(&request_free, req);
++
++    return;
++}
++
++/*
++ * Name: process_requests
++ *
++ * Description: Iterates through the ready queue, passing each request
++ * to the appropriate handler for processing.  It monitors the
++ * return value from handler functions, all of which return -1
++ * to indicate a block, 0 on completion and 1 to remain on the
++ * ready list for more procesing.
++ */
++
++void process_requests(void)
++{
++    int retval = 0;
++    request *current, *trailer;
++
++    current = request_ready;
++
++    while (current) {
++        time(&current_time);
++        if (current->buffer_end && /* there is data in the buffer */
++            current->status != DEAD && current->status != DONE) {
++            retval = req_flush(current);
++            /*
++             * retval can be -2=error, -1=blocked, or bytes left
++             */
++            if (retval == -2) { /* error */
++                current->status = DEAD;
++                retval = 0;
++            } else if (retval >= 0) {
++                /* notice the >= which is different from below?
++                   Here, we may just be flushing headers.
++                   We don't want to return 0 because we are not DONE
++                   or DEAD */
++
++                retval = 1;
++            }
++        } else {
++            switch (current->status) {
++            case READ_HEADER:
++            case ONE_CR:
++            case ONE_LF:
++            case TWO_CR:
++                retval = read_header(current);
++                break;
++            case BODY_READ:
++                retval = read_body(current);
++                break;
++            case BODY_WRITE:
++                retval = write_body(current);
++                break;
++            case WRITE:
++                retval = process_get(current);
++                break;
++            case PIPE_READ:
++                retval = read_from_pipe(current);
++                break;
++            case PIPE_WRITE:
++                retval = write_from_pipe(current);
++                break;
++            case DONE:
++                /* a non-status that will terminate the request */
++                retval = req_flush(current);
++                /*
++                 * retval can be -2=error, -1=blocked, or bytes left
++                 */
++                if (retval == -2) { /* error */
++                    current->status = DEAD;
++                    retval = 0;
++                } else if (retval > 0) {
++                    retval = 1;
++                }
++                break;
++            case DEAD:
++                retval = 0;
++                current->buffer_end = 0;
++                SQUASH_KA(current);
++                break;
++            default:
++                retval = 0;
++                fprintf(stderr, "Unknown status (%d), "
++                        "closing!\n", current->status);
++                current->status = DEAD;
++                break;
++            }
++
++        }
++
++        if (lame_duck_mode)
++            SQUASH_KA(current);
++
++        switch (retval) {
++        case -1:               /* request blocked */
++            trailer = current;
++            current = current->next;
++            block_request(trailer);
++            break;
++        case 0:                /* request complete */
++            current->time_last = current_time;
++            trailer = current;
++            current = current->next;
++            free_request(&request_ready, trailer);
++            break;
++        case 1:                /* more to do */
++            current->time_last = current_time;
++            current = current->next;
++            break;
++        default:
++            log_error_time();
++            fprintf(stderr, "Unknown retval in process.c - "
++                    "Status: %d, retval: %d\n", current->status, retval);
++            current = current->next;
++            break;
++        }
++    }
++}
++
++/*
++ * Name: process_logline
++ *
++ * Description: This is called with the first req->header_line received
++ * by a request, called "logline" because it is logged to a file.
++ * It is parsed to determine request type and method, then passed to
++ * translate_uri for further parsing.  Also sets up CGI environment if
++ * needed.
++ */
++
++int process_logline(request * req)
++{
++    char *stop, *stop2;
++    static char *SIMPLE_HTTP_VERSION = "HTTP/0.9";
++
++    req->logline = req->client_stream;
++    if (!memcmp(req->logline, "GET ", 4))
++        req->method = M_GET;
++    else if (!memcmp(req->logline, "HEAD ", 5))
++        /* head is just get w/no body */
++        req->method = M_HEAD;
++    else if (!memcmp(req->logline, "POST ", 5))
++        req->method = M_POST;
++    else {
++        log_error_time();
++        fprintf(stderr, "malformed request: \"%s\"\n", req->logline);
++        send_r_bad_request(req);
++        return 0;
++    }
++
++    /* Guaranteed to find ' ' since we matched a method above */
++    stop = req->logline + 3;
++    if (*stop != ' ')
++        ++stop;
++
++    /* scan to start of non-whitespace */
++    while (*(++stop) == ' ');
++
++    stop2 = stop;
++
++    /* scan to end of non-whitespace */
++    while (*stop2 != '\0' && *stop2 != ' ')
++        ++stop2;
++
++    if (stop2 - stop > MAX_HEADER_LENGTH) {
++        log_error_time();
++        fprintf(stderr, "URI too long %d: \"%s\"\n", MAX_HEADER_LENGTH,
++                req->logline);
++        send_r_bad_request(req);
++        return 0;
++    }
++    memcpy(req->request_uri, stop, stop2 - stop);
++    req->request_uri[stop2 - stop] = '\0';
++
++    if (*stop2 == ' ') {
++        /* if found, we should get an HTTP/x.x */
++        int p1, p2;
++
++        if (sscanf(++stop2, "HTTP/%d.%d", &p1, &p2) == 2 && p1 >= 1) {
++            req->http_version = stop2;
++            req->simple = 0;
++        } else {
++            log_error_time();
++            fprintf(stderr, "bogus HTTP version: \"%s\"\n", stop2);
++            send_r_bad_request(req);
++            return 0;
++        }
++
++    } else {
++        req->http_version = SIMPLE_HTTP_VERSION;
++        req->simple = 1;
++    }
++
++    if (req->method == M_HEAD && req->simple) {
++        send_r_bad_request(req);
++        return 0;
++    }
++    if (translate_uri(req) == 0) { /* unescape, parse uri */
++        SQUASH_KA(req);
++        return 0;               /* failure, close down */
++    }
++    if (req->is_cgi)
++        create_env(req);
++    return 1;
++}
++
++/*
++ * Name: process_header_end
++ *
++ * Description: takes a request and performs some final checking before
++ * init_cgi or init_get
++ * Returns 0 for error or NPH, or 1 for success
++ */
++
++int process_header_end(request * req)
++{
++    if (!req->logline) {
++        send_r_error(req);
++        return 0;
++    }
++    if (req->method == M_POST) {
++        char *tmpfilep = tmpnam(NULL);
++
++        if (!tmpfilep) {
++            boa_perror(req, "tmpnam");
++            return 0;
++        }
++        /* open temp file for post data */
++        if ((req->post_data_fd = open(tmpfilep, O_RDWR | O_CREAT /* read-write, create */
++                                      | O_EXCL, S_IRUSR /* don't overwrite, u+r */
++                                      & ~S_IWUSR & ~S_IEXEC /* u-wx */
++                                      & ~S_IRWXG /* g-rwx */
++                                      & ~S_IRWXO)) == -1) { /* o-rwx */
++            boa_perror(req, "tmpfile open");
++            return 0;
++        }
++#ifndef REALLY_FASCIST_LOGGING
++        unlink(tmpfilep);
++#endif
++        return 1;
++    }
++    if (req->is_cgi) {
++        return init_cgi(req);
++    }
++    req->status = WRITE;
++    return init_get(req);       /* get and head */
++}
++
++/*
++ * Name: process_option_line
++ *
++ * Description: Parses the contents of req->header_line and takes
++ * appropriate action.
++ */
++
++void process_option_line(request * req)
++{
++    char c, *value, *line = req->header_line;
++
++    /* Start by aggressively hacking the in-place copy of the header line */
++
++#ifdef FASCIST_LOGGING
++    log_error_time();
++    fprintf(stderr, "%s:%d - Parsing \"%s\"\n", __FILE__, __LINE__, line);
++#endif
++
++    value = strchr(line, ':');
++    if (value == NULL)
++        return;
++    *value++ = '\0';            /* overwrite the : */
++    to_upper(line);             /* header types are case-insensitive */
++    while ((c = *value) && (c == ' ' || c == '\t'))
++        value++;
++
++    if (!memcmp(line, "IF_MODIFIED_SINCE", 18) && !req->if_modified_since)
++        req->if_modified_since = value;
++
++    else if (!memcmp(line, "CONTENT_TYPE", 13) && !req->content_type)
++        req->content_type = value;
++
++    else if (!memcmp(line, "CONTENT_LENGTH", 15) && !req->content_length)
++        req->content_length = value;
++
++    else if (!memcmp(line, "CONNECTION", 11) &&
++             ka_max && req->keepalive != KA_STOPPED) {
++        req->keepalive = (!strncasecmp(value, "Keep-Alive", 10) ?
++                          KA_ACTIVE : KA_STOPPED);
++    }
++    /* #ifdef ACCEPT_ON */
++    else if (!memcmp(line, "ACCEPT", 7))
++        add_accept_header(req, value);
++    /* #endif */
++
++    /* Need agent and referer for logs */
++    else if (!memcmp(line, "REFERER", 8))
++        req->header_referer = value;
++    else if (!memcmp(line, "USER_AGENT", 11))
++        req->header_user_agent = value;
++
++    /* Silently ignore unknown header lines unless is_cgi */
++    else if (req->is_cgi)
++        add_cgi_env(req, line, value);
++    return;
++}
++
++/*
++ * Name: add_accept_header
++ * Description: Adds a mime_type to a requests accept char buffer
++ *   silently ignore any that don't fit -
++ *   shouldn't happen because of relative buffer sizes
++ */
++
++void add_accept_header(request * req, char *mime_type)
++{
++#ifdef ACCEPT_ON
++    int l = strlen(req->accept);
++    int l2 = strlen(mime_type);
++
++    if ((l + l2 + 2) >= MAX_HEADER_LENGTH)
++        return;
++
++    if (req->accept[0] == '\0')
++        strcpy(req->accept, mime_type);
++    else {
++        req->accept[l] = ',';
++        req->accept[l + 1] = ' ';
++        memcpy(req->accept + l + 2, mime_type, l2 + 1);
++        /* the +1 is for the '\0' */
++        /*
++           sprintf(req->accept + l, ", %s", mime_type);
++         */
++    }
++#endif
++}
++
++void free_requests(void)
++{
++    request *ptr, *next;
++
++    ptr = request_free;
++    while (ptr != NULL) {
++        next = ptr->next;
++        free(ptr);
++        ptr = next;
++    }
++    request_free = NULL;
++}
 diff -bruN boa-0.94.8.2/src/Makefile.in boa-0.94.8.2.pld/src/Makefile.in
 --- boa-0.94.8.2/src/Makefile.in       Sat Feb 12 22:52:45 2000
 +++ boa-0.94.8.2.pld/src/Makefile.in   Sun Sep 10 04:37:16 2000
This page took 0.722389 seconds and 4 git commands to generate.