2 * Copyright (c) 2007, 2008, 2010 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
18 * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
20 * Author: Dustin J. Mitchell <dustin@zmanda.com>
23 * Utility routines for handling sockaddrs
27 #include "sockaddr-util.h"
34 char ipstr[INET6_ADDRSTRLEN];
36 char ipstr[INET_ADDRSTRLEN];
40 port = SU_GET_PORT(sa);
42 if (SU_GET_FAMILY(sa) == AF_INET6) {
43 inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr));
44 dbprintf("(sockaddr_in6 *)%p = { %d, %d, %s }\n",
52 inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr));
53 dbprintf("(sockaddr_in *)%p = { %d, %d, %s }\n",
63 static char mystr_sockaddr[INET6_ADDRSTRLEN + 20];
65 static char mystr_sockaddr[INET_ADDRSTRLEN + 20];
73 char ipstr[INET6_ADDRSTRLEN];
75 char ipstr[INET_ADDRSTRLEN];
79 port = SU_GET_PORT(sa);
81 if ( SU_GET_FAMILY(sa) == AF_INET6) {
82 inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr));
86 inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr));
88 g_snprintf(mystr_sockaddr,sizeof(mystr_sockaddr),"%s.%d", ipstr, port);
89 mystr_sockaddr[sizeof(mystr_sockaddr)-1] = '\0';
91 return mystr_sockaddr;
101 g_debug("parsing %s", src);
102 /* try AF_INET first */
103 SU_INIT(dst, AF_INET);
104 if ((result = inet_pton(AF_INET, src, &dst->sin.sin_addr)) == 1)
107 /* otherwise try AF_INET6, if supported */
109 SU_INIT(dst, AF_INET6);
110 return inet_pton(AF_INET6, src, &dst->sin6.sin6_addr);
116 /* Unmap a V4MAPPED IPv6 address into its equivalent IPv4 address. The location
117 * TMP is used to store the rewritten address, if necessary. Returns a pointer
118 * to the unmapped address.
120 #if defined(WORKING_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
121 static sockaddr_union *
126 if (SU_GET_FAMILY(sa) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) {
127 SU_INIT(tmp, AF_INET);
128 SU_SET_PORT(tmp, SU_GET_PORT(sa));
129 /* extract the v4 address from byte 12 of the v6 address */
130 memcpy(&tmp->sin.sin_addr.s_addr,
131 &sa->sin6.sin6_addr.s6_addr[12],
132 sizeof(struct in_addr));
139 /* nothing to do if no IPv6 */
140 #define unmap_v4mapped(sa, tmp) ((void)tmp, sa)
149 sockaddr_union tmp1, tmp2;
151 /* if addresses are v4mapped, "unmap" them */
152 ss1 = unmap_v4mapped(ss1, &tmp1);
153 ss2 = unmap_v4mapped(ss2, &tmp2);
155 if (SU_GET_FAMILY(ss1) == SU_GET_FAMILY(ss2)) {
158 if(SU_GET_FAMILY(ss1) == AF_INET6)
160 &ss1->sin6.sin6_addr,
161 &ss2->sin6.sin6_addr,
162 sizeof(ss1->sin6.sin6_addr));
168 sizeof(ss1->sin.sin_addr));
170 return memcmp(ss1, ss2, SS_LEN(ss1));
173 /* compare families to give a total order */
174 if (SU_GET_FAMILY(ss1) < SU_GET_FAMILY(ss2))