nfs-ganesha 1.4
|
00001 /* 00002 * Functions to generate various networks based on a CIDR 00003 */ 00004 #ifdef HAVE_CONFIG_H 00005 #include "config.h" 00006 #endif 00007 00008 #include <errno.h> 00009 #include <stdlib.h> 00010 #include <string.h> 00011 00012 #include "cidr.h" 00013 #include "abstract_mem.h" 00014 00015 00016 /* Get the CIDR's immediate supernet */ 00017 CIDR * 00018 cidr_net_supernet(const CIDR *addr) 00019 { 00020 int i, j; 00021 int pflen; 00022 CIDR *toret; 00023 00024 /* Quick check */ 00025 if(addr==NULL) 00026 { 00027 errno = EFAULT; 00028 return(NULL); 00029 } 00030 00031 /* If it's already a /0 in its protocol, return nothing */ 00032 pflen = cidr_get_pflen(addr); 00033 if(pflen==0) 00034 { 00035 errno = 0; 00036 return(NULL); 00037 } 00038 00039 toret = cidr_dup(addr); 00040 if(toret==NULL) 00041 return(NULL); /* Preserve errno */ 00042 00043 /* Chop a bit off the netmask */ 00044 /* This gets the last network bit */ 00045 if(toret->proto==CIDR_IPV4) 00046 pflen += 96; 00047 pflen--; 00048 i = pflen / 8; 00049 j = 7 - (pflen % 8); 00050 00051 /* Make that bit a host bit */ 00052 (toret->mask)[i] &= ~(1<<j); 00053 00054 /* 00055 * Now zero out the host bits in the addr. Do this manually instead 00056 * of calling cidr_addr_network() to save some extra copies and 00057 * allocationss and so forth. 00058 */ 00059 for(/* i */ ; i<=15 ; i++) 00060 { 00061 for(/* j */ ; j>=0 ; j--) 00062 (toret->addr)[i] &= ~(1<<j); 00063 j=7; 00064 } 00065 00066 /* And send it back */ 00067 return(toret); 00068 } 00069 00070 00071 /* Get the CIDR's two children */ 00072 CIDR ** 00073 cidr_net_subnets(const CIDR *addr) 00074 { 00075 int i, j; 00076 int pflen; 00077 CIDR **toret; 00078 00079 if(addr==NULL) 00080 { 00081 errno = EFAULT; 00082 return(NULL); 00083 } 00084 00085 /* You can't split a host address! */ 00086 pflen = cidr_get_pflen(addr); 00087 if( (addr->proto==CIDR_IPV4 && pflen==32) 00088 || (addr->proto==CIDR_IPV6 && pflen==128)) 00089 { 00090 errno = 0; 00091 return(NULL); 00092 } 00093 00094 toret = gsh_calloc(2, sizeof(CIDR *)); 00095 if(toret==NULL) 00096 { 00097 errno = ENOMEM; 00098 return(NULL); 00099 } 00100 00101 /* Get a blank-ish slate for the first kid */ 00102 toret[0] = cidr_addr_network(addr); 00103 if(toret[0]==NULL) 00104 { 00105 gsh_free(toret); 00106 return(NULL); /* Preserve errno */ 00107 } 00108 00109 /* Find its first host bit */ 00110 if(toret[0]->proto==CIDR_IPV4) 00111 pflen += 96; 00112 i = pflen / 8; 00113 j = 7 - (pflen % 8); 00114 00115 /* Make it a network bit */ 00116 (toret[0])->mask[i] |= 1<<j; 00117 00118 /* Now dup the second kid off that */ 00119 toret[1] = cidr_dup(toret[0]); 00120 if(toret[1]==NULL) 00121 { 00122 cidr_free(toret[0]); 00123 gsh_free(toret); 00124 return(NULL); /* Preserve errno */ 00125 } 00126 00127 /* And set that first host bit */ 00128 (toret[1])->addr[i] |= 1<<j; 00129 00130 00131 /* Return the pair */ 00132 return(toret); 00133 }