nfs-ganesha 1.4

cidr_compare.c

Go to the documentation of this file.
00001 /*
00002  * Various comparison functions
00003  */
00004 #ifdef HAVE_CONFIG_H
00005 #include "config.h"
00006 #endif
00007 
00008 #include <errno.h>
00009 #include <stdio.h> /* For NULL */
00010 
00011 #include "../include/cidr.h"
00012 
00013 
00014 /* Is one block entirely contained in another? */
00015 int
00016 cidr_contains(const CIDR *big, const CIDR *little)
00017 {
00018         int i, oct, bit;
00019         int pflen;
00020 
00021         /* Sanity */
00022         if(big==NULL || little==NULL)
00023         {
00024                 errno = EFAULT;
00025                 return(-1);
00026         }
00027 
00028         /* First off, they better be the same type */
00029         if(big->proto != little->proto)
00030         {
00031                 errno = EPROTO;
00032                 return(-1);
00033         }
00034         
00035         /* We better understand the protocol, too */
00036         if(big->proto!=CIDR_IPV4 && big->proto!=CIDR_IPV6)
00037         {
00038                 errno = EINVAL;
00039                 return(-1);
00040         }
00041         
00042         /*
00043          * little better be SMALL enough to fit in big.  Note: The prefix
00044          * lengths CAN be the same, and little could still 'fit' in big if
00045          * the network bits are all the same.  No need to special-case it, as
00046          * the normal tests below will DTRT.  Save big's pflen for the test
00047          * loop.
00048          */
00049         if(cidr_get_pflen(little) < (pflen = cidr_get_pflen(big)))
00050         {
00051                 errno = 0;
00052                 return(-1);
00053         }
00054         
00055         /*
00056          * Now let's compare.  Note that for IPv4 addresses, the first 12
00057          * octets are irrelevant.  We take care throughout to keep them
00058          * zero'd out, so we don't _need_ to explicitly ignore them.  But,
00059          * it's wasteful; it quadrules the amount of work needed to be done
00060          * to compare to v4 blocks, and this function may be useful in fairly
00061          * performance-sensitive parts of the application.  Sure, an extra 12
00062          * uint8_t compares better not be the make-or-break perforamnce point
00063          * for anything real, but why make it harder unnecessarily?
00064          */
00065         if(big->proto==CIDR_IPV4)
00066         {
00067                 i = 96;
00068                 pflen += 96;
00069         }
00070         else if(big->proto==CIDR_IPV6)
00071                 i = 0;
00072         else
00073         {
00074                 /* Shouldn't happen */
00075                 errno = ENOENT; /* This is a really bad choice of errno */
00076                 return(-1);
00077         }
00078         
00079         /* Start comparing */
00080         for( /* i */ ; i < pflen ; i++ )
00081         {
00082                 /* For convenience, set temp. vars to the octet/bit */
00083                 oct = i/8;
00084                 bit = 7-(i%8);
00085 
00086                 if((big->addr[oct] & (1<<bit)) != (little->addr[oct] & (1<<bit)))
00087                 {
00088                         errno = 0;
00089                         return(-1);
00090                 }
00091         }
00092 
00093         /* If we get here, all their network bits are the same */
00094         return(0);
00095 }
00096 
00097 
00098 /* Are two CIDR's the same? */
00099 int
00100 cidr_equals(const CIDR *one, const CIDR *two)
00101 {
00102         int i;
00103 
00104         /* Check protocols */
00105         if(one->proto != two->proto)
00106                 return(-1);
00107         
00108         /* Check addresses/masks */
00109         if(one->proto==CIDR_IPV4)
00110                 i = 12;
00111         else
00112                 i = 0;
00113         for(/* i */ ; i<=15 ; i++)
00114         {
00115                 if(one->addr[i] != two->addr[i])
00116                         return(-1);
00117                 if(one->mask[i] != two->mask[i])
00118                         return(-1);
00119         }
00120 
00121         /* If we make it here, they're the same */
00122         return(0);
00123 }