2 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
21 * Author: Dustin J. Mitchell <dustin@zmanda.com>
24 * Utility routines for handling sockaddrs
28 #include "sockaddr-util.h"
35 char ipstr[INET6_ADDRSTRLEN];
37 char ipstr[INET_ADDRSTRLEN];
41 port = SU_GET_PORT(sa);
43 if (SU_GET_FAMILY(sa) == AF_INET6) {
44 inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr));
45 dbprintf("(sockaddr_in6 *)%p = { %d, %d, %s }\n",
53 inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr));
54 dbprintf("(sockaddr_in *)%p = { %d, %d, %s }\n",
64 static char mystr_sockaddr[INET6_ADDRSTRLEN + 20];
66 static char mystr_sockaddr[INET_ADDRSTRLEN + 20];
74 char ipstr[INET6_ADDRSTRLEN];
76 char ipstr[INET_ADDRSTRLEN];
80 port = SU_GET_PORT(sa);
82 if ( SU_GET_FAMILY(sa) == AF_INET6) {
83 inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr));
87 inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr));
89 g_snprintf(mystr_sockaddr,sizeof(mystr_sockaddr),"%s:%d", ipstr, port);
90 mystr_sockaddr[sizeof(mystr_sockaddr)-1] = '\0';
92 return mystr_sockaddr;
100 char ipstr[INET6_ADDRSTRLEN];
102 char ipstr[INET_ADDRSTRLEN];
106 if ( SU_GET_FAMILY(sa) == AF_INET6) {
107 inet_ntop(AF_INET6, &sa->sin6.sin6_addr, ipstr, sizeof(ipstr));
111 inet_ntop(AF_INET, &sa->sin.sin_addr.s_addr, ipstr, sizeof(ipstr));
113 g_snprintf(mystr_sockaddr,sizeof(mystr_sockaddr),"%s", ipstr);
114 mystr_sockaddr[sizeof(mystr_sockaddr)-1] = '\0';
116 return mystr_sockaddr;
126 g_debug("parsing %s", src);
127 /* try AF_INET first */
128 SU_INIT(dst, AF_INET);
129 if ((result = inet_pton(AF_INET, src, &dst->sin.sin_addr)) == 1)
132 /* otherwise try AF_INET6, if supported */
134 SU_INIT(dst, AF_INET6);
135 return inet_pton(AF_INET6, src, &dst->sin6.sin6_addr);
141 /* Unmap a V4MAPPED IPv6 address into its equivalent IPv4 address. The location
142 * TMP is used to store the rewritten address, if necessary. Returns a pointer
143 * to the unmapped address.
145 #if defined(WORKING_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
146 static sockaddr_union *
151 if (SU_GET_FAMILY(sa) == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) {
152 SU_INIT(tmp, AF_INET);
153 SU_SET_PORT(tmp, SU_GET_PORT(sa));
154 /* extract the v4 address from byte 12 of the v6 address */
155 memcpy(&tmp->sin.sin_addr.s_addr,
156 &sa->sin6.sin6_addr.s6_addr[12],
157 sizeof(struct in_addr));
164 /* nothing to do if no IPv6 */
165 #define unmap_v4mapped(sa, tmp) ((void)tmp, sa)
174 sockaddr_union tmp1, tmp2;
176 /* if addresses are v4mapped, "unmap" them */
177 ss1 = unmap_v4mapped(ss1, &tmp1);
178 ss2 = unmap_v4mapped(ss2, &tmp2);
180 if (SU_GET_FAMILY(ss1) == SU_GET_FAMILY(ss2)) {
183 if(SU_GET_FAMILY(ss1) == AF_INET6)
185 &ss1->sin6.sin6_addr,
186 &ss2->sin6.sin6_addr,
187 sizeof(ss1->sin6.sin6_addr));
193 sizeof(ss1->sin.sin_addr));
195 return memcmp(ss1, ss2, SS_LEN(ss1));
198 /* compare families to give a total order */
199 if (SU_GET_FAMILY(ss1) < SU_GET_FAMILY(ss2))