/***************************************************************************** * * STATUSWRL.C - NetSaint 3-D Network Status View * * Copyright (c) 1999-2001 Ethan Galstad (netsaint@netsaint.org) * Last Modified: 02-25-2001 * * Description: * * This CGI will dynamically create a 3-D VRML model of all hosts that are * being monitored on your network. * * License: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************************************/ #include "../common/config.h" #include "../common/locations.h" #include "../common/common.h" #include "../common/objects.h" #include "../common/statusdata.h" #include "cgiutils.h" #include "getcgi.h" #include "auth.h" #include "edata.h" extern char main_config_file[MAX_FILENAME_LENGTH]; extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char *statuswrl_include; extern hostextinfo *hostextinfo_list; extern host *host_list; #define DEFAULT_NODE_WIDTH 0.5 #define DEFAULT_HORIZONTAL_SPACING 1.0 #define DEFAULT_VERTICAL_SPACING 1.0 void calculate_world_bounds(void); void display_world(void); void write_global_vrml_data(void); void draw_host(hostextinfo *); void draw_host_links(void); void draw_host_link(host *,double,double,double,double,double,double); void document_header(void); int process_cgivars(void); char url_logo_images_path[MAX_FILENAME_LENGTH]; authdata current_authdata; float link_radius=0.016; float floor_width=0.0; float floor_depth=0.0; double min_z_coord=0.0; double min_x_coord=0.0; double min_y_coord=0.0; double max_z_coord=0.0; double max_x_coord=0.0; double max_y_coord=0.0; float vertical_spacing=DEFAULT_VERTICAL_SPACING; float horizontal_spacing=DEFAULT_HORIZONTAL_SPACING; float node_width=DEFAULT_NODE_WIDTH; float node_height=DEFAULT_NODE_WIDTH; /* should be the same as the node width */ char *host_name="all"; int show_all_hosts=TRUE; int use_textures=TRUE; int use_text=TRUE; int use_links=TRUE; int coordinates_were_specified=FALSE; /* were drawing coordinates specified with extended host info entries? */ int main(int argc, char **argv){ int result; /* get the arguments passed in the URL */ process_cgivars(); /* reset internal variables */ reset_cgi_vars(); /* read the CGI configuration file */ result=read_cgi_config_file(DEFAULT_CGI_CONFIG_FILE); if(result==ERROR){ document_header(); return ERROR; } document_header(); /* read the main configuration file */ result=read_main_config_file(main_config_file); if(result==ERROR) return ERROR; /* read all object configuration data */ result=read_all_object_configuration_data(main_config_file,READ_HOSTGROUPS|READ_CONTACTGROUPS|READ_HOSTS|READ_SERVICES); if(result==ERROR) return ERROR; /* read all status data */ result=read_all_status_data(DEFAULT_CGI_CONFIG_FILE,READ_PROGRAM_STATUS|READ_HOST_STATUS|READ_SERVICE_STATUS); if(result==ERROR){ free_memory(); return ERROR; } /* get authentication information */ get_authentication_information(¤t_authdata); /* read in extended host information */ read_extended_object_config_data(DEFAULT_CGI_CONFIG_FILE,READ_EXTENDED_HOST_INFO); /* display the 3-D VRML world... */ display_world(); /* free all allocated memory */ free_memory(); free_extended_data(); return OK; } void document_header(void){ char date_time[MAX_DATETIME_LENGTH]; time_t current_time; time_t expire_time; printf("Cache-Control: no-store\n"); printf("Pragma: no-cache\n"); time(¤t_time); get_time_string(¤t_time,date_time,sizeof(date_time),HTTP_DATE_TIME); printf("Last-Modified: %s\n",date_time); expire_time=0L; get_time_string(&expire_time,date_time,sizeof(date_time),HTTP_DATE_TIME); printf("Expires: %s\n",date_time); printf("Content-Type: x-world/x-vrml\n\n"); return; } int process_cgivars(void){ char **variables; int error=FALSE; int x; variables=getcgivars(); for(x=0;variables[x]!=NULL;x++){ /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x])>=MAX_INPUT_BUFFER-1){ x++; continue; } /* we found the host argument */ else if(!strcmp(variables[x],"host")){ x++; if(variables[x]==NULL){ error=TRUE; break; } host_name=(char *)malloc(strlen(variables[x])+1); if(host_name==NULL) host_name="all"; else strcpy(host_name,variables[x]); if(!strcmp(host_name,"all")) show_all_hosts=TRUE; else show_all_hosts=FALSE; } /* we found the no textures argument*/ else if(!strcmp(variables[x],"notextures")) use_textures=FALSE; /* we found the no text argument*/ else if(!strcmp(variables[x],"notext")) use_text=FALSE; /* we found the no links argument*/ else if(!strcmp(variables[x],"nolinks")) use_links=FALSE; } return error; } /* top-level VRML world generation... */ void display_world(void){ hostextinfo *temp_hostextinfo; /* get the url we will use to grab the logo images... */ snprintf(url_logo_images_path,sizeof(url_logo_images_path),"%slogos/",url_images_path); url_logo_images_path[sizeof(url_logo_images_path)-1]='\x0'; /* calculate world bounds */ calculate_world_bounds(); /* get the floor dimensions */ if(max_x_coord>0) floor_width=(float)(max_x_coord-min_x_coord)+(node_width*2); else floor_width=(float)(max_x_coord+min_x_coord)+(node_width*2); if(max_z_coord>0) floor_depth=(float)(max_z_coord-min_z_coord)+(node_height*2); else floor_depth=(float)(max_z_coord+min_z_coord)+(node_height*2); /* write global VRML data */ write_global_vrml_data(); /* no coordinates were specified, so display warning message */ if(coordinates_were_specified==FALSE){ printf("\n"); printf("Transform{\n"); printf("translation 0.0 0.0 0.0\n"); printf("children[\n"); printf("Billboard{\n"); printf("children[\n"); printf("Shape{\n"); printf("appearance Appearance {\n"); printf("material Material {\n"); printf("diffuseColor 1 0 0\n"); printf("}\n"); printf("}\n"); printf("geometry Text {\n"); printf("string [ \"You have not supplied any host drawing coordinates.\", \"Read the FAQs for more information on this.\" ]\n"); printf("fontStyle FontStyle {\n"); printf("size 0.3\n"); printf("justify \"MIDDLE\"\n"); printf("}\n"); printf("}\n"); printf("}\n"); printf("]\n"); printf("}\n"); printf("]\n"); printf("}\n"); } /* coordinates were specified... */ else{ /* draw all hosts */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next) draw_host(temp_hostextinfo); /* draw host links */ draw_host_links(); } return; } /******************************************************************/ /********************* CALCULATION FUNCTIONS **********************/ /******************************************************************/ /* calculate world dimensions */ void calculate_world_bounds(void){ hostextinfo *temp_hostextinfo; min_x_coord=0.0; min_y_coord=0.0; min_z_coord=0.0; max_x_coord=0.0; max_y_coord=0.0; max_z_coord=0.0; /* check all extended host entries */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ if(temp_hostextinfo->have_3d_coords==FALSE){ temp_hostextinfo->should_be_drawn=FALSE; continue; } if(temp_hostextinfo->x_3d < min_x_coord) min_x_coord=temp_hostextinfo->x_3d; else if(temp_hostextinfo->x_3d > max_x_coord) max_x_coord=temp_hostextinfo->x_3d; if(temp_hostextinfo->y_3d < min_y_coord) min_y_coord=temp_hostextinfo->y_3d; else if(temp_hostextinfo->y_3d > max_y_coord) max_y_coord=temp_hostextinfo->y_3d; if(temp_hostextinfo->z_3d < min_z_coord) min_x_coord=temp_hostextinfo->z_3d; else if(temp_hostextinfo->z_3d > max_z_coord) max_z_coord=temp_hostextinfo->z_3d; coordinates_were_specified=TRUE; } /* no drawing coordinates were specified */ if(coordinates_were_specified==FALSE){ min_x_coord=150.0; max_x_coord=150.0; min_y_coord=0.0; max_y_coord=100.0; min_z_coord=0.0; max_z_coord=10.0; } return; } /******************************************************************/ /*********************** DRAWING FUNCTIONS ************************/ /******************************************************************/ /* write global VRML data */ void write_global_vrml_data(void){ hostextinfo *temp_hostextinfo; /* write VRML code header */ printf("#VRML V2.0 utf8\n"); /* write world information */ printf("\n"); printf("WorldInfo{\n"); printf("title \"NetSaint 3-D Network Status View\"\n"); printf("info [\"Copyright (c) 1999 Ethan Galstad\"\n"); printf("\"netsaint@netsaint.org\"]\n"); printf("}\n"); /* write background color */ printf("\n"); printf("Background{\n"); printf("skyColor 0.2 0.2 0.2\n"); printf("}\n"); /* write fog information */ /* printf("\n"); printf("Fog{\n"); printf("color 0.2 0.2 0.2\n"); printf("fogType \"EXPONENTIAL\"\n"); printf("visibilityRange %2.2f\n",(floor_depth>floor_width)?(float)(floor_depth*2.0)+20.0:(float)(floor_width*2.0)+20.0); printf("}\n"); */ /* initial viewpoint */ printf("\n"); printf("Viewpoint{\n"); if(show_all_hosts==TRUE) printf("position 0.0 0.0 10.0\n"); else{ temp_hostextinfo=find_hostextinfo(host_name); if(temp_hostextinfo==NULL || temp_hostextinfo->have_3d_coords==FALSE) printf("position 0.0 0.0 10.0\n"); else printf("position %2.3f %2.3f %2.3f\n",temp_hostextinfo->x_3d,temp_hostextinfo->y_3d,temp_hostextinfo->z_3d+2.0); } printf("fieldOfView 0.78\n"); printf("description \"Entry Point\"\n"); printf("}\n"); /* host node prototype */ printf("\n"); printf("PROTO HostNode [\n"); printf("field SFColor emissive_color 0.2 0.9 0.2\n"); printf("field SFColor diffuse_color 0.2 0.9 0.2\n"); if(use_textures==TRUE) printf("field MFString texture_image \"\"\n"); printf("]\n"); printf("{\n"); printf("Shape{\n"); printf("appearance Appearance{\n"); printf("material Material{\n"); printf("emissiveColor IS emissive_color\n"); printf("diffuseColor IS diffuse_color\n"); printf("transparency 0.2\n"); printf("}\n"); if(use_textures==TRUE){ printf("texture ImageTexture{\n"); printf("url IS texture_image\n"); printf("}\n"); } printf("}\n"); printf("geometry Box{\n"); printf("size %2.2f %2.2f %2.2f\n",node_width,node_width,node_width); printf("}\n"); printf("}\n"); printf("}\n"); /* host text prototype */ printf("PROTO HostText[\n"); printf("field MFString the_text [\"\"]\n"); printf("field SFColor font_color 0.6 0.6 0.6"); printf("]\n"); printf("{\n"); printf("Billboard{\n"); printf("children[\n"); printf("Shape{\n"); printf("appearance Appearance {\n"); printf("material Material {\n"); printf("diffuseColor IS font_color\n"); printf("}\n"); printf("}\n"); printf("geometry Text {\n"); printf("string IS the_text\n"); printf("fontStyle FontStyle {\n"); printf("size 0.1\n"); printf("justify \"MIDDLE\"\n"); printf("}\n"); printf("}\n"); printf("}\n"); printf("]\n"); printf("}\n"); printf("}\n"); /* include user-defined world */ if(statuswrl_include!=NULL && coordinates_were_specified==TRUE){ printf("\n"); printf("Inline{\n"); printf("url \"%s%s\"\n",url_html_path,statuswrl_include); printf("}\n"); } return; } /* draws a host */ void draw_host(hostextinfo *temp_hostextinfo){ host *temp_host; hoststatus *temp_hoststatus=NULL; char state_string[16]=""; double x, y, z; if(temp_hostextinfo==NULL) return; /* make sure we have the coordinates */ if(temp_hostextinfo->have_3d_coords==FALSE) return; else{ x=temp_hostextinfo->x_3d; y=temp_hostextinfo->y_3d; z=temp_hostextinfo->z_3d; } /* find the config entry for this host */ temp_host=find_host(temp_hostextinfo->host_name,NULL); if(temp_host==NULL) return; /* see if user is authorized to view this host */ if(is_authorized_for_host(temp_host,¤t_authdata)==FALSE) return; printf("\n"); printf("Anchor{\n"); printf("children[\n"); printf("Transform {\n"); printf("translation %2.2f %2.2f %2.2f\n",x,y,z); printf("children [\n"); temp_hoststatus=find_hoststatus(temp_host->name); if(temp_hoststatus==NULL) printf("HostNode{\nemissive_color 0.2 0.2 0.2\ndiffuse_color 0.2 0.2 0.2\n"); else if(temp_hoststatus->status==HOST_UP) printf("HostNode{\n"); else printf("HostNode{\nemissive_color 0.9 0.6 0.6\ndiffuse_color 0.9 0.6 0.6\n"); if(temp_hostextinfo->vrml_image!=NULL && use_textures==TRUE) printf("texture_image \"%s%s\"\n",url_logo_images_path,temp_hostextinfo->vrml_image); printf("}\n"); printf("]\n"); printf("}\n"); printf("]\n"); printf("description \"View status details for host '%s' (%s)\"\n",temp_host->name,temp_host->alias); printf("url \"%s?host=%s\"\n",STATUS_CGI,temp_host->name); printf("}\n"); /* draw status text */ if(use_text==TRUE){ printf("\n"); printf("Transform{\n"); printf("translation %2.3f %2.3f %2.3f\n",x,y+DEFAULT_NODE_WIDTH,z); printf("children[\n"); printf("HostText{\n"); if(temp_hoststatus!=NULL){ if(temp_hoststatus->status==HOST_UP) printf("font_color 0 0.8 0\n"); else if(temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE) printf("font_color 1 0 0\n"); } printf("the_text [\"%s\", \"%s\", ",temp_host->name,temp_host->alias); if(temp_hoststatus==NULL) strcpy(state_string,"UNKNOWN"); else{ if(temp_hoststatus->status==HOST_DOWN) strcpy(state_string,"DOWN"); else if(temp_hoststatus->status==HOST_UNREACHABLE) strcpy(state_string,"UNREACHABLE"); else if(temp_hoststatus->status==HOST_PENDING) strcpy(state_string,"PENDING"); else strcpy(state_string,"UP"); } printf("\"%s\"]\n",state_string); printf("}\n"); printf("]\n"); printf("}\n"); } return; } /* draw links between hosts */ void draw_host_links(void){ hostextinfo *child_hostextinfo; hostextinfo *parent_hostextinfo; host *parent_host; host *child_host; if(use_links==FALSE) return; for(child_hostextinfo=hostextinfo_list;child_hostextinfo!=NULL;child_hostextinfo=child_hostextinfo->next){ if(child_hostextinfo->have_3d_coords==FALSE) continue; child_host=find_host(child_hostextinfo->host_name,NULL); if(child_host==NULL) continue; /* check authorization */ if(is_authorized_for_host(child_host,¤t_authdata)==FALSE) continue; /* draw a link from this host to all of its parent hosts */ for(parent_host=host_list;parent_host!=NULL;parent_host=parent_host->next){ if(is_host_immediate_child_of_host(child_host,parent_host)==TRUE){ parent_hostextinfo=find_hostextinfo(parent_host->name); if(parent_hostextinfo==NULL) continue; if(parent_hostextinfo->have_3d_coords==FALSE) continue; /* check authorization */ if(is_authorized_for_host(parent_host,¤t_authdata)==FALSE) continue; /* draw the link between the child and parent hosts */ draw_host_link(parent_host,parent_hostextinfo->x_3d,parent_hostextinfo->y_3d,parent_hostextinfo->z_3d,child_hostextinfo->x_3d,child_hostextinfo->y_3d,child_hostextinfo->z_3d); } } } return; } /* draws a link from a parent host to a child host */ void draw_host_link(host *hst,double x0, double y0, double z0, double x1, double y1, double z1){ if(hst==NULL) return; printf("\n"); printf("# Host '%s' LINK\n",hst->name); printf("Shape{\n"); printf("appearance DEF MATslategrey_0_ Appearance {\n"); printf("material Material {\n"); printf("diffuseColor 0.6 0.6 0.6\n"); printf("ambientIntensity 0.5\n"); printf("emissiveColor 0.6 0.6 0.6\n"); printf("}\n"); printf("}\n"); printf("geometry IndexedLineSet{\n"); printf("coord Coordinate{\n"); printf("point [ %2.3f %2.3f %2.3f, %2.3f %2.3f %2.3f ]\n",x0,y0,z0,x1,y1,z1); printf("}\n"); printf("coordIndex [ 0,1,-1 ]\n"); printf("}\n"); printf("}\n"); return; }