X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=common-src%2Fsockaddr-util.c;h=28da531239f1a3807a19ae004c11df5514b1971a;hb=refs%2Fheads%2Fmaster;hp=77fd54a0b11730ee1d001c2c655018caa8530741;hpb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;p=debian%2Famanda diff --git a/common-src/sockaddr-util.c b/common-src/sockaddr-util.c index 77fd54a..28da531 100644 --- a/common-src/sockaddr-util.c +++ b/common-src/sockaddr-util.c @@ -1,9 +1,10 @@ /* - * Copyright (c) 2005 Zmanda Inc. All Rights Reserved. + * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. + * 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 2 + * of the License, 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 @@ -14,8 +15,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 - * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + * Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300 + * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com * * Author: Dustin J. Mitchell */ @@ -23,11 +24,12 @@ * Utility routines for handling sockaddrs */ +#include "amanda.h" #include "sockaddr-util.h" void dump_sockaddr( - struct sockaddr_storage *sa) + sockaddr_union *sa) { #ifdef WORKING_IPV6 char ipstr[INET6_ADDRSTRLEN]; @@ -36,24 +38,22 @@ dump_sockaddr( #endif int port; - port = SS_GET_PORT(sa); + port = SU_GET_PORT(sa); #ifdef WORKING_IPV6 - if (sa->ss_family == (sa_family_t)AF_INET6) { - inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, - ipstr, sizeof(ipstr)); + if (SU_GET_FAMILY(sa) == AF_INET6) { + inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr)); dbprintf("(sockaddr_in6 *)%p = { %d, %d, %s }\n", sa, - ((struct sockaddr_in6 *)sa)->sin6_family, + SU_GET_FAMILY(sa), port, ipstr); } else #endif { - inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, ipstr, - sizeof(ipstr)); + inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr)); dbprintf("(sockaddr_in *)%p = { %d, %d, %s }\n", sa, - ((struct sockaddr_in *)sa)->sin_family, + SU_GET_FAMILY(sa), port, ipstr); } @@ -68,7 +68,7 @@ static char mystr_sockaddr[INET_ADDRSTRLEN + 20]; char * str_sockaddr( - struct sockaddr_storage *sa) + sockaddr_union *sa) { #ifdef WORKING_IPV6 char ipstr[INET6_ADDRSTRLEN]; @@ -77,77 +77,126 @@ str_sockaddr( #endif int port; - port = SS_GET_PORT(sa); + port = SU_GET_PORT(sa); #ifdef WORKING_IPV6 - if ( sa->ss_family == (sa_family_t)AF_INET6) { - inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, - ipstr, sizeof(ipstr)); + if ( SU_GET_FAMILY(sa) == AF_INET6) { + inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr)); } else #endif { - inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, ipstr, - sizeof(ipstr)); + inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr)); } - g_snprintf(mystr_sockaddr,sizeof(mystr_sockaddr),"%s.%d", ipstr, port); + g_snprintf(mystr_sockaddr,sizeof(mystr_sockaddr),"%s:%d", ipstr, port); + mystr_sockaddr[sizeof(mystr_sockaddr)-1] = '\0'; + return mystr_sockaddr; } -int -cmp_sockaddr( - struct sockaddr_storage *ss1, - struct sockaddr_storage *ss2, - int addr_only) +char * +str_sockaddr_no_port( + sockaddr_union *sa) { - /* if addresses are v4mapped, "unmap" them */ #ifdef WORKING_IPV6 -#ifdef IN6_IS_ADDR_V4MAPPED - struct sockaddr_in ss1_v4; - struct sockaddr_in ss2_v4; - - if (ss1->ss_family == AF_INET6 && - IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss1)->sin6_addr)) { - memset(&ss1_v4, 0, sizeof(struct sockaddr_in)); - memcpy(&ss1_v4.sin_addr.s_addr, - &(((struct sockaddr_in6 *)ss1)->sin6_addr.s6_addr[12]), - sizeof(struct in_addr)); - ss1_v4.sin_family = AF_INET; - SS_SET_PORT((struct sockaddr_storage *)&ss1_v4, SS_GET_PORT(ss1)); - ss1 = (struct sockaddr_storage *)&ss1_v4; + char ipstr[INET6_ADDRSTRLEN]; +#else + char ipstr[INET_ADDRSTRLEN]; +#endif + +#ifdef WORKING_IPV6 + if ( SU_GET_FAMILY(sa) == AF_INET6) { + inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr)); + } else +#endif + { + inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr)); } + g_snprintf(mystr_sockaddr,sizeof(mystr_sockaddr),"%s", ipstr); + mystr_sockaddr[sizeof(mystr_sockaddr)-1] = '\0'; - if (ss2->ss_family == AF_INET6 && - IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss2)->sin6_addr)) { - memset(&ss2_v4, 0, sizeof(struct sockaddr_in)); - memcpy(&ss2_v4.sin_addr.s_addr, - &(((struct sockaddr_in6 *)ss2)->sin6_addr.s6_addr[12]), + return mystr_sockaddr; +} + +int +str_to_sockaddr( + const char *src, + sockaddr_union *dst) +{ + int result; + + g_debug("parsing %s", src); + /* try AF_INET first */ + SU_INIT(dst, AF_INET); + if ((result = inet_pton(AF_INET, src, &dst->sin.sin_addr)) == 1) + return result; + + /* otherwise try AF_INET6, if supported */ +#ifdef WORKING_IPV6 + SU_INIT(dst, AF_INET6); + return inet_pton(AF_INET6, src, &dst->sin6.sin6_addr); +#else + return result; +#endif +} + +/* Unmap a V4MAPPED IPv6 address into its equivalent IPv4 address. The location + * TMP is used to store the rewritten address, if necessary. Returns a pointer + * to the unmapped address. + */ +#if defined(WORKING_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) +static sockaddr_union * +unmap_v4mapped( + sockaddr_union *sa, + sockaddr_union *tmp) +{ + if (SU_GET_FAMILY(sa) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) { + SU_INIT(tmp, AF_INET); + SU_SET_PORT(tmp, SU_GET_PORT(sa)); + /* extract the v4 address from byte 12 of the v6 address */ + memcpy(&tmp->sin.sin_addr.s_addr, + &sa->sin6.sin6_addr.s6_addr[12], sizeof(struct in_addr)); - ss2_v4.sin_family = AF_INET; - SS_SET_PORT((struct sockaddr_storage *)&ss2_v4, SS_GET_PORT(ss2)); - ss2 = (struct sockaddr_storage *)&ss2_v4; + return tmp; } + + return sa; +} +#else +/* nothing to do if no IPv6 */ +#define unmap_v4mapped(sa, tmp) ((void)tmp, sa) #endif -#endif - if (ss1->ss_family == ss2->ss_family) { +int +cmp_sockaddr( + sockaddr_union *ss1, + sockaddr_union *ss2, + int addr_only) +{ + sockaddr_union tmp1, tmp2; + + /* if addresses are v4mapped, "unmap" them */ + ss1 = unmap_v4mapped(ss1, &tmp1); + ss2 = unmap_v4mapped(ss2, &tmp2); + + if (SU_GET_FAMILY(ss1) == SU_GET_FAMILY(ss2)) { if (addr_only) { #ifdef WORKING_IPV6 - if(ss1->ss_family == (sa_family_t)AF_INET6) + if(SU_GET_FAMILY(ss1) == AF_INET6) return memcmp( - &((struct sockaddr_in6 *)ss1)->sin6_addr, - &((struct sockaddr_in6 *)ss2)->sin6_addr, - sizeof(((struct sockaddr_in6 *)ss1)->sin6_addr)); + &ss1->sin6.sin6_addr, + &ss2->sin6.sin6_addr, + sizeof(ss1->sin6.sin6_addr)); else #endif return memcmp( - &((struct sockaddr_in *)ss1)->sin_addr, - &((struct sockaddr_in *)ss2)->sin_addr, - sizeof(((struct sockaddr_in *)ss1)->sin_addr)); + &ss1->sin.sin_addr, + &ss2->sin.sin_addr, + sizeof(ss1->sin.sin_addr)); } else { return memcmp(ss1, ss2, SS_LEN(ss1)); } } else { /* compare families to give a total order */ - if (ss1->ss_family < ss2->ss_family) + if (SU_GET_FAMILY(ss1) < SU_GET_FAMILY(ss2)) return -1; else return 1;