00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "rsync.h"
00020
00021 #define NS_INT16SZ 2
00022 #define NS_IN6ADDRSZ 16
00023
00024
00025
00026
00027
00028
00029 static const char *inet_ntop4(const unsigned char *src, char *dst,
00030 size_t size);
00031
00032 #ifdef AF_INET6
00033 static const char *inet_ntop6(const unsigned char *src, char *dst,
00034 size_t size);
00035 #endif
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 const char *
00046 inet_ntop(int af, const void *src, char *dst, size_t size)
00047 {
00048 switch (af) {
00049 case AF_INET:
00050 return (inet_ntop4(src, dst, size));
00051 #ifdef AF_INET6
00052 case AF_INET6:
00053 return (inet_ntop6(src, dst, size));
00054 #endif
00055 default:
00056 errno = EAFNOSUPPORT;
00057 return (NULL);
00058 }
00059
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 static const char *
00074 inet_ntop4(const unsigned char *src, char *dst, size_t size)
00075 {
00076 static const char *fmt = "%u.%u.%u.%u";
00077 char tmp[sizeof "255.255.255.255"];
00078
00079 if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
00080 {
00081 errno = ENOSPC;
00082 return (NULL);
00083 }
00084 strcpy(dst, tmp);
00085
00086 return (dst);
00087 }
00088
00089
00090
00091
00092
00093
00094
00095 #ifdef AF_INET6
00096 static const char *
00097 inet_ntop6(const unsigned char *src, char *dst, size_t size)
00098 {
00099
00100
00101
00102
00103
00104
00105
00106 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
00107 struct { int base, len; } best, cur;
00108 unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
00109 int i;
00110
00111
00112
00113
00114
00115
00116 memset(words, '\0', sizeof words);
00117 for (i = 0; i < NS_IN6ADDRSZ; i++)
00118 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
00119 best.base = -1;
00120 cur.base = -1;
00121 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
00122 if (words[i] == 0) {
00123 if (cur.base == -1)
00124 cur.base = i, cur.len = 1;
00125 else
00126 cur.len++;
00127 } else {
00128 if (cur.base != -1) {
00129 if (best.base == -1 || cur.len > best.len)
00130 best = cur;
00131 cur.base = -1;
00132 }
00133 }
00134 }
00135 if (cur.base != -1) {
00136 if (best.base == -1 || cur.len > best.len)
00137 best = cur;
00138 }
00139 if (best.base != -1 && best.len < 2)
00140 best.base = -1;
00141
00142
00143
00144
00145 tp = tmp;
00146 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
00147
00148 if (best.base != -1 && i >= best.base &&
00149 i < (best.base + best.len)) {
00150 if (i == best.base)
00151 *tp++ = ':';
00152 continue;
00153 }
00154
00155 if (i != 0)
00156 *tp++ = ':';
00157
00158 if (i == 6 && best.base == 0 &&
00159 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
00160 if (!inet_ntop4(src+12, tp,
00161 sizeof tmp - (tp - tmp)))
00162 return (NULL);
00163 tp += strlen(tp);
00164 break;
00165 }
00166 tp += sprintf(tp, "%x", words[i]);
00167 }
00168
00169 if (best.base != -1 && (best.base + best.len) ==
00170 (NS_IN6ADDRSZ / NS_INT16SZ))
00171 *tp++ = ':';
00172 *tp++ = '\0';
00173
00174
00175
00176
00177 if ((size_t)(tp - tmp) > size) {
00178 errno = ENOSPC;
00179 return (NULL);
00180 }
00181 strcpy(dst, tmp);
00182 return (dst);
00183 }
00184 #endif