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