~iheino+ub/+junk/nut-upsconf-docfix

« back to all changes in this revision

Viewing changes to tools/nut-scanner/scan_ipmi.c

  • Committer: Tuomas Heino
  • Author(s): Laurent Bigonville
  • Date: 2014-04-22 20:46:12 UTC
  • Revision ID: iheino+ub@cc.hut.fi-20140422204612-1x2gh3nkezfsdao4
Tags: upstream-2.7.2
ImportĀ upstreamĀ versionĀ 2.7.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* scan_ipmi.c: detect NUT supported Power Supply Units
 
2
 * 
 
3
 *  Copyright (C)
 
4
 *    2011 - 2012  Arnaud Quette <arnaud.quette@free.fr>
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
19
 */
 
20
#include "common.h"
 
21
#include "nut-scan.h"
 
22
 
 
23
#ifdef WITH_IPMI
 
24
#include "upsclient.h"
 
25
#include <freeipmi/freeipmi.h>
 
26
#include <stdio.h>
 
27
#include <string.h>
 
28
#include <ltdl.h>
 
29
 
 
30
#define NUT_IPMI_DRV_NAME       "nut-ipmipsu"
 
31
 
 
32
/* IPMI defines */
 
33
/* 5 seconds for establishing an IPMI connection */
 
34
#define IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT                     5000
 
35
#define IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT      250
 
36
 
 
37
/* dynamic link library stuff */
 
38
static char * libname = "libfreeipmi";
 
39
static lt_dlhandle dl_handle = NULL;
 
40
static const char *dl_error = NULL;
 
41
 
 
42
#ifdef HAVE_FREEIPMI_11X_12X
 
43
  /* Functions symbols remapping */
 
44
  #define IPMI_FRU_CLOSE_DEVICE_ID                     "ipmi_fru_close_device_id"
 
45
  #define IPMI_FRU_CTX_DESTROY                         "ipmi_fru_ctx_destroy"
 
46
  #define IPMI_FRU_CTX_CREATE                          "ipmi_fru_ctx_create"
 
47
  #define IPMI_FRU_CTX_SET_FLAGS                       "ipmi_fru_ctx_set_flags"
 
48
  #define IPMI_FRU_OPEN_DEVICE_ID                      "ipmi_fru_open_device_id"
 
49
  #define IPMI_FRU_CTX_ERRORMSG                        "ipmi_fru_ctx_errormsg"
 
50
  #define IPMI_FRU_READ_DATA_AREA                      "ipmi_fru_read_data_area"
 
51
  #define IPMI_FRU_PARSE_NEXT                          "ipmi_fru_next"
 
52
  typedef ipmi_fru_ctx_t ipmi_fru_parse_ctx_t;
 
53
  typedef ipmi_sdr_ctx_t ipmi_sdr_cache_ctx_t;
 
54
  /* Functions remapping */
 
55
  static void (*nut_ipmi_sdr_ctx_destroy) (ipmi_sdr_ctx_t ctx);
 
56
#else /* HAVE_FREEIPMI_11X_12X */
 
57
  #define IPMI_FRU_AREA_SIZE_MAX                                   IPMI_FRU_PARSE_AREA_SIZE_MAX
 
58
  #define IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS                      IPMI_FRU_PARSE_FLAGS_SKIP_CHECKSUM_CHECKS
 
59
  #define IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION  IPMI_FRU_PARSE_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION
 
60
  /* Functions symbols remapping */
 
61
  #define IPMI_FRU_CLOSE_DEVICE_ID                     "ipmi_fru_parse_close_device_id"
 
62
  #define IPMI_FRU_CTX_DESTROY                         "ipmi_fru_parse_ctx_destroy"
 
63
  #define IPMI_FRU_CTX_CREATE                            "ipmi_fru_parse_ctx_create"
 
64
  #define IPMI_FRU_CTX_SET_FLAGS                         "ipmi_fru_parse_ctx_set_flags"
 
65
  #define IPMI_FRU_OPEN_DEVICE_ID                        "ipmi_fru_parse_open_device_id"
 
66
  #define IPMI_FRU_CTX_ERRORMSG                          "ipmi_fru_parse_ctx_errormsg"
 
67
  #define IPMI_FRU_READ_DATA_AREA                        "ipmi_fru_parse_read_data_area"
 
68
  #define IPMI_FRU_PARSE_NEXT                            "ipmi_fru_parse_next"
 
69
  /* Functions remapping */
 
70
  static void (*nut_ipmi_sdr_cache_ctx_destroy) (ipmi_sdr_cache_ctx_t ctx);
 
71
  static void (*nut_ipmi_sdr_parse_ctx_destroy) (ipmi_sdr_parse_ctx_t ctx);
 
72
#endif /* HAVE_FREEIPMI_11X_12X */
 
73
 
 
74
 
 
75
static int (*nut_ipmi_fru_close_device_id) (ipmi_fru_parse_ctx_t ctx);
 
76
static void (*nut_ipmi_fru_ctx_destroy) (ipmi_fru_parse_ctx_t ctx);
 
77
static ipmi_fru_parse_ctx_t (*nut_ipmi_fru_ctx_create) (ipmi_ctx_t ipmi_ctx);
 
78
static int (*nut_ipmi_fru_ctx_set_flags) (ipmi_fru_parse_ctx_t ctx, unsigned int flags);
 
79
static int (*nut_ipmi_fru_open_device_id) (ipmi_fru_parse_ctx_t ctx, uint8_t fru_device_id);
 
80
static char * (*nut_ipmi_fru_ctx_errormsg) (ipmi_fru_parse_ctx_t ctx);
 
81
static int (*nut_ipmi_fru_read_data_area) (ipmi_fru_parse_ctx_t ctx,
 
82
                                   unsigned int *area_type,
 
83
                                   unsigned int *area_length,
 
84
                                   void *areabuf,
 
85
                                   unsigned int areabuflen);
 
86
static int (*nut_ipmi_fru_next) (ipmi_fru_parse_ctx_t ctx);
 
87
static ipmi_ctx_t (*nut_ipmi_ctx_create) (void);
 
88
static int (*nut_ipmi_ctx_find_inband) (ipmi_ctx_t ctx,
 
89
                          ipmi_driver_type_t *driver_type,
 
90
                          int disable_auto_probe,
 
91
                          uint16_t driver_address,
 
92
                          uint8_t register_spacing,
 
93
                          const char *driver_device,
 
94
                          unsigned int workaround_flags,
 
95
                          unsigned int flags);
 
96
static int (*nut_ipmi_ctx_open_outofband) (ipmi_ctx_t ctx,
 
97
                             const char *hostname,
 
98
                             const char *username,
 
99
                             const char *password,
 
100
                             uint8_t authentication_type,
 
101
                             uint8_t privilege_level,
 
102
                             unsigned int session_timeout,
 
103
                             unsigned int retransmission_timeout,
 
104
                             unsigned int workaround_flags,
 
105
                             unsigned int flags);
 
106
static int (*nut_ipmi_ctx_errnum) (ipmi_ctx_t ctx);
 
107
static char * (*nut_ipmi_ctx_errormsg) (ipmi_ctx_t ctx);
 
108
static int (*nut_ipmi_ctx_close) (ipmi_ctx_t ctx);
 
109
static void (*nut_ipmi_ctx_destroy) (ipmi_ctx_t ctx);
 
110
 
 
111
/* Internal functions */
 
112
static nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * sec);
 
113
 
 
114
/* Return 0 on error */
 
115
int nutscan_load_ipmi_library()
 
116
{
 
117
        if( dl_handle != NULL ) {
 
118
                /* if previous init failed */
 
119
                if( dl_handle == (void *)1 ) {
 
120
                        return 0;
 
121
                }
 
122
                /* init has already been done */
 
123
                return 1;
 
124
        }
 
125
 
 
126
        if( lt_dlinit() != 0 ) {
 
127
                fprintf(stderr, "Error initializing lt_init\n");
 
128
                return 0;
 
129
        }
 
130
 
 
131
        dl_handle = lt_dlopenext(libname);
 
132
        if (!dl_handle) {
 
133
                dl_error = lt_dlerror();
 
134
                goto err;
 
135
        }
 
136
 
 
137
        /* Clear any existing error */
 
138
        lt_dlerror();
 
139
 
 
140
        *(void **) (&nut_ipmi_fru_close_device_id) = lt_dlsym(dl_handle, IPMI_FRU_CLOSE_DEVICE_ID);
 
141
        if ((dl_error = lt_dlerror()) != NULL)  {
 
142
                        goto err;
 
143
        }
 
144
 
 
145
        *(void **) (&nut_ipmi_fru_ctx_destroy) = lt_dlsym(dl_handle, IPMI_FRU_CTX_DESTROY);
 
146
        if ((dl_error = lt_dlerror()) != NULL)  {
 
147
                        goto err;
 
148
        }
 
149
 
 
150
#ifdef HAVE_FREEIPMI_11X_12X
 
151
 
 
152
        *(void **) (&nut_ipmi_sdr_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_ctx_destroy");
 
153
        if ((dl_error = lt_dlerror()) != NULL)  {
 
154
                        goto err;
 
155
        }
 
156
 
 
157
#else /* HAVE_FREEIPMI_11X_12X */
 
158
 
 
159
        *(void **) (&nut_ipmi_sdr_cache_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_cache_ctx_destroy");
 
160
        if ((dl_error = lt_dlerror()) != NULL)  {
 
161
                        goto err;
 
162
        }
 
163
 
 
164
        *(void **) (&nut_ipmi_sdr_parse_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_parse_ctx_destroy");
 
165
        if ((dl_error = lt_dlerror()) != NULL)  {
 
166
                        goto err;
 
167
        }
 
168
#endif /* HAVE_FREEIPMI_11X_12X */
 
169
 
 
170
        *(void **) (&nut_ipmi_fru_ctx_create) = lt_dlsym(dl_handle, IPMI_FRU_CTX_CREATE);
 
171
        if ((dl_error = lt_dlerror()) != NULL)  {
 
172
                        goto err;
 
173
        }
 
174
 
 
175
        *(void **) (&nut_ipmi_fru_ctx_set_flags) = lt_dlsym(dl_handle, IPMI_FRU_CTX_SET_FLAGS);
 
176
        if ((dl_error = lt_dlerror()) != NULL)  {
 
177
                        goto err;
 
178
        }
 
179
 
 
180
        *(void **) (&nut_ipmi_fru_open_device_id) = lt_dlsym(dl_handle, IPMI_FRU_OPEN_DEVICE_ID);
 
181
        if ((dl_error = lt_dlerror()) != NULL)  {
 
182
                        goto err;
 
183
        }
 
184
 
 
185
        *(void **) (&nut_ipmi_fru_ctx_errormsg) = lt_dlsym(dl_handle, IPMI_FRU_CTX_ERRORMSG);
 
186
        if ((dl_error = lt_dlerror()) != NULL)  {
 
187
                        goto err;
 
188
        }
 
189
 
 
190
        *(void **) (&nut_ipmi_fru_read_data_area) = lt_dlsym(dl_handle, IPMI_FRU_READ_DATA_AREA);
 
191
        if ((dl_error = lt_dlerror()) != NULL)  {
 
192
                        goto err;
 
193
        }
 
194
 
 
195
        *(void **) (&nut_ipmi_fru_next) = lt_dlsym(dl_handle, IPMI_FRU_PARSE_NEXT);
 
196
        if ((dl_error = lt_dlerror()) != NULL)  {
 
197
                        goto err;
 
198
        }
 
199
 
 
200
        *(void **) (&nut_ipmi_ctx_create) = lt_dlsym(dl_handle, "ipmi_ctx_create");
 
201
        if ((dl_error = lt_dlerror()) != NULL)  {
 
202
                        goto err;
 
203
        }
 
204
 
 
205
        *(void **) (&nut_ipmi_ctx_find_inband) = lt_dlsym(dl_handle, "ipmi_ctx_find_inband");
 
206
        if ((dl_error = lt_dlerror()) != NULL)  {
 
207
                        goto err;
 
208
        }
 
209
 
 
210
        *(void **) (&nut_ipmi_ctx_open_outofband) = lt_dlsym(dl_handle, "ipmi_ctx_open_outofband");
 
211
        if ((dl_error = lt_dlerror()) != NULL)  {
 
212
                        goto err;
 
213
        }
 
214
 
 
215
        *(void **) (&nut_ipmi_ctx_errnum) = lt_dlsym(dl_handle, "ipmi_ctx_errnum");
 
216
        if ((dl_error = lt_dlerror()) != NULL)  {
 
217
                        goto err;
 
218
        }
 
219
 
 
220
        *(void **) (&nut_ipmi_ctx_errormsg) = lt_dlsym(dl_handle, "ipmi_ctx_errormsg");
 
221
        if ((dl_error = lt_dlerror()) != NULL)  {
 
222
                        goto err;
 
223
        }
 
224
 
 
225
        *(void **) (&nut_ipmi_ctx_close) = lt_dlsym(dl_handle, "ipmi_ctx_close");
 
226
        if ((dl_error = lt_dlerror()) != NULL)  {
 
227
                        goto err;
 
228
        }
 
229
 
 
230
        *(void **) (&nut_ipmi_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_ctx_destroy");
 
231
        if ((dl_error = lt_dlerror()) != NULL)  {
 
232
                        goto err;
 
233
        }
 
234
 
 
235
        return 1;
 
236
err:
 
237
        fprintf(stderr, "Cannot load IPMI library (%s) : %s. IPMI search disabled.\n", libname, dl_error);
 
238
        dl_handle = (void *)1;
 
239
        lt_dlexit();
 
240
        return 0;
 
241
}
 
242
/* end of dynamic link library stuff */
 
243
 
 
244
/* Cleanup IPMI contexts */
 
245
#ifdef HAVE_FREEIPMI_11X_12X
 
246
static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx,
 
247
                                                                 ipmi_sdr_ctx_t sdr_ctx)
 
248
#else /* HAVE_FREEIPMI_11X_12X */
 
249
static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx,
 
250
                                                                 ipmi_sdr_cache_ctx_t sdr_cache_ctx,
 
251
                                                                 ipmi_sdr_parse_ctx_t sdr_parse_ctx)
 
252
#endif /* HAVE_FREEIPMI_11X_12X */
 
253
{
 
254
        if (fru_parse_ctx) {
 
255
                (*nut_ipmi_fru_close_device_id) (fru_parse_ctx);
 
256
                (*nut_ipmi_fru_ctx_destroy) (fru_parse_ctx);
 
257
        }
 
258
 
 
259
#ifdef HAVE_FREEIPMI_11X_12X
 
260
 
 
261
        if (sdr_ctx) {
 
262
                (*nut_ipmi_sdr_ctx_destroy) (sdr_ctx);
 
263
        }
 
264
 
 
265
#else /* HAVE_FREEIPMI_11X_12X */
 
266
 
 
267
        if (sdr_cache_ctx) {
 
268
                (*nut_ipmi_sdr_cache_ctx_destroy) (sdr_cache_ctx);
 
269
        }
 
270
 
 
271
        if (sdr_parse_ctx) {
 
272
                (*nut_ipmi_sdr_parse_ctx_destroy) (sdr_parse_ctx);
 
273
        }
 
274
 
 
275
#endif /* HAVE_FREEIPMI_11X_12X */
 
276
}
 
277
 
 
278
/* Return 1 if supported, 0 otherwise */
 
279
int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id)
 
280
{
 
281
        int ret = -1;
 
282
        unsigned int area_type = 0;
 
283
        unsigned int area_length = 0;
 
284
        uint8_t areabuf[IPMI_FRU_AREA_SIZE_MAX+1];
 
285
        ipmi_fru_parse_ctx_t fru_parse_ctx = NULL;
 
286
#ifdef HAVE_FREEIPMI_11X_12X
 
287
        ipmi_sdr_ctx_t sdr_ctx = NULL;
 
288
#else /* HAVE_FREEIPMI_11X_12X */
 
289
        ipmi_sdr_cache_ctx_t sdr_cache_ctx = NULL;
 
290
        ipmi_sdr_parse_ctx_t sdr_parse_ctx = NULL;
 
291
#endif /* HAVE_FREEIPMI_11X_12X */
 
292
 
 
293
        /* Parse FRU information */
 
294
        if (!(fru_parse_ctx = (*nut_ipmi_fru_ctx_create) (ipmi_ctx)))
 
295
        {
 
296
                fprintf(stderr, "Error with %s(): %s\n", IPMI_FRU_CTX_CREATE, (*nut_ipmi_ctx_errormsg)(ipmi_ctx));
 
297
                return 0;
 
298
        }
 
299
 
 
300
        /* lots of motherboards calculate checksums incorrectly */
 
301
        if ((*nut_ipmi_fru_ctx_set_flags) (fru_parse_ctx, IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS) < 0)
 
302
        {
 
303
#ifdef HAVE_FREEIPMI_11X_12X
 
304
                nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
 
305
#else
 
306
                nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
 
307
#endif /* HAVE_FREEIPMI_11X_12X */
 
308
                return 0;
 
309
        }
 
310
 
 
311
        if ((*nut_ipmi_fru_open_device_id) (fru_parse_ctx, ipmi_id) < 0)
 
312
        {
 
313
#ifdef HAVE_FREEIPMI_11X_12X
 
314
                nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
 
315
#else
 
316
                nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
 
317
#endif /* HAVE_FREEIPMI_11X_12X */
 
318
                return 0;
 
319
        }
 
320
 
 
321
        do
 
322
        {
 
323
                /* clear fields */
 
324
                area_type = 0;
 
325
                area_length = 0;
 
326
                memset (areabuf, '\0', IPMI_FRU_AREA_SIZE_MAX + 1);
 
327
 
 
328
                /* parse FRU buffer */
 
329
                if ((*nut_ipmi_fru_read_data_area) (fru_parse_ctx,
 
330
                                                                                        &area_type,
 
331
                                                                                        &area_length,
 
332
                                                                                        areabuf,
 
333
                                                                                        IPMI_FRU_AREA_SIZE_MAX) < 0)
 
334
                {
 
335
#ifdef HAVE_FREEIPMI_11X_12X
 
336
                        nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
 
337
#else
 
338
                        nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
 
339
#endif /* HAVE_FREEIPMI_11X_12X */
 
340
                        return 0;
 
341
                }
 
342
 
 
343
                if (area_length)
 
344
                {
 
345
                        if (area_type == IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION)
 
346
                        {
 
347
                                /* Found a POWER_SUPPLY record */
 
348
#ifdef HAVE_FREEIPMI_11X_12X
 
349
                                nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
 
350
#else
 
351
                                nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
 
352
#endif /* HAVE_FREEIPMI_11X_12X */
 
353
                                return 1;
 
354
                        }
 
355
                }
 
356
        } while ((ret = (*nut_ipmi_fru_next) (fru_parse_ctx)) == 1);
 
357
 
 
358
        /* No need for further errors checking */
 
359
#ifdef HAVE_FREEIPMI_11X_12X
 
360
        nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx);
 
361
#else
 
362
        nut_freeipmi_cleanup(fru_parse_ctx, sdr_cache_ctx, sdr_parse_ctx);
 
363
#endif /* HAVE_FREEIPMI_11X_12X */
 
364
        return 0;
 
365
}
 
366
 
 
367
/* Check for IPMI support on a specific (local or remote) system
 
368
 * Return NULL on error, or a valid nutscan_device_t otherwise */
 
369
nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * ipmi_sec)
 
370
{
 
371
        ipmi_ctx_t ipmi_ctx = NULL;
 
372
        nutscan_device_t * nut_dev = NULL;
 
373
        nutscan_device_t * current_nut_dev = NULL;
 
374
        int ret = -1;
 
375
        int ipmi_id = 0;
 
376
        char port_id[64];
 
377
 
 
378
        if( !nutscan_avail_ipmi ) {
 
379
                return NULL;
 
380
        }
 
381
 
 
382
        /* Initialize the FreeIPMI library. */
 
383
        if (!(ipmi_ctx = (*nut_ipmi_ctx_create) ()))
 
384
        {
 
385
                /* we have to force cleanup, since exit handler is not yet installed */
 
386
                fprintf(stderr, "ipmi_ctx_create\n");
 
387
                return NULL;
 
388
        }
 
389
 
 
390
        /* Are we scanning locally, or over the network? */
 
391
        if (IPaddr == NULL) 
 
392
        {
 
393
                /* FIXME: we need root right to access local IPMI!
 
394
                if (!ipmi_is_root ()) {
 
395
                        fprintf(stderr, "IPMI scan: %s\n", ipmi_ctx_strerror (IPMI_ERR_PERMISSION));
 
396
                } */
 
397
 
 
398
                if ((ret = (*nut_ipmi_ctx_find_inband) (ipmi_ctx,
 
399
                                        NULL,
 
400
                                        0, /* don't disable auto-probe */
 
401
                                        0,
 
402
                                        0,
 
403
                                        NULL,
 
404
                                        0, /* workaround flags, none by default */
 
405
                                        0  /* flags */
 
406
                                        )) < 0)
 
407
                {
 
408
                        fprintf(stderr, "ipmi_ctx_find_inband: %s\n",
 
409
                                (*nut_ipmi_ctx_errormsg) (ipmi_ctx));
 
410
                        return NULL;
 
411
                }
 
412
                if (!ret)
 
413
                {
 
414
                        /* No local IPMI device detected */
 
415
                        return NULL;
 
416
                }
 
417
        }
 
418
        else {
 
419
 
 
420
#if 0
 
421
                if (ipmi_sec->ipmi_version == IPMI_2_0) {
 
422
 
 
423
                        /* FIXME: need processing?!
 
424
                         * int parse_kg (void *out, unsigned int outlen, const char *in)
 
425
                         * if ((rv = parse_kg (common_cmd_args_config->k_g, IPMI_MAX_K_G_LENGTH + 1, data->string)) < 0)
 
426
                         * {
 
427
                         *      fprintf (stderr, "Config File Error: k_g input formatted incorrectly\n");
 
428
                         *      exit (EXIT_FAILURE);
 
429
                         * }*/
 
430
                        if ((ret = (*nut_ipmi_ctx_open_outofband_2_0) (ipmi_ctx,
 
431
                                                                                                                        IPaddr,
 
432
                                                                                                                        ipmi_sec->username,
 
433
                                                                                                                        ipmi_sec->password,
 
434
                                                                                                                        ipmi_sec->K_g_BMC_key,
 
435
???                                                                                                                     (ipmi_sec->K_g_BMC_key) ? config->k_g_len : 0,
 
436
                                                                                                                        ipmi_sec->privilege_level,
 
437
                                                                                                                        ipmi_sec->cipher_suite_id,
 
438
                                                                                                                        IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT,
 
439
                                                                                                                        IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT,
 
440
                                                                                                                        ipmi_dev->workaround_flags,
 
441
                                                                                                                        flags) < 0)
 
442
                        {
 
443
                                IPMI_MONITORING_DEBUG (("ipmi_ctx_open_outofband_2_0: %s", ipmi_ctx_errormsg (c->ipmi_ctx)));
 
444
                                if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_USERNAME_INVALID)
 
445
                                        c->errnum = IPMI_MONITORING_ERR_USERNAME_INVALID;
 
446
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID)
 
447
                                        c->errnum = IPMI_MONITORING_ERR_PASSWORD_INVALID;
 
448
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT)
 
449
                                        c->errnum = IPMI_MONITORING_ERR_PRIVILEGE_LEVEL_INSUFFICIENT;
 
450
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED)
 
451
                                        c->errnum = IPMI_MONITORING_ERR_PRIVILEGEL_LEVEL_CANNOT_BE_OBTAINED;
 
452
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_K_G_INVALID)
 
453
                                        c->errnum = IPMI_MONITORING_ERR_K_G_INVALID;
 
454
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_CIPHER_SUITE_ID_UNAVAILABLE)
 
455
                                        c->errnum = IPMI_MONITORING_ERR_CIPHER_SUITE_ID_UNAVAILABLE;
 
456
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT)
 
457
                                        c->errnum = IPMI_MONITORING_ERR_PASSWORD_VERIFICATION_TIMEOUT;
 
458
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_IPMI_2_0_UNAVAILABLE)
 
459
                                        c->errnum = IPMI_MONITORING_ERR_IPMI_2_0_UNAVAILABLE;
 
460
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT)
 
461
                                        c->errnum = IPMI_MONITORING_ERR_CONNECTION_TIMEOUT;
 
462
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_SESSION_TIMEOUT)
 
463
                                        c->errnum = IPMI_MONITORING_ERR_SESSION_TIMEOUT;
 
464
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE
 
465
                                           || ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_IPMI_ERROR)
 
466
                                        c->errnum = IPMI_MONITORING_ERR_IPMI_ERROR;
 
467
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_BMC_BUSY)
 
468
                                        c->errnum = IPMI_MONITORING_ERR_BMC_BUSY;
 
469
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_OUT_OF_MEMORY)
 
470
                                        c->errnum = IPMI_MONITORING_ERR_OUT_OF_MEMORY;
 
471
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_HOSTNAME_INVALID)
 
472
                                        c->errnum = IPMI_MONITORING_ERR_HOSTNAME_INVALID;
 
473
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PARAMETERS)
 
474
                                        c->errnum = IPMI_MONITORING_ERR_PARAMETERS;
 
475
                                else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_SYSTEM_ERROR)
 
476
                                        c->errnum = IPMI_MONITORING_ERR_SYSTEM_ERROR;
 
477
                                else
 
478
                                        c->errnum = IPMI_MONITORING_ERR_INTERNAL_ERROR;
 
479
                                return (-1);
 
480
                        }
 
481
                }
 
482
                else { /* Not IPMI 2.0 */
 
483
 
 
484
#endif /* 0 */
 
485
 
 
486
                /* Fall back to IPMI 1.5 */
 
487
                if ((ret = (*nut_ipmi_ctx_open_outofband) (ipmi_ctx,
 
488
                                                IPaddr,
 
489
                                                ipmi_sec->username,
 
490
                                                ipmi_sec->password,
 
491
                                                ipmi_sec->authentication_type,
 
492
                                                ipmi_sec->privilege_level,
 
493
                                                IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT,
 
494
                                                IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT,
 
495
                                                ipmi_sec->workaround_flags,
 
496
                                                IPMI_FLAGS_DEFAULT
 
497
                                                )) < 0)
 
498
                {
 
499
                        /* No IPMI device detected on this host!
 
500
                        if ((*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_USERNAME_INVALID
 
501
                          || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID
 
502
                          || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT
 
503
                          || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED
 
504
                          || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_AUTHENTICATION_TYPE_UNAVAILABLE
 
505
                          || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT
 
506
                          || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_HOSTNAME_INVALID
 
507
                          || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT) { */
 
508
 
 
509
                                /* FIXME: don't log timeout errors */
 
510
                                fprintf(stderr, "nut_ipmi_ctx_open_outofband: %s\n",
 
511
                                        (*nut_ipmi_ctx_errormsg) (ipmi_ctx));
 
512
                                return NULL;
 
513
                        /*}*/
 
514
                }
 
515
        }
 
516
 
 
517
        /* Loop through all possible components */
 
518
        for (ipmi_id = 0 ; ipmi_id <= IPMI_FRU_DEVICE_ID_MAX ; ipmi_id++) {
 
519
 
 
520
                if (is_ipmi_device_supported(ipmi_ctx, ipmi_id)) {
 
521
 
 
522
                        if ( (nut_dev = nutscan_new_device()) == NULL ) {
 
523
                                fprintf(stderr,"Memory allocation error\n");
 
524
                                nutscan_free_device(current_nut_dev);
 
525
                                break;
 
526
                        }
 
527
 
 
528
                        /* Fill the device structure (sufficient with driver and port) */
 
529
                        nut_dev->type = TYPE_IPMI;
 
530
                        nut_dev->driver = strdup(NUT_IPMI_DRV_NAME);
 
531
                        if (IPaddr == NULL) {
 
532
                                sprintf(port_id, "id%x", ipmi_id);
 
533
                        }
 
534
                        else {
 
535
                                /* FIXME: also check against "localhost" and its IPv{4,6} */
 
536
                                sprintf(port_id, "id%x@%s", ipmi_id, IPaddr);
 
537
                        }
 
538
                        nut_dev->port = strdup(port_id);
 
539
                        /* FIXME: also dump device.serial?
 
540
                         * using drivers/libfreeipmi_get_board_info() */
 
541
                        
 
542
                        current_nut_dev = nutscan_add_device_to_device(
 
543
                                                        current_nut_dev,
 
544
                                                        nut_dev);
 
545
 
 
546
                        memset (port_id, 0, sizeof(port_id));
 
547
                }
 
548
        }
 
549
 
 
550
        /* Final cleanup */
 
551
        if (ipmi_ctx) {
 
552
                (*nut_ipmi_ctx_close) (ipmi_ctx);
 
553
                (*nut_ipmi_ctx_destroy) (ipmi_ctx);
 
554
        }
 
555
 
 
556
        return current_nut_dev;
 
557
}
 
558
 
 
559
/* General IPMI scan entry point: scan 1 to n devices, local or remote,
 
560
 * for IPMI support
 
561
 * Return NULL on error, or a valid nutscan_device_t otherwise */
 
562
nutscan_device_t * nutscan_scan_ipmi(const char * start_ip, const char * stop_ip, nutscan_ipmi_t * sec)
 
563
{
 
564
        nutscan_ip_iter_t ip;
 
565
        char * ip_str = NULL;
 
566
        nutscan_ipmi_t * tmp_sec;
 
567
        nutscan_device_t * nut_dev = NULL;
 
568
        nutscan_device_t * current_nut_dev = NULL;
 
569
 
 
570
        if( !nutscan_avail_ipmi ) {
 
571
                return NULL;
 
572
        }
 
573
 
 
574
 
 
575
        /* Are we scanning locally, or through the network? */
 
576
        if (start_ip == NULL) 
 
577
        {
 
578
                /* Local PSU scan */
 
579
                current_nut_dev = nutscan_scan_ipmi_device(NULL, NULL);
 
580
        }
 
581
        else {
 
582
                ip_str = nutscan_ip_iter_init(&ip, start_ip, stop_ip);
 
583
 
 
584
                while(ip_str != NULL) {
 
585
                        tmp_sec = malloc(sizeof(nutscan_ipmi_t));
 
586
                        memcpy(tmp_sec, sec, sizeof(nutscan_ipmi_t));
 
587
 
 
588
                        if ((current_nut_dev = nutscan_scan_ipmi_device(ip_str, tmp_sec)) != NULL) {
 
589
                                /* Store the positive result */
 
590
                                current_nut_dev = nutscan_add_device_to_device(current_nut_dev, nut_dev);
 
591
                        }
 
592
                        /* Prepare the next iteration */
 
593
                        ip_str = nutscan_ip_iter_inc(&ip);
 
594
                };
 
595
        }
 
596
 
 
597
        return nutscan_rewind_device(current_nut_dev);
 
598
}
 
599
#else /* WITH_IPMI */
 
600
/* stub function */
 
601
nutscan_device_t *  nutscan_scan_ipmi(const char * startIP, const char * stopIP, nutscan_ipmi_t * sec)
 
602
{
 
603
        return NULL;
 
604
}
 
605
#endif /* WITH_IPMI */