1 /*  snmp-ups.h - NUT Meta SNMP driver (support different MIBS)
2  *
3  *  Based on NET-SNMP API (Simple Network Management Protocol V1-2)
4  *
5  *  Copyright (C)
6  *   2002-2010  Arnaud Quette <arnaud.quette@free.fr>
7  *   2002-2006	Dmitry Frolov <frolov@riss-telecom.ru>
8   *  			J.W. Hoogervorst <jeroen@hoogervorst.net>
9  *  			Niels Baggesen <niels@baggesen.net>
10  *
11  *  Sponsored by MGE UPS SYSTEMS <http://opensource.mgeups.com/>
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 2 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, write to the Free Software
25  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  *
27  */
28 
29 /* TODO list:
30 - add syscontact/location (to all mib.h or centralized?)
31 - complete shutdown
32 - add enum values to OIDs.
33 - optimize network flow by:
34   1) caching OID values (as in usbhid-ups) with timestamping and lifetime
35   2) constructing one big packet (calling snmp_add_null_var
36      for each OID request we made), instead of sending many small packets
37 - add support for registration and traps (manager mode)
38   => Issue: 1 trap listener for N snmp-ups drivers!
39 - complete mib2nut data (add all OID translation to NUT)
40 - externalize mib2nut data in .m2n files and load at driver startup using parseconf()...
41 - adjust information logging.
42 
43 - move numeric OIDs into th mib2nut tables and remove defines
44 - move mib2nut into c files (à la usbhid-ups)?
45 - add a claim function and move to usbhid-ups style for specific processing
46 - rework the flagging system
47 */
48 
49 #ifndef SNMP_UPS_H
50 #define SNMP_UPS_H
51 
52 /* FIXME: still needed?
53  * workaround for buggy Net-SNMP config */
54 #ifdef PACKAGE_BUGREPORT
55 #undef PACKAGE_BUGREPORT
56 #endif
57 
58 #ifdef PACKAGE_NAME
59 #undef PACKAGE_NAME
60 #endif
61 
62 #ifdef PACKAGE_VERSION
63 #undef PACKAGE_VERSION
64 #endif
65 
66 #ifdef PACKAGE_STRING
67 #undef PACKAGE_STRING
68 #endif
69 
70 #ifdef PACKAGE_TARNAME
71 #undef PACKAGE_TARNAME
72 #endif
73 
74 #ifdef HAVE_DMALLOC_H
75 #undef HAVE_DMALLOC_H
76 #endif
77 
78 #include <net-snmp/net-snmp-config.h>
79 #include <net-snmp/net-snmp-includes.h>
80 
81 /* Force numeric OIDs by disabling MIB loading */
82 #define DISABLE_MIB_LOADING 1
83 
84 /* Parameters default values */
85 #define DEFAULT_POLLFREQ          30   /* in seconds */
86 #define DEFAULT_NETSNMP_RETRIES   5
87 #define DEFAULT_NETSNMP_TIMEOUT   1    /* in seconds */
88 
89 /* use explicit booleans */
90 #ifndef FALSE
91 typedef enum ebool { FALSE, TRUE } bool_t;
92 #else
93 typedef int bool_t;
94 #endif
95 
96 /* Common SNMP data and lookup definitions */
97 /* special functions to interpret items:
98    take UPS answer, return string to set in INFO, max len
99 
100    NOTE: FFE means For Future Extensions
101 
102    */
103 
104 /* typedef void (*interpreter)(char *, char *, int); */
105 
106 /* for lookup between OID values and INFO_ value */
107 typedef struct {
108 	int oid_value;			/* OID value */
109 	const char *info_value;	/* INFO_* value */
110 } info_lkp_t;
111 
112 /* Structure containing info about one item that can be requested
113    from UPS and set in INFO.  If no interpreter functions is defined,
114    use sprintf with given format string.  If unit is not NONE, values
115    are converted according to the multiplier table
116 */
117 typedef struct {
118 	const char   *info_type;	/* INFO_ or CMD_ element */
119 	int           info_flags;	/* flags to set in addinfo */
120 	double        info_len;		/* length of strings if STR,
121 								 * cmd value if CMD, multiplier otherwise. */
122 	const char   *OID;			/* SNMP OID or NULL */
123 	const char   *dfl;			/* default value */
124 	unsigned long flags;		/* my flags */
125 	info_lkp_t   *oid2info;		/* lookup table between OID and NUT values */
126 	int          *setvar;		/* variable to set for SU_FLAG_SETINT */
127 } snmp_info_t;
128 
129 #define SU_FLAG_OK			(1 << 0)	/* show element to upsd. */
130 #define SU_FLAG_STATIC		(1 << 1)	/* retrieve info only once. */
131 #define SU_FLAG_ABSENT		(1 << 2)	/* data is absent in the device,
132 										 * use default value. */
133 #define SU_FLAG_STALE		(1 << 3)	/* data stale, don't try too often. */
134 #define SU_FLAG_NEGINVALID	(1 << 4)	/* Invalid if negative value */
135 #define SU_FLAG_UNIQUE		(1 << 5)	/* There can be only be one
136 						 				 * provider of this info,
137 						 				 * disable the other providers */
138 #define SU_FLAG_SETINT		(1 << 6)	/* save value */
139 #define SU_OUTLET			(1 << 7)	/* outlet template definition */
140 #define SU_CMD_OFFSET		(1 << 8)	/* Add +1 to the OID index */
141 /* Notes on outlet templates usage:
142  * - outlet.count MUST exist and MUST be declared before any outlet template
143  * Otherwise, the driver will try to determine it by itself...
144  * - the first outlet template MUST NOT be a server side variable (ie MUST have
145  *   a valid OID) in order to detect the base SNMP index (0 or 1)
146  */
147 
148 /* status string components
149  * FIXME: these should be removed, since there is no added value.
150  * Ie, this can be guessed from info->type! */
151 
152 #define SU_STATUS_PWR		(0 << 8)	/* indicates power status element */
153 #define SU_STATUS_BATT		(1 << 8)	/* indicates battery status element */
154 #define SU_STATUS_CAL		(2 << 8)	/* indicates calibration status element */
155 #define SU_STATUS_RB		(3 << 8)	/* indicates replace battery status element */
156 #define SU_STATUS_NUM_ELEM	4
157 #define SU_STATUS_INDEX(t)	(((t) >> 8) & 7)
158 
159 #define SU_OUTLET_GROUP     (1 << 10)   /* outlet group template definition */
160 
161 /* Phase specific data */
162 #define SU_PHASES		(0x3F << 12)
163 #define SU_INPHASES		(0x3 << 12)
164 #define SU_INPUT_1		(1 << 12)	/* only if 1 input phase */
165 #define SU_INPUT_3		(1 << 13)	/* only if 3 input phases */
166 #define SU_OUTPHASES	(0x3 << 14)
167 #define SU_OUTPUT_1		(1 << 14)	/* only if 1 output phase */
168 #define SU_OUTPUT_3		(1 << 15)	/* only if 3 output phases */
169 #define SU_BYPPHASES	(0x3 << 16)
170 #define SU_BYPASS_1		(1 << 16)	/* only if 1 bypass phase */
171 #define SU_BYPASS_3		(1 << 17)	/* only if 3 bypass phases */
172 /* FIXME: use input.phases and output.phases to replace this */
173 
174 
175 /* hints for su_ups_set, applicable only to rw vars */
176 #define SU_TYPE_INT			(0 << 18)	/* cast to int when setting value */
177 #define SU_TYPE_STRING		(1 << 18)	/* cast to string. FIXME: redundant with ST_FLAG_STRING */
178 #define SU_TYPE_TIME		(2 << 18)	/* cast to int */
179 #define SU_TYPE_CMD			(3 << 18)	/* instant command */
180 #define SU_TYPE(t)			((t)->flags & (7 << 18))
181 
182 #define SU_VAR_COMMUNITY	"community"
183 #define SU_VAR_VERSION		"snmp_version"
184 #define SU_VAR_RETRIES		"snmp_retries"
185 #define SU_VAR_TIMEOUT		"snmp_timeout"
186 #define SU_VAR_MIBS			"mibs"
187 #define SU_VAR_POLLFREQ		"pollfreq"
188 /* SNMP v3 related parameters */
189 #define SU_VAR_SECLEVEL		"secLevel"
190 #define SU_VAR_SECNAME		"secName"
191 #define SU_VAR_AUTHPASSWD	"authPassword"
192 #define SU_VAR_PRIVPASSWD	"privPassword"
193 #define SU_VAR_AUTHPROT		"authProtocol"
194 #define SU_VAR_PRIVPROT		"privProtocol"
195 
196 
197 #define SU_INFOSIZE		128
198 #define SU_BUFSIZE		32
199 #define SU_LARGEBUF		256
200 
201 #define SU_STALE_RETRY	10	/* retry to retrieve stale element */
202 				/* after this number of iterations. */
203 				/* FIXME: this is for *all* elements */
204 /* modes to snmp_ups_walk. */
205 #define SU_WALKMODE_INIT	0
206 #define SU_WALKMODE_UPDATE	1
207 
208 /* log spew limiters */
209 #define SU_ERR_LIMIT 10	/* start limiting after this many errors in a row  */
210 #define SU_ERR_RATE 100	/* only print every nth error once limiting starts */
211 
212 typedef struct {
213 	const char * OID;
214 	const char *status_value; /* when not NULL, set ups.status to this */
215 	const char *alarm_value;  /* when not NULL, set ups.alarm to this */
216 } alarms_info_t;
217 
218 typedef struct {
219 	const char	*mib_name;
220 	const char	*mib_version;
221 	const char	*oid_pwr_status;
222 	const char	*oid_auto_check;	/* FIXME: rename to SysOID */
223 	snmp_info_t	*snmp_info;			/* pointer to the good Snmp2Nut lookup data */
224 	const char	*sysOID;			/* OID to match against sysOID, aka MIB
225 									 * main entry point */
226 	alarms_info_t	*alarms_info;
227 } mib2nut_info_t;
228 
229 /* Common SNMP functions */
230 void nut_snmp_init(const char *type, const char *hostname);
231 void nut_snmp_cleanup(void);
232 struct snmp_pdu *nut_snmp_get(const char *OID);
233 bool_t nut_snmp_get_str(const char *OID, char *buf, size_t buf_len,
234 	info_lkp_t *oid2info);
235 bool_t nut_snmp_get_int(const char *OID, long *pval);
236 bool_t nut_snmp_set(const char *OID, char type, const char *value);
237 bool_t nut_snmp_set_str(const char *OID, const char *value);
238 bool_t nut_snmp_set_int(const char *OID, long value);
239 void nut_snmp_perror(struct snmp_session *sess,  int status,
240 	struct snmp_pdu *response, const char *fmt, ...)
241 	__attribute__ ((__format__ (__printf__, 4, 5)));
242 
243 void su_startup(void);
244 void su_cleanup(void);
245 void su_init_instcmds(void);
246 void su_setuphandlers(void); /* need to deal with external function ptr */
247 void su_setinfo(snmp_info_t *su_info_p, const char *value);
248 void su_status_set(snmp_info_t *, long value);
249 snmp_info_t *su_find_info(const char *type);
250 bool_t snmp_ups_walk(int mode);
251 bool_t su_ups_get(snmp_info_t *su_info_p);
252 
253 bool_t load_mib2nut(const char *mib);
254 
255 const char *su_find_infoval(info_lkp_t *oid2info, long value);
256 long su_find_valinfo(info_lkp_t *oid2info, const char* value);
257 
258 int su_setvar(const char *varname, const char *val);
259 int su_instcmd(const char *cmdname, const char *extradata);
260 void su_shutdown_ups(void);
261 
262 void read_mibconf(char *mib);
263 
264 extern struct snmp_session g_snmp_sess, *g_snmp_sess_p;
265 extern const char *OID_pwr_status;
266 extern int g_pwr_battery;
267 extern int pollfreq; /* polling frequency */
268 extern int input_phases, output_phases, bypass_phases;
269 
270 #endif /* SNMP_UPS_H */
271 
272