1 /* ------------------------------------------------
2 Copyright 2014 AT&T Intellectual Property
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
7 http://www.apache.org/licenses/LICENSE-2.0
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ------------------------------------------- */
24 extern string hostname; // namne of the current host
26 static string int_to_string(int i){
29 sprintf(tmpstr,"%d",i);
35 // Interface for the res parser
36 extern int ResParserparse(void);
37 extern FILE *ResParserin;
38 extern int ResParserdebug;
39 void ResParser_setfileinput(FILE *f);
40 void ResParser_setstringinput(char *s);
41 extern int flex_res_lineno;
43 resparse_data *rpd_ptr;
44 vector<string> res_val_vec, res_attr_vec;
47 ///////////////////////////////////////
50 void iface_t::add_property(const char *name, const char *att){
52 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
53 vals[nm].push_back(att);
56 void iface_t::add_property(const char *name, const char **atts){
59 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
60 if(atts[0]) val = atts[1];
62 vals[nm].push_back(val);
65 void iface_t::add_property(const char *name, vector<string> &val_vec){
68 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
69 if(val_vec.size()) val = val_vec[0];
71 vals[nm].push_back(val);
74 int iface_t::finalize(string &errs){
75 string tag ="ERROR in interface starting at line "+int_to_string(lineno)+", ";
77 if(vals.count("name") == 0){
78 e += "Name not specified. ";
80 if(vals["name"].size() > 1){
81 e+="More than one name specified. ";
86 errs += tag + e + "\n";
92 string iface_t::to_string(){
94 string ret = "Interface "+vals["name"][0]+":\n";
95 map<string, vector<string> >::iterator svmi;
96 for(svmi=vals.begin();svmi!=vals.end();++svmi){
97 ret += "\t"+(*svmi).first + " : ";
98 for(i=0;i<((*svmi).second).size();++i){
100 ret += (*svmi).second[i];
108 string iface_t::get_name(){
109 if(vals.count("name") == 0) return (string)"";
110 return (vals["name"])[0];
113 string iface_t::get_host(){
114 if(vals.count("host") == 0) return (string)"";
115 return (vals["host"])[0];
119 bool iface_t::eval_Contains(string prop, string val){
120 // convert to lowercase
121 std::transform(prop.begin(), prop.end(), prop.begin(), (int(*)(int))std::tolower);
123 if(vals.count(prop) == 0) return false;
125 for(i=0;i<vals[prop].size();++i){
126 if((vals[prop])[i] == val) return true;
131 bool iface_t::eval_Equals(string prop, string val){
132 // convert to lowercase
133 std::transform(prop.begin(), prop.end(), prop.begin(), (int(*)(int))std::tolower);
134 if(vals.count(prop) == 0) return false;
135 if(vals[prop].size() != 1) return false;
137 for(i=0;i<vals[prop].size();++i){
138 if((vals[prop])[i] == val) return true;
143 bool iface_t::eval_Exists(string prop){
144 // convert to lowercase
145 std::transform(prop.begin(), prop.end(), prop.begin(), (int(*)(int))std::tolower);
146 if(vals.count(prop) == 0) return false;
151 ///////////////////////////////////////
152 /// gs_host_t methods
154 void gs_host_t::add_property(const char *name, const char *att){
156 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
157 vals[nm].push_back(att);
160 void gs_host_t::add_property(const char *name, vector<string> &val_vec){
163 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
164 if(val_vec.size()) val = val_vec[0];
166 vals[nm].push_back(val);
169 int gs_host_t::finalize(string &errs){
170 string tag ="ERROR in host starting at line "+int_to_string(lineno)+", ";
172 if(vals.count("name") == 0){
173 e += "Name not specified. ";
175 if(vals["name"].size() > 1){
176 e+="More than one name specified. ";
181 errs += tag + e + "\n";
188 /////////////////////////////////////////////////////////////////
189 /// reparse_data methods
191 int resparse_data::finalize_iface(string &errs){
192 int ret = curr_iface->finalize(errs);
197 curr_host->add_interface(curr_iface);
203 int resparse_data::finalize_host(string &errs){
204 int ret = curr_host->finalize(errs);
210 string host = curr_host->vals["name"][0];
211 // in non-distributed case we will ignore all other hosts
212 if (!distributed_mode) {
214 if (host != hostname)
217 // we need to exclude failed hosts
218 if (!use_live_hosts_file || live_hosts->count(hostname)) {
219 hosts.push_back(curr_host);
221 // push the host name to every interface
222 curr_host->propagate_name();
224 // add all interfaces into interface list
225 for(int i=0;i<curr_host->ifaces.size();i++)
226 ifaces.push_back(curr_host->ifaces[i]);
232 string resparse_data::to_string(){
235 for(i=0;i<ifaces.size();i++)
236 ret += ifaces[i]->to_string();
240 vector<pair<string,string> > resparse_data::find_ifaces(predicate_t *pr){
242 vector<pair<string,string> > ret;
243 for(i=0;i<ifaces.size();++i){
244 if(this->eval_pred(i,pr)){
245 pair<string,string> p(ifaces[i]->get_host(), ifaces[i]->get_name());
253 vector<int> resparse_data::get_ifaces_by_Name(std::string host_name, std::string if_name){
256 for(i=0;i<ifaces.size();++i){
257 if(ifaces[i]->get_host() == host_name && ifaces[i]->get_name() == if_name)
265 bool resparse_data::eval_pred(int i, predicate_t *pr){
266 vector<scalarexp_t *> op_list;
269 switch(pr->get_operator_type()){
271 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, IN not supported. %d\n",
272 pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );
275 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, IN not supported. %d\n",
276 pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );
279 if(pr->get_op() == "NOT")
280 return(! eval_pred(i, pr->get_left_pr()) );
281 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, unknown unary pred operator %s.\n",
282 pr->get_lineno(), pr->get_charno(), pr->get_op().c_str() );
285 if(pr->get_op() == "AND"){
286 if(! eval_pred(i, pr->get_left_pr()) ) return false;
287 return eval_pred(i, pr->get_right_pr()) ;
289 if(pr->get_op() == "OR"){
290 if( eval_pred(i, pr->get_left_pr()) ) return true;
291 return eval_pred(i, pr->get_right_pr()) ;
293 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, unknown binary pred operator %s.\n",
294 pr->get_lineno(), pr->get_charno(), pr->get_op().c_str() );
297 op_list = pr->get_op_list();
298 if(op_list[0]->get_operator_type() != SE_PARAM){
299 fprintf(stderr,"INTERNAL ERROR : ifq parameters are supposed to be of type SE_PARAM, found %s at position 0\n",op_list[0]->get_op().c_str());
302 prop=op_list[0]->get_op();
304 if(op_list.size() > 1){
305 if(op_list[1]->get_operator_type() != SE_PARAM){
306 fprintf(stderr,"INTERNAL ERROR : ifq parameters are supposed to be of type SE_PARAM, found %s at position 1\n",op_list[0]->get_op().c_str());
309 val=op_list[1]->get_op();
313 if(pr->get_op() == "Contains"){
314 if(op_list.size() != 2){
315 fprintf(stderr,"INTERNAL ERROR : predicate Contains expects 2 parameters, received %lu\n",op_list.size());
318 return ifaces[i]->eval_Contains(prop,val);
321 if(pr->get_op() == "Equals"){
322 if(op_list.size() != 2){
323 fprintf(stderr,"INTERNAL ERROR : predicate Equals expects 2 parameters, received %lu\n",op_list.size());
326 return ifaces[i]->eval_Equals(prop,val);
329 if(pr->get_op() == "Exists"){
330 if(op_list.size() != 1){
331 fprintf(stderr,"INTERNAL ERROR : predicate Exists expects 1 parameter, received %lu\n",op_list.size());
334 return ifaces[i]->eval_Exists(prop);
337 fprintf(stderr,"INTERNAL ERROR : Unknown predicate %s in reparse_date::eval_pred.\n",pr->get_op().c_str());
341 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, unknown predicate operator type %d\n",
342 pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );
351 ///////////////////////////////////////////
352 /// XML parser callbacks for parsing interface resources
354 void startElement(void *userData, const char *name, const char **atts) {
357 resparse_data *rpd = (resparse_data *)userData;
358 rpd->level.push_back(name);
360 if(rpd->level.size() == 1 && rpd->level[0] == "Resources")
361 rpd->in_Resources = true;
363 if(rpd->in_Resources && rpd->level.size() == 2 && rpd->level[1] == "Interface"){
364 // rpd->new_iface(XML_GetCurrentLineNumber(rpd->parser));
366 rpd->in_Iface = true;
369 if(rpd->in_Iface && rpd->level.size() == 3){
370 rpd->add_property(name, atts);
374 // for(i=0;i<rpd->level.size();++i) printf("%s, ",rpd->level[i].c_str());
378 void startElement(void *userData, const char *name, vector<string> &attr_vec, vector<string> &val_vec){
381 resparse_data *rpd = (resparse_data *)userData;
382 rpd->level.push_back(name);
384 if(rpd->level.size() == 1 && rpd->level[0] == "Resources")
385 rpd->in_Resources = true;
387 if(rpd->in_Resources && rpd->level.size() == 2 && rpd->level[1] == "Host"){
388 // rpd->new_iface(XML_GetCurrentLineNumber(rpd->parser));
390 rpd->new_host(flex_res_lineno);
391 for (int i = 0; i < attr_vec.size(); ++i)
392 rpd->curr_host->add_property(attr_vec[i].c_str(), val_vec[i].c_str());
396 if(rpd->in_Host && rpd->level.size() == 3) {
397 if ( rpd->level[2] == "Interface"){
398 // rpd->new_iface(XML_GetCurrentLineNumber(rpd->parser));
399 rpd->new_iface(flex_res_lineno);
400 for (int i = 0; i < attr_vec.size(); ++i)
401 rpd->add_property(attr_vec[i].c_str(), val_vec[i].c_str());
402 rpd->in_Iface = true;
404 rpd->curr_host->add_property(name, val_vec);
408 if(rpd->in_Iface && rpd->level.size() == 4){
409 rpd->add_property(name, val_vec);
413 // for(i=0;i<rpd->level.size();++i) printf("%s, ",rpd->level[i].c_str());
418 void endElement(void *userData, const char *name) {
419 resparse_data *rpd = (resparse_data *)userData;
421 if(rpd->in_Iface && rpd->level.size() == 3){
423 int err = rpd->finalize_iface(err_msg);
424 if(err) fprintf(stderr,"%s\n",err_msg.c_str());
425 } else if (rpd->in_Host && rpd->level.size() == 2) {
427 int err = rpd->finalize_host(err_msg);
428 if(err) fprintf(stderr,"%s\n",err_msg.c_str());
431 rpd->level.pop_back();
435 // Interface to ifq definition lexer and parser ...
437 extern int IfqParserparse(void);
438 extern FILE *IfqParserin;
439 extern int IfqParserdebug;
440 void IfqParser_setfileinput(FILE *f);
441 void IfqParser_setstringinput(char *s);
444 fta_parse_t *ifq_parse_result;
446 int ifq_t::load_ifaces(string fname, bool use_live_hosts_file, bool disributed_mode, string &err){
447 char buf[1000], errbuf[1000];
448 // XML_Parser parser = XML_ParserCreate(NULL);
454 // open the list of failed hosts
455 set<string> live_hosts;
456 if (use_live_hosts_file) {
457 FILE* live_hosts_file = fopen("live_hosts.txt", "r");
458 if (!live_hosts_file) {
459 err="Error, can't open live_hosts.txt, error is ";
460 err+=strerror(errno); err+="\n";
464 while(fgets(buf, 1000, live_hosts_file)) {
465 char* host = strtok(buf, " \t\n\r"); // strip the line
467 live_hosts.insert(host);
470 fclose(live_hosts_file);
475 // IfqParserdebug = 1;
477 FILE *resfile = fopen(fname.c_str(),"r");
479 err="Error, can't open "+fname+", error is ";
480 err+=strerror(errno); err+="\n";
484 // rpd = new resparse_data(parser);
485 rpd = new resparse_data(use_live_hosts_file, &live_hosts, disributed_mode);
488 ResParser_setfileinput(resfile);
489 if(ResParserparse()){
490 err = "ERROR, interface query parse failed.\n";
495 XML_SetUserData(parser, rpd);
496 XML_SetElementHandler(parser, startElement, endElement);
498 size_t len = fread(buf, 1, sizeof(buf), resfile);
499 done = len < sizeof(buf);
500 if (!XML_Parse(parser, buf, len, done)) {
503 XML_ErrorString(XML_GetErrorCode(parser)),
504 XML_GetCurrentLineNumber(parser));
509 XML_ParserFree(parser);
512 err = "Interface resource parse failed, exiting.\n";
522 int ifq_t::load_ifqs(string fname, string &err){
526 FILE *qfile = fopen(fname.c_str(),"r");
528 sprintf(err_buf, "ERROR, can't open %s, error is %s\n",fname.c_str(),strerror(errno));
533 ifq_parse_result = new fta_parse_t();
534 IfqParser_setfileinput(qfile);
535 if(IfqParserparse()){
536 err = "ERROR, interface query parse failed.\n";
540 vector<table_exp_t *> ifqlist = ifq_parse_result->parse_tree_list->qlist;
543 for(i=0;i<ifqlist.size();++i){
544 string nm = ifqlist[i]->nmap["name"];
545 if(ifq_map.count(nm)){
546 err += "ERROR, Duplicate interface query "+nm+"\n";
549 ifq_map[nm] = ifqlist[i]->wh;
558 vector<pair<string,string> > ifq_t::eval(string qname, int &err_no){
559 vector<pair<string,string> > retval;
562 if(ifq_map.count(qname) == 0){
571 return rpd->find_ifaces(ifq_map[qname]);
575 vector<string> ifq_t::get_iface_vals(string host_name, string basic_if_name, string property, int &err_no, string &err_str){
576 vector<string> retval;
579 char *cdat = strdup(basic_if_name.c_str());
581 string virtual_iface = "0";
582 string iface_name = basic_if_name;
583 for(pos=strlen(cdat)-1;pos>=0 && isdigit(cdat[pos]);--pos);
584 if(pos>0 && cdat[pos] == 'X' && pos<=strlen(cdat)-2){
586 virtual_iface = cdat+pos+1;
591 if(property == "virtual_interface_id"){
592 retval.push_back(virtual_iface);
598 err_no = 1; err_str = "interface resource parse failed.";
602 vector<int> ifi = rpd->get_ifaces_by_Name(host_name, iface_name);
604 err_no = 1; err_str="interface not found.";
608 err_no = 1; err_str="multiple interfaces found.";
612 return rpd->get_property(ifi[0], property);
616 vector<string> ifq_t::get_iface_properties(string host_name, string basic_if_name, int &err_no, string &err_str){
617 vector<string> retval;
620 char *cdat = strdup(basic_if_name.c_str());
622 string virtual_iface = "0";
623 string iface_name = basic_if_name;
624 for(pos=strlen(cdat)-1;pos>=0 && isdigit(cdat[pos]);--pos);
625 if(pos>0 && cdat[pos] == 'X' && pos<=strlen(cdat)-2){
627 virtual_iface = cdat+pos+1;
633 err_no = 1; err_str = "interface resource parse failed.";
637 vector<int> ifi = rpd->get_ifaces_by_Name(host_name, iface_name);
639 err_no = 1; err_str="interface not found.";
643 err_no = 1; err_str="multiple interfaces found.";
647 return rpd->get_properties(ifi[0]);