ip_addr.c

Go to the documentation of this file.
00001 /** @file ip_addr.c
00002  *
00003  * Generic IP address representation and conversion utilities.
00004  *  
00005  */
00006 /*
00007  * Copyright (C) 2006  Red Hat, Inc. All rights reserved.
00008  *
00009  * This copyrighted material is made available to anyone wishing to use,
00010  * modify, copy, or redistribute it subject to the terms and conditions of
00011  * the GNU General Public License v.2.  This program is distributed in the
00012  * hope that it will be useful, but WITHOUT ANY WARRANTY expressed or
00013  * implied, including the implied warranties of MERCHANTABILITY or FITNESS
00014  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
00015  * details.  You should have received a copy of the GNU General Public
00016  * License along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00018  * USA. Any Red Hat trademarks that are incorporated in the source code or
00019  * documentation are not subject to the GNU General Public License and may
00020  * only be used or replicated with the express permission of Red Hat, Inc.
00021  *
00022  * Red Hat Author(s): Jason Vas Dias
00023  *                    David Cantrell
00024  */
00025 
00026 #include <ip_addr.h>
00027 #include <arpa/inet.h>
00028 #include <net/if_arp.h>
00029 #include <string.h>
00030 #include <stdio.h>
00031 
00032 ip_addr_t ip_addr_v4( register uint32_t i )
00033 {
00034     ip_addr_t ip = { AF_INET };
00035     memset(&(ip.sa_data[0]),'\0',sizeof(ip.sa_data));
00036     ((struct in_addr*)IP_ADDR_IN(&ip))->s_addr = htonl( i );
00037     return ip;
00038 }
00039 
00040 uint32_t ip_v4_addr( register ip_addr_t *ip )
00041 {
00042     if ( ip->sa_family != AF_INET ) return 0;
00043     return ntohl( ((struct in_addr*)IP_ADDR_IN(ip))->s_addr );
00044 }
00045 
00046 
00047 ip_addr_t ip_addr_in( register struct in_addr *in )
00048 {
00049     ip_addr_t ip = { AF_INET };
00050     memset(&(ip.sa_data[0]),'\0',sizeof(ip.sa_data));
00051     *((struct in_addr*)IP_ADDR_IN(&ip)) = *in;
00052     return ip;
00053 }
00054 
00055 struct in_addr ip_in_addr( register ip_addr_t *ip )
00056 {
00057     
00058     return *((struct in_addr*)IP_ADDR_IN(ip));    
00059 }
00060 
00061 
00062 ip_addr_t ip_addr_sin( register struct sockaddr_in *sin )
00063 {
00064     ip_addr_t ip;
00065     *((struct sockaddr_in*)&ip) = *sin;
00066     return ip;
00067 }
00068 
00069 struct sockaddr_in ip_sin_addr( register ip_addr_t *ip )
00070 {
00071     return *((struct sockaddr_in*)ip);
00072 }
00073 
00074 
00075 ip_addr_t ip_addr_in6(  register struct in6_addr *in6 )
00076 {
00077     ip_addr_t ip = { AF_INET6 };
00078     memset(&(ip.sa_data[0]),'\0',sizeof(ip.sa_data));
00079     *((struct in6_addr*)IP_ADDR_IN6(&ip)) = *in6;
00080     return ip;
00081 }
00082 
00083 
00084 struct in6_addr ip_in6_addr( register ip_addr_t *ip)
00085 {
00086     return *((struct in6_addr*)IP_ADDR_IN6(ip));
00087 }
00088 
00089 
00090 
00091 ip_addr_t ip_addr_sin6( register struct sockaddr_in6 *sin6 )
00092 {
00093     ip_addr_t ip;
00094     *((struct sockaddr_in6*)&ip) = *sin6;
00095     return ip;
00096 }
00097 
00098 struct sockaddr_in6 ip_sin6_addr( register ip_addr_t *ip )
00099 {
00100     return *((struct sockaddr_in6*)ip);    
00101 }
00102 
00103 
00104 ip_addr_t ip_addr_in6bytes(register in6_bytes_t *in6)
00105 {  
00106     ip_addr_t ip = { AF_INET6 };
00107     memset(&(ip.sa_data[0]),'\0',sizeof(ip.sa_data));
00108     *((struct in6_addr*)IP_ADDR_IN6(&ip)) = *((struct in6_addr*)in6);
00109     return ip;
00110 }
00111 
00112 
00113 in6_bytes_t ip_in6bytes_addr( register ip_addr_t *ip )
00114 {
00115     return *((in6_bytes_t*)IP_ADDR_IN6(ip));
00116 }
00117 
00118 ip_addr_t ip_addr_text( register const char *s )
00119 {
00120     ip_addr_t ip;
00121     memset(&ip,'\0',sizeof(ip));
00122 
00123     if( inet_pton( AF_INET6, s, ((struct in6_addr*)IP_ADDR_IN6(&ip))) )
00124         ip.sa_family = AF_INET6;
00125     else
00126     if( inet_pton( AF_INET, s, ((struct in6_addr*)IP_ADDR_IN(&ip))) )
00127         ip.sa_family = AF_INET;
00128 
00129     return ip;
00130 } 
00131 
00132 static void hex_dump( uint8_t *src, uint32_t src_len, uint8_t *dst, uint32_t dst_len, char sep)
00133 {
00134     while( src_len-- && (dst_len-=3) )
00135         dst+=sprintf((char*)dst,"%.2x%c",*(src++),sep); 
00136     *(--dst)='\0';
00137 }
00138 
00139 char *ip_text_addr( register ip_addr_t *ip, register  char *buf, register size_t len)
00140 {
00141     static char sbuf[64]="\0";
00142     char *d = buf ? buf : &(sbuf[0]);
00143     size_t sz = buf ? len : 64;
00144     char sep ='.';
00145 
00146     switch(ip->sa_family)
00147     {
00148     case AF_INET:
00149         return (char*) inet_ntop(AF_INET, (struct in_addr*)IP_ADDR_IN(ip), d, sz );
00150     case AF_INET6:
00151         return (char*) inet_ntop(AF_INET6, (struct in6_addr*)IP_ADDR_IN6(ip), d, sz );
00152 #ifndef AF_LLC
00153 #define AF_LLC 26
00154 #endif
00155     case AF_LLC:
00156         sep = ':';
00157     default:
00158         hex_dump((uint8_t*)IP_ADDR_LLC(ip), sep == ':' ? 6 : __LLC_SOCK_SIZE__, (uint8_t*)d, sz, sep);
00159         return d;
00160     }
00161     return 0L;
00162 }
00163 
00164 char * ip_text(ip_addr_t ip, register char *buf, register size_t sz)
00165 {
00166     return ip_text_addr(&ip, buf, sz);
00167 }
00168 
00169 ip_addr_t ip_addr_binary(uint8_t *addr_data, uint8_t len)
00170 {
00171     ip_addr_t ip;
00172     uint8_t *addr=0;
00173     memset(&ip, '\0', sizeof(ip_addr_t));
00174 
00175     switch( len )
00176     {
00177     case 4:
00178         ip.sa_family = AF_INET;
00179         addr = (uint8_t*) IP_ADDR_IN( &ip );
00180         break;
00181     case 6:
00182         ip.sa_family = AF_LLC;
00183         addr = (uint8_t*) IP_ADDR_IN6( &ip );
00184         break;
00185     case 16:
00186         ip.sa_family = AF_INET6;
00187         addr = (uint8_t*) IP_ADDR_LLC( &ip );
00188         break;
00189     default:
00190         return ip;
00191     }
00192     memcpy(addr, addr_data, len);
00193     return ip;
00194 }
00195 
00196 ip_addr_t ip_v4_broadcast( ip_addr_t *ipp, uint8_t prefix )
00197 {
00198     ip_addr_t ip = { AF_INET };
00199     memset(&(ip.sa_data[0]),'\0',sizeof(ip.sa_data));
00200     uint32_t ip4 = ntohl( ((struct in_addr*)IP_ADDR_IN( ipp ))->s_addr );
00201     ((struct sockaddr_in*)&(ip))->sin_addr.s_addr=
00202     htonl( ( ip4 & (((1 << prefix)-1) << (32 - prefix)))
00203                                  |(((1<< (32 - prefix))-1))
00204          );
00205     return ip;
00206 }
00207 
00208 uint8_t ip_v4_netmask_to_prefix( ip_addr_t *netmask )
00209 {
00210     if ( netmask->sa_family != AF_INET ) return 0;
00211     register uint32_t nm = ntohl(((struct sockaddr_in*)netmask)->sin_addr.s_addr), i=32, b=1;
00212     for(; i && ((nm & b) != b); i-=1, b <<= 1);
00213     return i;
00214 }
00215 
00216 ip_addr_t ip_v4_prefix_to_netmask( uint8_t prefix )
00217 {
00218     ip_addr_t ip = { .sa_family = AF_INET };
00219     
00220     ((struct sockaddr_in*)&ip)->sin_addr.s_addr = 
00221         htonl( (( 1 << prefix ) - 1) << (32 - prefix));
00222     
00223     return ip;
00224 }
00225 
00226 ip_addr_t ip_mask( ip_addr_t *ipA, uint8_t prefix )
00227 {
00228     ip_addr_t ip;
00229     ip = *ipA;
00230     switch( ipA->sa_family )
00231     {
00232     case AF_INET:
00233     {
00234         uint32_t a = ntohl(IP_ADDR_IN(ipA)->s_addr);
00235         prefix &= 0x1f;
00236         (IP_ADDR_IN(&ip))->s_addr = 
00237             htonl( a  & (((1 << prefix) -1 ) << (32 - prefix)) );
00238     }   break;
00239     case AF_INET6:
00240     {
00241         uint8_t n = 
00242             prefix & 0x7f, 
00243             *a = ((uint8_t*)IP_ADDR_IN6(&ip)), 
00244             *b = &(a[16]);
00245         for(; (b > a) && (n >= 8); b--, n-=8)
00246             *b=0;
00247         if( n )
00248             *b &=((1<<n)-1)<<(8-n);
00249     }   break;
00250     }
00251     return ip;
00252 }

Generated on Mon Aug 14 17:26:18 2006 for libdhcp by  doxygen 1.4.7