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

📄 addr_families.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1997-2007 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden).  * 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. Neither the name of the Institute nor the names of its contributors  *    may be used to endorse or promote products derived from this software  *    without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  * ANY EXPRESS 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 INSTITUTE OR 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.  */#include "krb5_locl.h"RCSID("$Id: addr_families.c 22039 2007-11-10 11:47:35Z lha $");struct addr_operations {    int af;    krb5_address_type atype;    size_t max_sockaddr_size;    krb5_error_code (*sockaddr2addr)(const struct sockaddr *, krb5_address *);    krb5_error_code (*sockaddr2port)(const struct sockaddr *, int16_t *);    void (*addr2sockaddr)(const krb5_address *, struct sockaddr *,			  krb5_socklen_t *sa_size, int port);    void (*h_addr2sockaddr)(const char *, struct sockaddr *, krb5_socklen_t *, int);    krb5_error_code (*h_addr2addr)(const char *, krb5_address *);    krb5_boolean (*uninteresting)(const struct sockaddr *);    void (*anyaddr)(struct sockaddr *, krb5_socklen_t *, int);    int (*print_addr)(const krb5_address *, char *, size_t);    int (*parse_addr)(krb5_context, const char*, krb5_address *);    int (*order_addr)(krb5_context, const krb5_address*, const krb5_address*);    int (*free_addr)(krb5_context, krb5_address*);    int (*copy_addr)(krb5_context, const krb5_address*, krb5_address*);    int (*mask_boundary)(krb5_context, const krb5_address*, unsigned long, 				     krb5_address*, krb5_address*);};/* * AF_INET - aka IPv4 implementation */static krb5_error_codeipv4_sockaddr2addr (const struct sockaddr *sa, krb5_address *a){    const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;    unsigned char buf[4];    a->addr_type = KRB5_ADDRESS_INET;    memcpy (buf, &sin4->sin_addr, 4);    return krb5_data_copy(&a->address, buf, 4);}static krb5_error_codeipv4_sockaddr2port (const struct sockaddr *sa, int16_t *port){    const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;    *port = sin4->sin_port;    return 0;}static voidipv4_addr2sockaddr (const krb5_address *a,		    struct sockaddr *sa,		    krb5_socklen_t *sa_size,		    int port){    struct sockaddr_in tmp;    memset (&tmp, 0, sizeof(tmp));    tmp.sin_family = AF_INET;    memcpy (&tmp.sin_addr, a->address.data, 4);    tmp.sin_port = port;    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));    *sa_size = sizeof(tmp);}static voidipv4_h_addr2sockaddr(const char *addr,		     struct sockaddr *sa,		     krb5_socklen_t *sa_size,		     int port){    struct sockaddr_in tmp;    memset (&tmp, 0, sizeof(tmp));    tmp.sin_family = AF_INET;    tmp.sin_port   = port;    tmp.sin_addr   = *((const struct in_addr *)addr);    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));    *sa_size = sizeof(tmp);}static krb5_error_codeipv4_h_addr2addr (const char *addr,		  krb5_address *a){    unsigned char buf[4];    a->addr_type = KRB5_ADDRESS_INET;    memcpy(buf, addr, 4);    return krb5_data_copy(&a->address, buf, 4);}/* * Are there any addresses that should be considered `uninteresting'? */static krb5_booleanipv4_uninteresting (const struct sockaddr *sa){    const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;    if (sin4->sin_addr.s_addr == INADDR_ANY)	return TRUE;    return FALSE;}static voidipv4_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port){    struct sockaddr_in tmp;    memset (&tmp, 0, sizeof(tmp));    tmp.sin_family = AF_INET;    tmp.sin_port   = port;    tmp.sin_addr.s_addr = INADDR_ANY;    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));    *sa_size = sizeof(tmp);}static intipv4_print_addr (const krb5_address *addr, char *str, size_t len){    struct in_addr ia;    memcpy (&ia, addr->address.data, 4);    return snprintf (str, len, "IPv4:%s", inet_ntoa(ia));}static intipv4_parse_addr (krb5_context context, const char *address, krb5_address *addr){    const char *p;    struct in_addr a;    p = strchr(address, ':');    if(p) {	p++;	if(strncasecmp(address, "ip:", p - address) != 0 &&	   strncasecmp(address, "ip4:", p - address) != 0 &&	   strncasecmp(address, "ipv4:", p - address) != 0 &&	   strncasecmp(address, "inet:", p - address) != 0)	    return -1;    } else	p = address;#ifdef HAVE_INET_ATON    if(inet_aton(p, &a) == 0)	return -1;#elif defined(HAVE_INET_ADDR)    a.s_addr = inet_addr(p);    if(a.s_addr == INADDR_NONE)	return -1;#else    return -1;#endif    addr->addr_type = KRB5_ADDRESS_INET;    if(krb5_data_alloc(&addr->address, 4) != 0)	return -1;    _krb5_put_int(addr->address.data, ntohl(a.s_addr), addr->address.length);    return 0;}static intipv4_mask_boundary(krb5_context context, const krb5_address *inaddr,		   unsigned long len, krb5_address *low, krb5_address *high){    unsigned long ia;    uint32_t l, h, m = 0xffffffff;    if (len > 32) {	krb5_set_error_string(context, "IPv4 prefix too large (%ld)", len);	return KRB5_PROG_ATYPE_NOSUPP;    }    m = m << (32 - len);    _krb5_get_int(inaddr->address.data, &ia, inaddr->address.length);    l = ia & m;    h = l | ~m;    low->addr_type = KRB5_ADDRESS_INET;    if(krb5_data_alloc(&low->address, 4) != 0)	return -1;    _krb5_put_int(low->address.data, l, low->address.length);    high->addr_type = KRB5_ADDRESS_INET;    if(krb5_data_alloc(&high->address, 4) != 0) {	krb5_free_address(context, low);	return -1;    }    _krb5_put_int(high->address.data, h, high->address.length);    return 0;}/* * AF_INET6 - aka IPv6 implementation */#ifdef HAVE_IPV6static krb5_error_codeipv6_sockaddr2addr (const struct sockaddr *sa, krb5_address *a){    const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;    if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {	unsigned char buf[4];	a->addr_type      = KRB5_ADDRESS_INET;#ifndef IN6_ADDR_V6_TO_V4#ifdef IN6_EXTRACT_V4ADDR#define IN6_ADDR_V6_TO_V4(x) (&IN6_EXTRACT_V4ADDR(x))#else#define IN6_ADDR_V6_TO_V4(x) ((const struct in_addr *)&(x)->s6_addr[12])#endif#endif	memcpy (buf, IN6_ADDR_V6_TO_V4(&sin6->sin6_addr), 4);	return krb5_data_copy(&a->address, buf, 4);    } else {	a->addr_type = KRB5_ADDRESS_INET6;	return krb5_data_copy(&a->address,			      &sin6->sin6_addr,			      sizeof(sin6->sin6_addr));    }}static krb5_error_codeipv6_sockaddr2port (const struct sockaddr *sa, int16_t *port){    const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;    *port = sin6->sin6_port;    return 0;}static voidipv6_addr2sockaddr (const krb5_address *a,		    struct sockaddr *sa,		    krb5_socklen_t *sa_size,		    int port){    struct sockaddr_in6 tmp;    memset (&tmp, 0, sizeof(tmp));    tmp.sin6_family = AF_INET6;    memcpy (&tmp.sin6_addr, a->address.data, sizeof(tmp.sin6_addr));    tmp.sin6_port = port;    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));    *sa_size = sizeof(tmp);}static voidipv6_h_addr2sockaddr(const char *addr,		     struct sockaddr *sa,		     krb5_socklen_t *sa_size,		     int port){    struct sockaddr_in6 tmp;    memset (&tmp, 0, sizeof(tmp));    tmp.sin6_family = AF_INET6;    tmp.sin6_port   = port;    tmp.sin6_addr   = *((const struct in6_addr *)addr);    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));    *sa_size = sizeof(tmp);}static krb5_error_codeipv6_h_addr2addr (const char *addr,		  krb5_address *a){    a->addr_type = KRB5_ADDRESS_INET6;    return krb5_data_copy(&a->address, addr, sizeof(struct in6_addr));}/* *  */static krb5_booleanipv6_uninteresting (const struct sockaddr *sa){    const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;    const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr;        return	IN6_IS_ADDR_LINKLOCAL(in6)	|| IN6_IS_ADDR_V4COMPAT(in6);}static voidipv6_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port){    struct sockaddr_in6 tmp;    memset (&tmp, 0, sizeof(tmp));    tmp.sin6_family = AF_INET6;    tmp.sin6_port   = port;    tmp.sin6_addr   = in6addr_any;    *sa_size = sizeof(tmp);}static intipv6_print_addr (const krb5_address *addr, char *str, size_t len){    char buf[128], buf2[3];#ifdef HAVE_INET_NTOP    if(inet_ntop(AF_INET6, addr->address.data, buf, sizeof(buf)) == NULL)#endif	{	    /* XXX this is pretty ugly, but better than abort() */	    int i;	    unsigned char *p = addr->address.data;	    buf[0] = '\0';	    for(i = 0; i < addr->address.length; i++) {		snprintf(buf2, sizeof(buf2), "%02x", p[i]);		if(i > 0 && (i & 1) == 0)		    strlcat(buf, ":", sizeof(buf));		strlcat(buf, buf2, sizeof(buf));	    }	}    return snprintf(str, len, "IPv6:%s", buf);}static intipv6_parse_addr (krb5_context context, const char *address, krb5_address *addr){    int ret;    struct in6_addr in6;    const char *p;    p = strchr(address, ':');    if(p) {	p++;	if(strncasecmp(address, "ip6:", p - address) == 0 ||	   strncasecmp(address, "ipv6:", p - address) == 0 ||	   strncasecmp(address, "inet6:", p - address) == 0)	    address = p;    }    ret = inet_pton(AF_INET6, address, &in6.s6_addr);    if(ret == 1) {	addr->addr_type = KRB5_ADDRESS_INET6;	ret = krb5_data_alloc(&addr->address, sizeof(in6.s6_addr));	if (ret)	    return -1;	memcpy(addr->address.data, in6.s6_addr, sizeof(in6.s6_addr));	return 0;    }    return -1;}static intipv6_mask_boundary(krb5_context context, const krb5_address *inaddr,		   unsigned long len, krb5_address *low, krb5_address *high){    struct in6_addr addr, laddr, haddr;    uint32_t m;    int i, sub_len;    if (len > 128) {	krb5_set_error_string(context, "IPv6 prefix too large (%ld)", len);	return KRB5_PROG_ATYPE_NOSUPP;    }    if (inaddr->address.length != sizeof(addr)) {	krb5_set_error_string(context, "IPv6 addr bad length");	return KRB5_PROG_ATYPE_NOSUPP;    }    memcpy(&addr, inaddr->address.data, inaddr->address.length);    for (i = 0; i < 16; i++) {	sub_len = min(8, len);	m = 0xff << (8 - sub_len);		laddr.s6_addr[i] = addr.s6_addr[i] & m;	haddr.s6_addr[i] = (addr.s6_addr[i] & m) | ~m;	if (len > 8)	    len -= 8;	else	    len = 0;    }    low->addr_type = KRB5_ADDRESS_INET6;    if (krb5_data_alloc(&low->address, sizeof(laddr.s6_addr)) != 0)	return -1;    memcpy(low->address.data, laddr.s6_addr, sizeof(laddr.s6_addr));    high->addr_type = KRB5_ADDRESS_INET6;    if (krb5_data_alloc(&high->address, sizeof(haddr.s6_addr)) != 0) {	krb5_free_address(context, low);	return -1;    }    memcpy(high->address.data, haddr.s6_addr, sizeof(haddr.s6_addr));    return 0;}#endif /* IPv6 *//* * table */#define KRB5_ADDRESS_ARANGE	(-100)struct arange {    krb5_address low;    krb5_address high;};static intarange_parse_addr (krb5_context context, 		   const char *address, krb5_address *addr){    char buf[1024], *p;    krb5_address low0, high0;    struct arange *a;    krb5_error_code ret;        if(strncasecmp(address, "RANGE:", 6) != 0)	return -1;        address += 6;    p = strrchr(address, '/');    if (p) {	krb5_addresses addrmask;	char *q;	long num;	if (strlcpy(buf, address, sizeof(buf)) > sizeof(buf))	    return -1;	buf[p - address] = '\0';	ret = krb5_parse_address(context, buf, &addrmask);	if (ret)	    return ret;	if(addrmask.len != 1) {	    krb5_free_addresses(context, &addrmask);	    return -1;	}		address += p - address + 1;	num = strtol(address, &q, 10);	if (q == address || *q != '\0' || num < 0) {	    krb5_free_addresses(context, &addrmask);	    return -1;	}

⌨️ 快捷键说明

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