nis-util
1.0.D108
|
00001 // 00002 // nis-util - NIS Administration Utilities 00003 // Copyright (C) 2002, 2008, 2009, 2011, 2012 Peter Miller 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 2 of the License, or (at 00008 // your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 // 00018 00019 #include <lib/ac/string.h> 00020 #include <arpa/inet.h> 00021 #include <lib/ac/ctype.h> 00022 #include <netinet/in.h> 00023 00024 #include <lib/net_utils.h> 00025 #include <lib/space/netmasks.h> 00026 00027 00028 space_netmasks::~space_netmasks() 00029 { 00030 } 00031 00032 00033 space_netmasks::space_netmasks(const rcstring &a_filename) : 00034 space(a_filename), 00035 last_number(0) 00036 { 00037 discard_comments(); 00038 discard_blank_lines(); 00039 } 00040 00041 00042 space_netmasks::pointer 00043 space_netmasks::create(const rcstring &a_filename) 00044 { 00045 return pointer(new space_netmasks(a_filename)); 00046 } 00047 00048 00049 space_netmasks::record::pointer 00050 space_netmasks::get(void) 00051 { 00052 for (;;) 00053 { 00054 source_location line_locn; 00055 line_t line; 00056 if (!read_one_line(line_locn, line)) 00057 { 00058 last_number = 0; 00059 return record::pointer(); 00060 } 00061 if (line.size() < 2) 00062 { 00063 error 00064 ( 00065 line_locn, 00066 "too few fields (expected 2, given %ld)", 00067 (long)line.size() 00068 ); 00069 continue; 00070 } 00071 if (line.size() > 2) 00072 { 00073 error 00074 ( 00075 line_locn, 00076 "too many fields (expected 2, given %ld)", 00077 (long)line.size() 00078 ); 00079 } 00080 00081 // 00082 // Check the network number. 00083 // 00084 in_addr tmp_addr; 00085 if (!inet_aton(line[0].c_str(), &tmp_addr)) 00086 { 00087 error 00088 ( 00089 line_locn, 00090 "network number %s not valid", 00091 line[0].quote_c().c_str() 00092 ); 00093 continue; 00094 } 00095 rcstring temp(inet_ntoa(tmp_addr)); 00096 if (temp != line[0]) 00097 { 00098 error 00099 ( 00100 line_locn, 00101 "network number %s not in correct format, use %s instead", 00102 line[0].quote_c().c_str(), 00103 temp.quote_c().c_str() 00104 ); 00105 } 00106 rcstring rec_number = temp; 00107 unsigned long rec_number_binary = ntohl(tmp_addr.s_addr); 00108 00109 // 00110 // Check record ordering 00111 // 00112 if (last_number > rec_number_binary) 00113 { 00114 error 00115 ( 00116 line_locn, 00117 "network %s out of order", 00118 rec_number.quote_c().c_str() 00119 ); 00120 explain_sequence_errors(); 00121 } 00122 last_number = rec_number_binary; 00123 00124 // 00125 // Check that it is class A, B or C. 00126 // Any other class is invalid. 00127 // 00128 int net_class = network_class_from_number(rec_number_binary); 00129 if (net_class > 'C') 00130 { 00131 error(line_locn, "networks of class %c are reserved", net_class); 00132 } 00133 00134 // 00135 // Check the network mask. 00136 // 00137 rcstring rec_mask = line[1]; 00138 if (!inet_aton(rec_mask.c_str(), &tmp_addr)) 00139 { 00140 error 00141 ( 00142 line_locn, 00143 "network mask %s not valid", 00144 rec_mask.quote_c().c_str() 00145 ); 00146 continue; 00147 } 00148 temp = rcstring(inet_ntoa(tmp_addr)); 00149 if (temp != rec_mask) 00150 { 00151 error 00152 ( 00153 line_locn, 00154 "network mask %s not in correct format, use %s instead", 00155 rec_mask.quote_c().c_str(), 00156 temp.quote_c().c_str() 00157 ); 00158 rec_mask = temp; 00159 } 00160 unsigned long rec_mask_binary = ntohl(tmp_addr.s_addr); 00161 00162 // 00163 // Make sure the network mask has the correct pattern of ones 00164 // and zeros. Otherwise it's stuffed. 00165 // 00166 { 00167 unsigned long tmp_mask = rec_mask_binary; 00168 unsigned long vfy_mask = 0xFFFFFFFFuL ^ (LSB(tmp_mask) - 1); 00169 vfy_mask &= ~3; // smallest possible subnet 00170 if (vfy_mask != tmp_mask) 00171 { 00172 rcstring s = string_from_network_number(vfy_mask); 00173 error 00174 ( 00175 line_locn, 00176 "network mask %s not valid, " 00177 "suggest network mask %s instead", 00178 rec_mask.quote_c().c_str(), 00179 s.quote_c().c_str() 00180 ); 00181 00182 // to avoid cascading errors, re-write the rule 00183 rec_mask_binary = vfy_mask; 00184 rec_mask = s; 00185 } 00186 } 00187 00188 // 00189 // Make sure there are at least 2 bits at the bottom, otherwise 00190 // there are insufficient bits for hosts. 00191 // 00192 if (rec_number_binary & 3) 00193 { 00194 unsigned long tmp_number = rec_number_binary & ~3; 00195 rcstring tmp_number_str = string_from_network_number(tmp_number); 00196 error 00197 ( 00198 line_locn, 00199 "network number %s has no room for any hosts, " 00200 "suggest network number %s instead", 00201 rec_number.quote_c().c_str(), 00202 tmp_number_str.quote_c().c_str() 00203 ); 00204 00205 // to avoid cascading errors, re-write the rule 00206 rec_number_binary = tmp_number; 00207 rec_number = tmp_number_str; 00208 } 00209 if (rec_mask_binary & 3) 00210 { 00211 unsigned long tmp_mask = rec_mask_binary & ~3; 00212 rcstring s = string_from_network_number(tmp_mask); 00213 error 00214 ( 00215 line_locn, 00216 "network mask %s has no room for any hosts, " 00217 "suggest network mask %s instead", 00218 rec_mask.quote_c().c_str(), 00219 s.quote_c().c_str() 00220 ); 00221 00222 // to avoid cascading errors, re-write the rule 00223 rec_mask_binary = tmp_mask; 00224 rec_mask = s; 00225 } 00226 00227 // 00228 // Sanity check the network number against the inverse 00229 // of the network mask. We know the mask is valid at this point. 00230 // 00231 if (rec_number_binary & ~rec_mask_binary) 00232 { 00233 unsigned long vfy_num = rec_number_binary & rec_mask_binary; 00234 rcstring vfy_num_str = string_from_network_number(vfy_num); 00235 unsigned long vfy_mask = 00236 0xFFFFFFFFuL ^ (LSB(rec_number_binary) - 1); 00237 rcstring vfy_mask_str = string_from_network_number(vfy_mask); 00238 00239 if (vfy_num != rec_number_binary) 00240 { 00241 if (vfy_mask != rec_mask_binary) 00242 { 00243 error 00244 ( 00245 line_locn, 00246 "network number %s and network mask %s " 00247 "inconsistent, suggest network number %s " 00248 "or network mask %s instead", 00249 rec_number.quote_c().c_str(), 00250 rec_mask.quote_c().c_str(), 00251 vfy_num_str.quote_c().c_str(), 00252 vfy_mask_str.quote_c().c_str() 00253 ); 00254 // to avoid cascading errors, re-write the rule 00255 rec_mask_binary = vfy_mask; 00256 rec_mask = vfy_mask_str; 00257 } 00258 else 00259 { 00260 error 00261 ( 00262 line_locn, 00263 "network number %s and network mask %s inconsistent, " 00264 "suggest network number %s instead", 00265 rec_number.quote_c().c_str(), 00266 rec_mask.quote_c().c_str(), 00267 vfy_num_str.quote_c().c_str() 00268 ); 00269 // to avoid cascading errors, re-write the rule 00270 rec_number_binary = vfy_num; 00271 rec_number = vfy_num_str; 00272 } 00273 } 00274 else 00275 { 00276 error 00277 ( 00278 line_locn, 00279 "network number %s and network mask %s inconsistent, " 00280 "suggest network mask %s instead", 00281 rec_number.quote_c().c_str(), 00282 rec_mask.quote_c().c_str(), 00283 vfy_mask_str.quote_c().c_str() 00284 ); 00285 // to avoid cascading errors, re-write the rule 00286 rec_mask_binary = vfy_mask; 00287 rec_mask = vfy_mask_str; 00288 } 00289 } 00290 00291 // 00292 // build the new record and pass it to the caller. 00293 // 00294 return record::create(line_locn, rec_number, rec_mask); 00295 } 00296 } 00297 00298 00299 space_netmasks::record::~record() 00300 { 00301 } 00302 00303 00304 space_netmasks::record::record( 00305 const source_location &a_locn, 00306 const rcstring &a_number, 00307 const rcstring &a_mask 00308 ) : 00309 locn(a_locn), 00310 number(a_number), 00311 mask(a_mask) 00312 { 00313 } 00314 00315 00316 space_netmasks::record::pointer 00317 space_netmasks::record::create(const source_location &a_locn, 00318 const rcstring &a_number, const rcstring &a_mask) 00319 { 00320 return pointer(new record(a_locn, a_number, a_mask)); 00321 } 00322 00323 00324 unsigned long 00325 space_netmasks::record::get_number_binary(void) 00326 const 00327 { 00328 return network_number_from_string(number); 00329 } 00330 00331 00332 unsigned long 00333 space_netmasks::record::get_mask_binary(void) 00334 const 00335 { 00336 return network_number_from_string(mask); 00337 } 00338 00339 00340 rcstring 00341 space_netmasks::record::representation(void) 00342 const 00343 { 00344 return (number + " " + mask); 00345 } 00346 00347 00348 // vim: set ts=8 sw=4 et :