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 <arpa/inet.h> 00020 #include <lib/ac/ctype.h> 00021 #include <lib/ac/string.h> 00022 #include <netinet/in.h> 00023 00024 #include <lib/net_utils.h> 00025 #include <lib/space/networks.h> 00026 #include <lib/rcstring/accumulator.h> 00027 00028 00029 space_networks::~space_networks() 00030 { 00031 } 00032 00033 00034 space_networks::space_networks(const rcstring &a_filename) : 00035 space(a_filename), 00036 last_addr(0) 00037 { 00038 discard_comments(); 00039 discard_blank_lines(); 00040 } 00041 00042 00043 space_networks::pointer 00044 space_networks::create(const rcstring &a_filename) 00045 { 00046 return pointer(new space_networks(a_filename)); 00047 } 00048 00049 00050 bool 00051 space_networks::is_ok_name(const rcstring &input) 00052 { 00053 rcstring dummy; 00054 return is_ok_name(input, dummy); 00055 } 00056 00057 00058 bool 00059 space_networks::is_ok_name(const rcstring &input, rcstring &output) 00060 { 00061 const char *cp = input.c_str(); 00062 const char *end = cp + (input.size() < 40 ? input.size() : 40); 00063 rcstring_accumulator acc; 00064 while (cp < end) 00065 { 00066 unsigned char c = *cp++; 00067 assert(c != '\0'); 00068 switch (c) 00069 { 00070 case '0': case '1': case '2': case '3': case '4': 00071 case '5': case '6': case '7': case '8': case '9': 00072 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': 00073 case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': 00074 case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': 00075 case 'v': case 'w': case 'x': case 'y': case 'z': 00076 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': 00077 case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': 00078 case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': 00079 case 'V': case 'W': case 'X': case 'Y': case 'Z': 00080 case '_': case'-': 00081 acc.push_back(c); 00082 break; 00083 00084 default: 00085 acc.push_back('_'); 00086 break; 00087 } 00088 } 00089 output = acc.mkstr(); 00090 return (input == output); 00091 } 00092 00093 00094 space_networks::record::pointer 00095 space_networks::get(void) 00096 { 00097 for (;;) 00098 { 00099 source_location line_locn; 00100 line_t line; 00101 if (!read_one_line(line_locn, line)) 00102 return record::pointer(); 00103 if (line.size() < 2) 00104 { 00105 error 00106 ( 00107 line_locn, 00108 "too few fields (expected 2, given %ld)", 00109 (long)line.size() 00110 ); 00111 continue; 00112 } 00113 00114 // 00115 // Check the network name 00116 // 00117 rcstring rec_name = line[0]; 00118 { 00119 rcstring suggest; 00120 if (!is_ok_name(rec_name, suggest)) 00121 { 00122 error 00123 ( 00124 line_locn, 00125 "network name %s not valid, suggest %s instead", 00126 rec_name.quote_c().c_str(), 00127 suggest.quote_c().c_str() 00128 ); 00129 continue; 00130 } 00131 } 00132 00133 // 00134 // Check the network number. 00135 // 00136 rcstring rec_number = line[1]; 00137 in_addr tmp_addr; 00138 if (!inet_aton(rec_number.c_str(), &tmp_addr)) 00139 { 00140 error 00141 ( 00142 line_locn, 00143 "network number %s not valid", 00144 rec_number.quote_c().c_str() 00145 ); 00146 continue; 00147 } 00148 rcstring temp(inet_ntoa(tmp_addr)); 00149 if (temp != rec_number) 00150 { 00151 error 00152 ( 00153 line_locn, 00154 "network number %s not in correct format, use %s instead", 00155 rec_number.quote_c().c_str(), 00156 temp.quote_c().c_str() 00157 ); 00158 } 00159 rec_number = temp; 00160 unsigned long rec_number_binary = ntohl(tmp_addr.s_addr); 00161 00162 // 00163 // Make sure there are at least 2 bits not occupied by network 00164 // number, otherwise there are not bits for hosts. 00165 // 00166 if (rec_number_binary & 3) 00167 { 00168 unsigned long suggest = rec_number_binary & ~3; 00169 rcstring suggest_str = string_from_network_number(suggest); 00170 error 00171 ( 00172 line_locn, 00173 "network %s has no room for any hosts, suggest %s instead", 00174 rec_number.quote_c().c_str(), 00175 suggest_str.quote_c().c_str() 00176 ); 00177 rec_number = suggest_str; 00178 rec_number_binary = suggest; 00179 } 00180 00181 // 00182 // Check that it is class A, B or C. 00183 // Any other class is invalid. 00184 // 00185 int net_class = network_class_from_number(rec_number_binary); 00186 if (net_class > 'C') 00187 { 00188 error 00189 ( 00190 line_locn, 00191 "networks of class %c are reserved", 00192 net_class 00193 ); 00194 } 00195 00196 // 00197 // Check record ordering 00198 // 00199 if (last_addr > rec_number_binary) 00200 { 00201 error 00202 ( 00203 line_locn, 00204 "address %s out of order", 00205 rec_number.quote_c().c_str() 00206 ); 00207 explain_sequence_errors(); 00208 } 00209 last_addr = rec_number_binary; 00210 00211 // 00212 // Check the network aliases 00213 // 00214 record::aliases_t rec_aliases; 00215 for 00216 ( 00217 line_t::const_iterator it = line.begin() + 2; 00218 it != line.end(); 00219 ++it 00220 ) 00221 { 00222 rcstring suggest; 00223 if (!is_ok_name(*it, suggest)) 00224 { 00225 error 00226 ( 00227 line_locn, 00228 "network alias %s not valid, suggest %s instead", 00229 it->quote_c().c_str(), 00230 suggest.quote_c().c_str() 00231 ); 00232 } 00233 rec_aliases.push_back(*it); 00234 } 00235 00236 // 00237 // build the record, and return it to the caller. 00238 // 00239 return record::create(line_locn, rec_name, rec_number, rec_aliases); 00240 } 00241 } 00242 00243 00244 space_networks::record::~record() 00245 { 00246 } 00247 00248 00249 space_networks::record::record( 00250 const source_location &a_locn, 00251 const rcstring &a_name, 00252 const rcstring &a_number, 00253 const aliases_t &a_aliases 00254 ) : 00255 locn(a_locn), 00256 name(a_name), 00257 number(a_number), 00258 aliases(a_aliases) 00259 { 00260 } 00261 00262 00263 space_networks::record::pointer 00264 space_networks::record::create(const source_location &a_locn, 00265 const rcstring &a_name, const rcstring &a_number, 00266 const aliases_t &a_aliases) 00267 { 00268 return pointer(new record(a_locn, a_name, a_number, a_aliases)); 00269 } 00270 00271 00272 unsigned long 00273 space_networks::record::get_number_binary(void) 00274 const 00275 { 00276 return network_number_from_string(number); 00277 } 00278 00279 00280 rcstring 00281 space_networks::record::representation(void) 00282 const 00283 { 00284 rcstring_accumulator acc; 00285 acc.push_back(name); 00286 acc.push_back(' '); 00287 acc.push_back(number); 00288 for 00289 ( 00290 aliases_t::const_iterator it = aliases.begin(); 00291 it != aliases.end(); 00292 ++it 00293 ) 00294 { 00295 acc.push_back(' '); 00296 acc.push_back(*it); 00297 } 00298 return acc.mkstr(); 00299 } 00300 00301 00302 // vim: set ts=8 sw=4 et :