00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <ipv6.h>
00022 #include <string.h>
00023 #include <stdio.h>
00024 #include <inttypes.h>
00025 #include <arpa/inet.h>
00026 #include <sys/socket.h>
00027 #include <security.h>
00028
00029 #ifdef HAVE_CONFIG_H
00030 #include <config.h>
00031 #endif
00032
00047 void clear_ipv6(struct in6_addr *ipv6)
00048 {
00049 memset(ipv6, 0, sizeof(*ipv6));
00050 }
00051
00056 void uint32_to_ipv6(const uint32_t ipv4, struct in6_addr *ipv6)
00057 {
00058 #ifdef LINUX
00059 ipv6->s6_addr32[0] = 0x00000000;
00060 ipv6->s6_addr32[1] = 0x00000000;
00061 ipv6->s6_addr32[2] = htonl(0xffff);
00062 ipv6->s6_addr32[3] = ipv4;
00063 #else
00064 ipv6->__u6_addr.__u6_addr32[0] = 0x00000000;
00065 ipv6->__u6_addr.__u6_addr32[1] = 0x00000000;
00066 ipv6->__u6_addr.__u6_addr32[2] = htonl(0xffff);
00067 ipv6->__u6_addr.__u6_addr32[3] = ipv4;
00068 #endif
00069 }
00070
00075 void ipv4_to_ipv6(const struct in_addr ipv4, struct in6_addr *ipv6)
00076 {
00077 uint32_to_ipv6(ipv4.s_addr, ipv6);
00078 }
00079
00084 void ipv6_to_ipv4(const struct in6_addr *ipv6, struct in_addr *ipv4)
00085 {
00086 #ifdef LINUX
00087 ipv4->s_addr = ntohl(ipv6->s6_addr32[3]);
00088 #else
00089 ipv4->s_addr = ntohl(ipv6->__u6_addr.__u6_addr32[3]);
00090 #endif
00091 }
00092
00098 int is_ipv4(const struct in6_addr *addr)
00099 {
00100 #ifdef LINUX
00101 if (ntohl(addr->s6_addr32[2]) != 0x0000ffff)
00102 return 0;
00103 if (addr->s6_addr32[0] != 0 || addr->s6_addr32[1] != 0)
00104 return 0;
00105 #else
00106 if (ntohl(addr->__u6_addr.__u6_addr32[2]) != 0x0000ffff)
00107 return 0;
00108 if (addr->__u6_addr.__u6_addr32[0] != 0 || addr->__u6_addr.__u6_addr32[1] != 0)
00109 return 0;
00110 #endif
00111 return 1;
00112 }
00113
00123 void format_ipv6(const struct in6_addr *addr, char *buffer, size_t buflen, uint8_t *protocol)
00124 {
00125 if (is_ipv4(addr)) {
00126 struct in_addr addr4;
00127 #ifdef LINUX
00128 addr4.s_addr = addr->s6_addr32[3];
00129 #else
00130 addr4.s_addr = addr->__u6_addr.__u6_addr32[3];
00131 #endif
00132 if (protocol) *protocol = AF_INET;
00133 if (inet_ntop(AF_INET, &addr4, buffer, buflen) == NULL)
00134 {
00135
00136 SECURE_STRNCPY(buffer, "<ipv4>", buflen);
00137 }
00138 } else {
00139 if (protocol) *protocol = AF_INET6;
00140 if (inet_ntop(AF_INET6, addr, buffer, buflen) == NULL)
00141 {
00142
00143 SECURE_STRNCPY(buffer, "<ipv6>", buflen);
00144 }
00145 }
00146
00147 if (0 < buflen) buffer[buflen-1] = 0;
00148 }
00149
00155 int getsockname_ipv6(int fileno, struct in6_addr *addr)
00156 {
00157 struct sockaddr_storage peer_storage;
00158 socklen_t peerlen = sizeof(peer_storage) ;
00159 int ret;
00160
00161 ret = getsockname(fileno, (struct sockaddr*)&peer_storage, &peerlen);
00162 if (ret != 0 )
00163 {
00164 clear_ipv6(addr);
00165 return 0;
00166 }
00167 if (peer_storage.ss_family == AF_INET6)
00168 {
00169 struct sockaddr_in6 *peer6 = (struct sockaddr_in6 *)&peer_storage;
00170 *addr = peer6->sin6_addr;
00171 return 1;
00172 } else if (peer_storage.ss_family == AF_INET) {
00173 struct sockaddr_in *peer4 = (struct sockaddr_in *)&peer_storage;
00174 ipv4_to_ipv6(peer4->sin_addr, addr);
00175 return 1;
00176 } else {
00177 clear_ipv6(addr);
00178 return 0;
00179 }
00180 }
00181
00188 int hex2ipv6(const char *text, struct in6_addr *ip)
00189 {
00190 #ifdef LINUX
00191 # define READ(text, index) sscanf((text), "%08" SCNx32, (uint32_t *) &ip->s6_addr32[index])
00192 #else
00193 # define READ(text, index) sscanf((text), "%08" SCNx32, (uint32_t *) &ip->__u6_addr.__u6_addr32[index])
00194 #endif
00195
00196 char copy[33];
00197 if (strlen(text) != 32)
00198 return 0;
00199 SECURE_STRNCPY(copy, text, sizeof(copy));
00200
00201 if (READ(copy + 8 * 3, 3) != 1)
00202 return 0;
00203 copy[8 * 3] = 0;
00204
00205 if (READ(copy + 8 * 2, 2) != 1)
00206 return 0;
00207 copy[8 * 2] = 0;
00208
00209 if (READ(copy + 8 * 1, 1) != 1)
00210 return 0;
00211 copy[8] = 0;
00212
00213 if (READ(copy + 8 * 0, 0) != 1)
00214 return 0;
00215 return 1;
00216 #undef READ
00217 }
00218
00224 int ipv6_equal(const struct in6_addr *ipa, const struct in6_addr *ipb)
00225 {
00226 return memcmp(ipa, ipb, sizeof(struct in6_addr)) == 0;
00227 }
00228
00234 int compare_ipv6_with_mask(
00235 const struct in6_addr *addr1,
00236 const struct in6_addr *addr2,
00237 const struct in6_addr *mask)
00238 {
00239 struct in6_addr masked = *addr2;
00240 #ifdef LINUX
00241 masked.s6_addr32[0] &= mask->s6_addr32[0];
00242 masked.s6_addr32[1] &= mask->s6_addr32[1];
00243 masked.s6_addr32[2] &= mask->s6_addr32[2];
00244 masked.s6_addr32[3] &= mask->s6_addr32[3];
00245 #else
00246 masked.__u6_addr.__u6_addr32[0] &= mask->__u6_addr.__u6_addr32[0];
00247 masked.__u6_addr.__u6_addr32[1] &= mask->__u6_addr.__u6_addr32[1];
00248 masked.__u6_addr.__u6_addr32[2] &= mask->__u6_addr.__u6_addr32[2];
00249 masked.__u6_addr.__u6_addr32[3] &= mask->__u6_addr.__u6_addr32[3];
00250 #endif
00251 return memcmp(addr1, &masked, sizeof(struct in6_addr));
00252 }
00253
00257 void create_ipv6_netmask(struct in6_addr *netmask, int mask)
00258 {
00259 uint32_t *p_netmask;
00260 memset(netmask, 0, sizeof(struct in6_addr));
00261 if (mask < 0) {
00262 mask = 0;
00263 } else if (128 < mask) {
00264 mask = 128;
00265 }
00266 #ifdef LINUX
00267 p_netmask = &netmask->s6_addr32[0];
00268 #else
00269 p_netmask = &netmask->__u6_addr.__u6_addr32[0];
00270 #endif
00271 while (32 < mask)
00272 {
00273 *p_netmask = 0xffffffff;
00274 p_netmask++;
00275 mask -= 32;
00276 }
00277 if (mask != 0) {
00278 *p_netmask = htonl(0xFFFFFFFF << (32 - mask));
00279 }
00280 }
00281