1 /* 2 3 Firewall Builder 4 5 Copyright (C) 2001 NetCitadel, LLC 6 7 Author: Vadim Zaliva lord@crocodile.org 8 9 This program is free software which we release under the GNU General Public 10 License. You may redistribute and/or modify this program under the terms 11 of that license as published by the Free Software Foundation; either 12 version 2 of the License, or (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 To get a copy of the GNU General Public License, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 22 */ 23 24 25 #ifndef __SNMP_HH_FLAG__ 26 #define __SNMP_HH_FLAG__ 27 28 #include "config.h" 29 #include "fwbuilder/libfwbuilder-config.h" 30 31 #ifdef HAVE_LIBSNMP 32 33 #include <vector> 34 35 #include "fwbuilder/FWObjectDatabase.h" 36 #include "fwbuilder/Interface.h" 37 #include "fwbuilder/BackgroundOp.h" 38 #include "fwbuilder/FWException.h" 39 #include "fwbuilder/InetAddr.h" 40 #include "fwbuilder/InterfaceData.h" 41 #include "fwbuilder/IPRoute.h" 42 #include "fwbuilder/dns.h" 43 44 #ifdef UCD_SNMP 45 #include <ucd-snmp/ucd-snmp-config.h> 46 #include <ucd-snmp/ucd-snmp-includes.h> 47 #include <ucd-snmp/snmp_api.h> 48 #endif 49 50 #ifdef NET_SNMP 51 #include <net-snmp/net-snmp-config.h> 52 #include <net-snmp/net-snmp-includes.h> 53 #endif 54 55 namespace libfwbuilder 56 { 57 58 class SNMPConnection; 59 60 class SNMPVariable 61 { 62 friend class SNMPConnection; 63 64 public: 65 ~SNMPVariable()66 virtual ~SNMPVariable() {} 67 enum 68 { 69 snmp_int = ASN_INTEGER, 70 snmp_string = ASN_OCTET_STR, 71 snmp_bits = ASN_BIT_STR, 72 snmp_counter64 = ASN_APP_COUNTER64, 73 snmp_oid = ASN_OBJECT_ID, 74 snmp_ipaddr = ASN_IPADDRESS 75 } type; 76 77 /** 78 * Returns std::string representation of this variable 79 */ 80 virtual std::string toString() = 0; 81 82 static std::string varList2String(std::vector<SNMPVariable*> &v); 83 static long varList2Int(std::vector<SNMPVariable*> &v) throw(FWException); 84 static long var2Int(SNMPVariable *var) throw(FWException); 85 static void freeVarList(std::vector<SNMPVariable*> &v); 86 87 protected: 88 89 static SNMPVariable *create(struct variable_list *v) throw(FWException); 90 }; 91 92 class SNMPVariable_Int : public SNMPVariable 93 { 94 friend class SNMPVariable; 95 96 public: 97 98 virtual std::string toString(); getIntValue()99 long getIntValue() { return value; } 100 101 protected: 102 SNMPVariable_Int(long v)103 SNMPVariable_Int(long v) { type=snmp_int; value=v; } 104 long value; 105 }; 106 107 class SNMPVariable_Bits : public SNMPVariable 108 { 109 friend class SNMPVariable; 110 111 public: 112 ~SNMPVariable_Bits()113 virtual ~SNMPVariable_Bits() 114 { 115 delete value; 116 } 117 118 virtual std::string toString(); 119 120 protected: 121 SNMPVariable_Bits(u_char * v,size_t l)122 SNMPVariable_Bits(u_char *v, size_t l) 123 { 124 type = snmp_bits; 125 if (v) 126 { 127 len=l; 128 value = (uint32_t*)(new unsigned char[len]); 129 memcpy((void*)value, v, len); 130 } else 131 { 132 value = NULL ; 133 len = 0 ; 134 } 135 } 136 137 const uint32_t *value; 138 size_t len; 139 }; 140 141 /** 142 * Unfortunately SNMP does not distinguish Netmask and InetAddr 143 * types. On our framework they are different, and thus 144 * we have to do late type conversion. 145 * (lord) 146 */ 147 class SNMPVariable_IPaddr : public SNMPVariable 148 { 149 friend class SNMPVariable; 150 151 public: 152 153 virtual std::string toString(); 154 155 virtual InetAddr getInetAddrValue() throw(FWException); 156 virtual InetAddr getNetmaskValue() throw(FWException); 157 158 protected: 159 SNMPVariable_IPaddr(u_char * v,size_t l)160 SNMPVariable_IPaddr(u_char *v, size_t l) throw(FWException) 161 { 162 type = snmp_ipaddr; 163 if(v) 164 { 165 len=l; 166 value=new unsigned char[len]; 167 memcpy((void*)value, v, len); 168 } else 169 { 170 throw FWException("Invalid data for snmp_ipaddress variable."); 171 } 172 } 173 174 const unsigned char *value; 175 size_t len; 176 }; 177 178 class SNMPVariable_String : public SNMPVariable 179 { 180 friend class SNMPVariable; 181 182 public: 183 184 virtual std::string toString(); 185 virtual const std::string toHexString(); 186 187 protected: 188 SNMPVariable_String(u_char * v,size_t l)189 SNMPVariable_String(u_char *v, size_t l) 190 { 191 type=snmp_string; 192 193 if(v) 194 { 195 for(u_char *p=v; l; p++,l--) 196 { 197 value+=*p; 198 } 199 } 200 else 201 value=""; 202 } 203 std::string value; 204 }; 205 206 class SNMPVariable_Counter64 : public SNMPVariable 207 { 208 friend class SNMPVariable; 209 210 public: 211 212 virtual std::string toString(); 213 214 protected: 215 SNMPVariable_Counter64(struct counter64 * v)216 SNMPVariable_Counter64(struct counter64 *v) 217 { 218 type=snmp_counter64; 219 if(v) 220 { 221 high=v->high; 222 low=v->low; 223 } else 224 { 225 high=low=0l; 226 } 227 } 228 unsigned long high; 229 unsigned long low; 230 }; 231 232 class SNMPVariable_OID : public SNMPVariable 233 { 234 friend class SNMPVariable; 235 236 public: 237 238 virtual std::string toString(); 239 240 protected: 241 SNMPVariable_OID(oid v)242 SNMPVariable_OID(oid v) { type=snmp_oid; value=v; } 243 oid value; 244 }; 245 246 class SNMPConnection 247 { 248 public: 249 250 SNMPConnection(const std::string &peer, const std::string &community); 251 virtual ~SNMPConnection(); 252 253 /** 254 * Optional parameter timeout is in milliseconds. 255 */ 256 void connect(int retries=SNMP_DEFAULT_RETRIES, long timeout=SNMP_DEFAULT_TIMEOUT) throw(FWException); 257 void disconnect() throw(FWException); 258 std::vector<SNMPVariable*> get(const std::string &variable) throw(FWException); 259 std::multimap<std::string, SNMPVariable*> walk(const std::string &variable) throw(FWException); 260 261 private: 262 263 std::string peer; 264 std::string community; 265 bool connected; 266 struct snmp_session *session, *session_data; 267 static bool lib_initialized; 268 }; 269 270 class SNMPQuery : public BackgroundOp 271 { 272 private: 273 274 static const char *SNMP_INTERFACE_ASTATUS; 275 static const char *SNMP_INTERFACE_OSTATUS; 276 static const char *SNMP_INTERFACE_INDEX ; 277 static const char *SNMP_INTERFACES_DESCR ; 278 static const char *SNMP_INTERFACES_PHYSA ; 279 static const char *SNMP_INTERFACES_TYPE ; 280 static const char *SNMP_ADDR_INDEX_TABLE ; 281 static const char *SNMP_NMASK_TABLE ; 282 static const char *SNMP_ADDR_TABLE ; 283 static const char *SNMP_BCAST_TABLE ; 284 285 static const char *SNMP_AT_TABLE_NET ; 286 static const char *SNMP_AT_TABLE_PHYS ; 287 288 static const char *SNMP_ROUTE_DST_TABLE ; 289 static const char *SNMP_ROUTE_NM_TABLE ; 290 static const char *SNMP_ROUTE_TYPE_TABLE ; 291 static const char *SNMP_ROUTE_IF_TABLE ; 292 static const char *SNMP_ROUTE_GW_TABLE ; 293 static const int SNMP_DIRECT_ROUTE ; 294 295 static const char *SNMP_SYSNAME ; 296 static const char *SNMP_SYSDESCR ; 297 static const char *SNMP_CONTACT ; 298 static const char *SNMP_LOCATION ; 299 300 static const char *IP_MIB_PREFIX ; 301 static const char *IP_MIB_ENTIFINDEX_PREFIX ; 302 303 static const char *RFC1213_MIB_PREFIX ; 304 static const char *RFC1213_MIB_PREFIX_IPROUTEDEST_PREFIX ; 305 306 static const char* SNMP_IP_MIB_RFC4293_V4_INDEX; 307 static const char* SNMP_IP_MIB_RFC4293_V6_INDEX; 308 static const char* SNMP_IP_MIB_RFC4293_V6_PREFIX; 309 310 std::string hostname, community; 311 std::string descr, contact, location, sysname; 312 std::map<int, InterfaceData> interfaces; 313 std::map<InetAddr, std::string> arptable; 314 std::vector<IPRoute> routes; 315 int retries; 316 long timeout; 317 318 void walkInterfaceIndexTable(Logger *logger, 319 SNMPConnection *c, 320 const char* OID, 321 std::map<long, std::list<std::string> > &addr); 322 void getAddressAndNetmask(Logger *logger, 323 SNMPConnection *c, 324 std::string adentry, 325 InetAddr **addr, 326 InetAddr **netmask); 327 328 public: 329 SNMPQuery()330 SNMPQuery() {} 331 332 SNMPQuery(std::string hostname, 333 std::string community, 334 int retries_=SNMP_DEFAULT_RETRIES, 335 long timeout_=SNMP_DEFAULT_TIMEOUT); 336 337 virtual ~SNMPQuery(); 338 339 void init(std::string hostname, 340 std::string community, 341 int retries_=SNMP_DEFAULT_RETRIES, 342 long timeout_=SNMP_DEFAULT_TIMEOUT); 343 344 void fetchArpTable(Logger *,SyncFlag *stop_program, 345 SNMPConnection *connection=NULL) throw(FWException); 346 void fetchInterfaces(Logger *,SyncFlag *stop_program, 347 SNMPConnection *connection=NULL) throw(FWException); 348 void fetchSysInfo(Logger *,SyncFlag *stop_program, 349 SNMPConnection *connection=NULL) throw(FWException); 350 void fetchAll(Logger *,SyncFlag *stop_program) throw(FWException); 351 void fetchRoutingTable(Logger *,SyncFlag *stop_program, 352 SNMPConnection *connection=NULL) throw(FWException); 353 354 std::map<int, InterfaceData>* getInterfaces(); 355 std::map<InetAddr, std::string>* getArpTable(); 356 std::vector<IPRoute>* getRoutes(); 357 358 const std::string& getSysname (); 359 const std::string& getDescr (); 360 const std::string& getContact (); 361 const std::string& getLocation (); 362 363 protected: 364 365 bool isDefault(const IPRoute &) const; 366 367 }; 368 369 class SNMP_interface_query : public SNMPQuery 370 { 371 public: 372 SNMP_interface_query()373 SNMP_interface_query() : SNMPQuery() {} 374 375 SNMP_interface_query(std::string hostname, 376 std::string community, 377 int retries_=SNMP_DEFAULT_RETRIES, 378 long timeout_=SNMP_DEFAULT_TIMEOUT) : SNMPQuery(hostname,community,retries_,timeout_)379 SNMPQuery(hostname, community, retries_, timeout_) {} 380 381 void init(std::string hostname, 382 std::string community, 383 int retries_=SNMP_DEFAULT_RETRIES, 384 long timeout_=SNMP_DEFAULT_TIMEOUT) { 385 SNMPQuery::init(hostname, community, retries_, timeout_); 386 } 387 388 virtual void run_impl(Logger *logger,SyncFlag *stop_program) throw(FWException); 389 390 }; 391 392 class SNMP_sysdesc_query : public SNMPQuery 393 { 394 public: 395 SNMP_sysdesc_query()396 SNMP_sysdesc_query() : SNMPQuery() {} 397 398 SNMP_sysdesc_query(std::string hostname, 399 std::string community, 400 int retries_=SNMP_DEFAULT_RETRIES, 401 long timeout_=SNMP_DEFAULT_TIMEOUT) : SNMPQuery(hostname,community,retries_,timeout_)402 SNMPQuery(hostname, community, retries_, timeout_) {} 403 404 void init(std::string hostname, 405 std::string community, 406 int retries_=SNMP_DEFAULT_RETRIES, 407 long timeout_=SNMP_DEFAULT_TIMEOUT) { 408 SNMPQuery::init(hostname, community, retries_, timeout_); 409 } 410 411 virtual void run_impl(Logger *logger,SyncFlag *stop_program) throw(FWException); 412 }; 413 414 class SNMP_discover_query : public SNMPQuery 415 { 416 private: 417 418 bool fetch_inerfaces; 419 420 public: 421 SNMP_discover_query()422 SNMP_discover_query() : SNMPQuery() {} SNMPQuery(hostname,community,retries_,timeout_)423 SNMP_discover_query(std::string hostname, std::string community, int retries_=SNMP_DEFAULT_RETRIES, long timeout_=SNMP_DEFAULT_TIMEOUT, bool _f=true):SNMPQuery(hostname, community, retries_, timeout_) { fetch_inerfaces=_f; } 424 425 virtual void run_impl(Logger *logger,SyncFlag *stop_program) throw(FWException); 426 }; 427 428 class CrawlerFind: public HostEnt 429 { 430 public: 431 432 CrawlerFind(); 433 virtual ~CrawlerFind(); 434 435 bool have_snmpd ; 436 std::string descr, contact, location, sysname; 437 std::map<int, InterfaceData> interfaces; 438 439 /** 440 * What physical address host had in ARP table when it was found. 441 * (optional) 442 */ 443 std::string found_phys_addr; 444 445 //set when DNS resolution succeeded. 446 bool dns_ok ; 447 }; 448 449 class SNMPCrawler : public BackgroundOp 450 { 451 private: 452 453 const std::vector<InetAddrMask> *limit_to_networks ; 454 static const InetAddrMask LOOPBACK_NET ; 455 static const InetAddrMask IPV6_LOOPBACK_NET ; 456 static const InetAddr PTP_NETMASK ; 457 458 std::map<InetAddr, std::string> queue; 459 std::map<InetAddr, CrawlerFind> found; 460 std::set<InetAddrMask> networks; 461 std::string community; 462 int snmp_retries ; 463 long snmp_timeout ; 464 bool recursive ; 465 bool do_dns ; 466 bool follow_ptp ; 467 unsigned int dns_threads ; 468 int dns_retries ; 469 int dns_timeout ; 470 471 static const int PTP_INTERFACE_TYPES[]; 472 473 protected: 474 475 bool included (const InetAddr &) const ; 476 bool alreadyseen (const InetAddr &) const ; 477 bool special (const InetAddrMask &) const ; 478 bool special (const InetAddr &) const ; 479 bool point2point (const InetAddrMask &, const InterfaceData&) const ; 480 bool point2point (const InterfaceData&) const ; 481 482 std::list<InterfaceData> guessInterface( 483 const IPRoute &r, const std::map<int, InterfaceData> &intf) const; 484 485 public: 486 487 SNMPCrawler(); 488 SNMPCrawler(const InetAddr &seed, 489 const std::string &_community, 490 bool _recursive=true, 491 bool _do_dns=true, 492 bool _follow_ptp=false, 493 unsigned int _dns_threads=10, 494 int _retries=SNMP_DEFAULT_RETRIES, 495 long _timeout=SNMP_DEFAULT_TIMEOUT, 496 int _dns_retries=RES_DFLRETRY, 497 int _dns_timeout=RES_TIMEOUT, 498 const std::vector<InetAddrMask> *include=NULL); 499 virtual ~SNMPCrawler(); 500 501 void init(const InetAddr &seed, 502 const std::string &_community, 503 bool _recursive=true, 504 bool _do_dns=true, 505 bool _follow_ptp=false, 506 unsigned int _dns_threads=10, 507 int _snmp_retries=SNMP_DEFAULT_RETRIES, 508 long _snmp_timeout=SNMP_DEFAULT_TIMEOUT, 509 int _dns_retries=RES_DFLRETRY, 510 int _dns_timeout=RES_TIMEOUT, 511 const std::vector<InetAddrMask> *include=NULL); 512 513 std::map<InetAddr, CrawlerFind> getAllIPs(); 514 std::set<InetAddrMask> getNetworks(); 515 516 virtual void run_impl(Logger *logger,SyncFlag *stop_program) 517 throw(FWException); 518 void bacresolve_results(Logger *logger,SyncFlag *stop_program) 519 throw(FWException); 520 521 }; 522 523 } 524 525 #endif 526 527 #endif 528