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

Generated on Thu Aug 10 21:26:26 2006 for libdhcp by  doxygen 1.4.7