⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sa_common.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 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/)." *    Alternately, this acknowledgment may appear in the software itself, *    if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", *    nor may "Apache" appear in their name, without prior written *    permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation.  For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. *//* sa_common.c *  * this file has common code that manipulates socket information * * It's intended to be included in sockaddr.c for every platform and * so should NOT have any headers included in it. * * Feature defines are OK, but there should not be any code in this file * that differs between platforms. */#include "apr.h"#include "apr_lib.h"#include "apr_strings.h"#if APR_HAVE_STDLIB_H#include <stdlib.h>#endifAPR_DECLARE(apr_status_t) apr_sockaddr_port_set(apr_sockaddr_t *sockaddr,                                       apr_port_t port){    /* XXX IPv6: assumes sin_port and sin6_port at same offset */    sockaddr->sa.sin.sin_port = htons(port);    return APR_SUCCESS;}/* XXX assumes IPv4... I don't think this function is needed anyway * since we have apr_sockaddr_info_get(), but we need to clean up Apache's  * listen.c a bit more first. */APR_DECLARE(apr_status_t) apr_sockaddr_ip_set(apr_sockaddr_t *sockaddr,                                         const char *addr){    apr_uint32_t ipaddr;        if (!strcmp(addr, APR_ANYADDR)) {        sockaddr->sa.sin.sin_addr.s_addr = htonl(INADDR_ANY);        return APR_SUCCESS;    }        ipaddr = inet_addr(addr);    if (ipaddr == (apr_uint32_t)-1) {#ifdef WIN32        return WSAEADDRNOTAVAIL;#else        return errno;#endif    }        sockaddr->sa.sin.sin_addr.s_addr = ipaddr;    return APR_SUCCESS;}APR_DECLARE(apr_status_t) apr_sockaddr_port_get(apr_port_t *port,                                       apr_sockaddr_t *sockaddr){    /* XXX IPv6 - assumes sin_port and sin6_port at same offset */    *port = ntohs(sockaddr->sa.sin.sin_port);    return APR_SUCCESS;}APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr,                                         apr_sockaddr_t *sockaddr){    *addr = apr_palloc(sockaddr->pool, sockaddr->addr_str_len);    apr_inet_ntop(sockaddr->sa.sin.sin_family,                  sockaddr->ipaddr_ptr,                  *addr,                  sockaddr->addr_str_len);#if APR_HAVE_IPV6    if (sockaddr->sa.sin.sin_family == AF_INET6 &&        IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sockaddr->ipaddr_ptr)) {        /* This is an IPv4-mapped IPv6 address; drop the leading         * part of the address string so we're left with the familiar         * IPv4 format.         */        *addr += strlen("::ffff:");    }#endif    return APR_SUCCESS;}static void set_sockaddr_vars(apr_sockaddr_t *addr, int family){    addr->sa.sin.sin_family = family;    if (family == APR_INET) {        addr->salen = sizeof(struct sockaddr_in);        addr->addr_str_len = 16;        addr->ipaddr_ptr = &(addr->sa.sin.sin_addr);        addr->ipaddr_len = sizeof(struct in_addr);    }#if APR_HAVE_IPV6    else if (family == APR_INET6) {        addr->salen = sizeof(struct sockaddr_in6);        addr->addr_str_len = 46;        addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr);        addr->ipaddr_len = sizeof(struct in6_addr);    }#endif}APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa,                                           apr_interface_e which,                                           apr_socket_t *sock){    if (which == APR_LOCAL) {        if (sock->local_interface_unknown || sock->local_port_unknown) {            apr_status_t rv = get_local_addr(sock);            if (rv != APR_SUCCESS) {                return rv;            }        }        *sa = sock->local_addr;    }    else if (which == APR_REMOTE) {        *sa = sock->remote_addr;    }    else {        *sa = NULL;        return APR_EINVAL;    }    return APR_SUCCESS;}APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr,                                              char **scope_id,                                              apr_port_t *port,                                              const char *str,                                              apr_pool_t *p){    const char *ch, *lastchar;    int big_port;    apr_size_t addrlen;    *addr = NULL;         /* assume not specified */    *scope_id = NULL;     /* assume not specified */    *port = 0;            /* assume not specified */    /* First handle the optional port number.  That may be all that     * is specified in the string.     */    ch = lastchar = str + strlen(str) - 1;    while (ch >= str && apr_isdigit(*ch)) {        --ch;    }    if (ch < str) {       /* Entire string is the port. */        big_port = atoi(str);        if (big_port < 1 || big_port > 65535) {            return APR_EINVAL;        }        *port = big_port;        return APR_SUCCESS;    }    if (*ch == ':' && ch < lastchar) { /* host and port number specified */        if (ch == str) {               /* string starts with ':' -- bad */            return APR_EINVAL;        }        big_port = atoi(ch + 1);        if (big_port < 1 || big_port > 65535) {            return APR_EINVAL;        }        *port = big_port;        lastchar = ch - 1;    }    /* now handle the hostname */    addrlen = lastchar - str + 1;/* XXX we don't really have to require APR_HAVE_IPV6 for this;  * just pass char[] for ipaddr (so we don't depend on struct in6_addr) * and always define APR_INET6  */#if APR_HAVE_IPV6    if (*str == '[') {        const char *end_bracket = memchr(str, ']', addrlen);        struct in6_addr ipaddr;        const char *scope_delim;        if (!end_bracket || end_bracket != lastchar) {            *port = 0;            return APR_EINVAL;        }        /* handle scope id; this is the only context where it is allowed */        scope_delim = memchr(str, '%', addrlen);        if (scope_delim) {            if (scope_delim == end_bracket - 1) { /* '%' without scope id */                *port = 0;                return APR_EINVAL;            }            addrlen = scope_delim - str - 1;            *scope_id = apr_palloc(p, end_bracket - scope_delim);            memcpy(*scope_id, scope_delim + 1, end_bracket - scope_delim - 1);            (*scope_id)[end_bracket - scope_delim - 1] = '\0';        }        else {            addrlen = addrlen - 2; /* minus 2 for '[' and ']' */        }        *addr = apr_palloc(p, addrlen + 1);        memcpy(*addr,               str + 1,               addrlen);        (*addr)[addrlen] = '\0';        if (apr_inet_pton(AF_INET6, *addr, &ipaddr) != 1) {            *addr = NULL;            *scope_id = NULL;            *port = 0;            return APR_EINVAL;        }    }    else #endif    {        /* XXX If '%' is not a valid char in a DNS name, we *could* check          *     for bogus scope ids first.         */        *addr = apr_palloc(p, addrlen + 1);        memcpy(*addr, str, addrlen);        (*addr)[addrlen] = '\0';    }    return APR_SUCCESS;}#if defined(HAVE_GETADDRINFO) && APR_HAVE_IPV6static void save_addrinfo(apr_pool_t *p, apr_sockaddr_t *sa,                           struct addrinfo *ai, apr_port_t port){    sa->pool = p;    sa->sa.sin.sin_family = ai->ai_family;    memcpy(&sa->sa, ai->ai_addr, ai->ai_addrlen);    /* XXX IPv6: assumes sin_port and sin6_port at same offset */    sa->sa.sin.sin_port = htons(port);    set_sockaddr_vars(sa, sa->sa.sin.sin_family);}#elsestatic void save_addrinfo(apr_pool_t *p, apr_sockaddr_t *sa,                          struct in_addr ipaddr, apr_port_t port){    sa->pool = p;    sa->sa.sin.sin_family = AF_INET;    sa->sa.sin.sin_addr = ipaddr;    sa->sa.sin.sin_port = htons(port);    set_sockaddr_vars(sa, sa->sa.sin.sin_family);}#endifAPR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa,                                          const char *hostname,                                           apr_int32_t family, apr_port_t port,                                          apr_int32_t flags, apr_pool_t *p){    (*sa) = (apr_sockaddr_t *)apr_pcalloc(p, sizeof(apr_sockaddr_t));    if ((*sa) == NULL)        return APR_ENOMEM;    (*sa)->hostname = apr_pstrdup(p, hostname);#if defined(HAVE_GETADDRINFO) && APR_HAVE_IPV6    if (hostname != NULL) {        struct addrinfo hints, *ai;        apr_sockaddr_t *cursa;        int error;        char num[8];        memset(&hints, 0, sizeof(hints));        hints.ai_flags = AI_CANONNAME;        hints.ai_family = family;        hints.ai_socktype = SOCK_STREAM;        hints.ai_protocol = 0;        apr_snprintf(num, sizeof(num), "%d", port);        error = getaddrinfo(hostname, num, &hints, &ai);        if (error) {            if (error == EAI_SYSTEM) {                return errno;            }            else {                /* XXX fixme!                 * no current way to represent this with APR's error                 * scheme... note that glibc uses negative values for these                 * numbers, perhaps so they don't conflict with h_errno                 * values...  Tru64 uses positive values which conflict                 * with h_errno values                 */                return error + APR_OS_START_SYSERR;            }        }        cursa = *sa;        save_addrinfo(p, cursa, ai, port);        while (ai->ai_next) { /* while more addresses to report */            cursa->next = apr_pcalloc(p, sizeof(apr_sockaddr_t));            ai = ai->ai_next;            cursa = cursa->next;            save_addrinfo(p, cursa, ai, port);        }        freeaddrinfo(ai);    }    else {        if (family == APR_UNSPEC) {            (*sa)->sa.sin.sin_family = APR_INET;        }        else {            (*sa)->sa.sin.sin_family = family;        }        (*sa)->pool = p;        /* XXX IPv6: assumes sin_port and sin6_port at same offset */        (*sa)->sa.sin.sin_port = htons(port);        set_sockaddr_vars(*sa, (*sa)->sa.sin.sin_family);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -