ipv6.c

Go to the documentation of this file.
00001 /*
00002  ** Copyright(C) 2007 INL
00003  ** Written by Victor Stinner <victor.stinner@inl.fr>
00004  **
00005  ** $Id: ipv6.c 4847 2008-06-13 14:48:31Z regit $
00006  **
00007  ** This program is free software; you can redistribute it and/or modify
00008  ** it under the terms of the GNU General Public License as published by
00009  ** the Free Software Foundation, version 3 of the License.
00010  **
00011  ** This program is distributed in the hope that it will be useful,
00012  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  ** GNU General Public License for more details.
00015  **
00016  ** You should have received a copy of the GNU General Public License
00017  ** along with this program; if not, write to the Free Software
00018  ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #include <ipv6.h>
00022 #include <string.h>
00023 #include <stdio.h> /* sscanf() */
00024 #include <inttypes.h> /* SCNx32 */
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                         /* error */
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                         /* error */
00143                         SECURE_STRNCPY(buffer, "<ipv6>", buflen);
00144                 }
00145         }
00146         /* always write nul byte at the end */
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         /* Copy text */
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 

Generated on Sat Nov 22 04:00:37 2008 for NuFW by  doxygen 1.4.7