/* This programs use the MAC addresses retrieved by logstory and the output of snmpwalk on switches to produce a map of the swich ports. */ #include #include #include #include #include #include #include #include using namespace std; struct PORTINFO{ int others; bool up; int vlan; int speed; vector servers; PORTINFO(){ others = 0; up = false; vlan = -1; } }; struct PORTSINFO{ string id; int ifnumber; map ports; }; static const char *netmap_getstr(const string &val) { const char *ret = ""; const char *pt = val.c_str(); if (strncmp(pt,"STRING:",7)==0){ ret = pt+8; } return ret; } static bool netmap_getupdown(const string &val) { int ret = -1; const char *pt = val.c_str(); if (strncmp(pt,"INTEGER:",8)==0){ ret = strncmp(pt+9,"up",2)==0; } return ret; } static int netmap_getval(const string &val) { int ret = -1; const char *pt = val.c_str(); if (strncmp(pt,"INTEGER:",8)==0){ ret = atoi(pt+9); } return ret; } static int netmap_getgauge(const string &val) { int ret = -1; const char *pt = val.c_str(); if (strncmp(pt,"Gauge32:",8)==0){ ret = atoi(pt+9); } return ret; } /* Extract the mac address from the left part of the line (it is encoded in decimal in the OID) It returns the value in val. */ static int netmap_parsemac (const string &prefix, const string &val, string &mac) { vector tbnum; int nnum = str_splitline (prefix.c_str(),'.',tbnum); int ret = netmap_getval(val); int nums[6]; for (int u=0; u<6; u++){ nums[u] = atoi(tbnum[nnum-6+u].c_str()); } char tmp[100]; snprintf (tmp,sizeof(tmp)-1,"%02x:%02x:%02x:%02x:%02x:%02x" ,nums[0],nums[1],nums[2],nums[3],nums[4],nums[5]); #if 0 printf ("%s -> %d -> %s %s %s %s %s %s -> %s\n",line ,ret ,tbnum[nnum-6].c_str() ,tbnum[nnum-5].c_str() ,tbnum[nnum-4].c_str() ,tbnum[nnum-3].c_str() ,tbnum[nnum-2].c_str() ,tbnum[nnum-1].c_str(),mac.c_str()); #endif mac = tmp; return ret; } int main (int argc, char *argv[]) { glocal int ret = -1; glocal bool dumpmacs = false; glocal.ret = (argc,argv); setproginfo ("mapnet",VERSION,"Document the port connection of switches"); setarg (' ',"dumpmacs","Prints all the MAC addresses found in story files",glocal.dumpmacs,false); glocal map mac2serv; // mac address to server/device glocal map switches; int ret = -1; for (int i=0; i(fname,true); vector tb; int n = str_splitline (line,' ',tb); if (n == 3 && tb[2] == "-" && strncmp(tb[0].c_str(),"net/",4)==0){ vector parts; int np = str_splitline (tb[0].c_str(),'/',parts); if (np != 3){ tlmp_error ("Invalid net line in file %s: %s\n",info.filename,line); }else{ string sdev = glocal.server + "/" + parts[1]; glocal.mac2serv[parts[2]] = sdev; } } return 0; }else if (strcmp(pt,".snmp")==0){ (fname,true); static string ifnumber = "IF-MIB::ifNumber.0 "; static string id = "SNMPv2-MIB::sysDescr.0 "; static const char *port_prefix = "SNMPv2-SMI::mib-2.17.7.1.2.2.1.2"; static int len_port_prefix = strlen(port_prefix); static const char *status_prefix = "SNMPv2-SMI::mib-2.17.7.1.2.2.1.3"; static int len_status_prefix = strlen(port_prefix); static const char *speed_prefix = "IF-MIB::ifSpeed."; static int len_speed_prefix = strlen(speed_prefix); static const char *oper_prefix = "IF-MIB::ifOperStatus."; static int len_oper_prefix = strlen(oper_prefix); vector tb; int n = str_splitline (line,'=',tb); if (n == 2){ if (tb[0] == id){ glocal.switches[glocal.server].id = netmap_getstr(tb[1]); }else if (tb[0] == ifnumber){ glocal.switches[glocal.server].ifnumber = netmap_getval(tb[1]); }else if (strncmp(line,speed_prefix,len_speed_prefix)==0){ int port = atoi(line+len_speed_prefix); glocal.switches[glocal.server].ports[port].speed = netmap_getgauge(tb[1]); }else if (strncmp(line,oper_prefix,len_oper_prefix)==0){ int port = atoi(line+len_oper_prefix); glocal.switches[glocal.server].ports[port].up = netmap_getupdown(tb[1]); }else if (strncmp(line,port_prefix,len_port_prefix)==0){ string mac; int port = netmap_parsemac (tb[0],tb[1],mac); #if 0 vector tbnum; int nnum = str_splitline (tb[0].c_str(),'.',tbnum); int port = netmap_getval(tb[1]); int nums[6]; for (int u=0; u<6; u++){ nums[u] = atoi(tbnum[nnum-6+u].c_str()); } char tmp[100]; snprintf (tmp,sizeof(tmp)-1,"%02x:%02x:%02x:%02x:%02x:%02x" ,nums[0],nums[1],nums[2],nums[3],nums[4],nums[5]); #endif map::iterator it = glocal.mac2serv.find(mac); if (it == glocal.mac2serv.end()){ glocal.switches[glocal.server].ports[port].others++; }else{ glocal.switches[glocal.server].ports[port].servers.push_back(it->second); } }else if (strncmp(line,status_prefix,len_status_prefix)==0){ #if 0 string mac; int status = netmap_parsemac (tb[0],tb[1],mac); printf ("mac %s status %d\n",mac.c_str(),status); #endif } } return 0; }else{ tlmp_error ("Unknown file extension %s for file %s, can't process, aborting\n",pt,fname); exit (-1); } } } if (glocal.dumpmacs){ for (map::iterator it=glocal.mac2serv.begin(); it!=glocal.mac2serv.end(); it++){ printf ("%s -> %s\n",it->first.c_str(),it->second.c_str()); } } for (map::iterator it=glocal.switches.begin(); it != glocal.switches.end(); it++){ printf ("switch %s: %s\n",it->first.c_str(),it->second.id.c_str()); printf ("\t%d ports\n",it->second.ifnumber); for (map::iterator jit=it->second.ports.begin(); jit != it->second.ports.end(); jit++){ printf ("\t%-2d (%-5u %-4s)",jit->first,jit->second.speed/1000000,jit->second.up ? "up" : "down"); for (unsigned i=0; isecond.servers.size(); i++){ printf (" %s",jit->second.servers[i].c_str()); } if (jit->second.others > 0){ printf (" [%d]",jit->second.others); } printf ("\n"); } } return ret; return glocal.ret; }